Author: Jonas Bilinkevicius
How to remove the client edge of a MDI parent form
Answer:
Apparently, in Delphi 4, the logic for the MDI client window edge was changed. If
you have the source for Forms.pas, you can see the MDI client window procedure
(TCustomForm.ClientWndProc) explicitly changes the client edge on a certain
mysterious message ($3F) by calling ShowMDIClientEdge.
Unfortunately, simply replacing the client window procedure doesn't work well. I've
finally been able to work out a hack, that replaces the client window procedure,
and changes the form style on the fly. This makes sure the form's FormStyle
property is not fsMDIForm when the client window procedure wants to call
ShowMDIClientEdge, which it does only if the FormStyle property is fsMDIForm. When
the FormStyle property changes, however, the window is destroyed (to be recreated
when needed). To prevent this, I've overriden the DestroyWnd method.
The following unit is my MDI main form, displayed without a sunken edge:
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 StdCtrls;
8
9 type
10 TForm1 = class(TForm)
11 procedure FormCreate(Sender: TObject);
12 procedure FormDestroy(Sender: TObject);
13 private
14 { Private declarations }
15 FUpdating: Boolean;
16 OldWndProc: TFarProc;
17 NewWndProc: Pointer;
18 procedure ClientWndProc(var message: TMessage);
19 protected
20 procedure DestroyWnd; override;
21 public
22 { Public declarations }
23 end;
24
25 var
26 Form1: TForm1;
27
28 implementation
29
30 {$R *.DFM}
31
32 procedure TForm1.ClientWndProc(var message: TMessage);
33
34 procedure DefProc;
35 begin
36 with message do
37 Result := CallWindowProc(OldWndProc, ClientHandle, Msg, wParam, lParam);
38 end;
39
40 begin
41 if message.Msg = $3F then
42 begin
43 FUpdating := True;
44 FormStyle := fsNormal;
45 DefProc;
46 FormStyle := fsMDIForm;
47 FUpdating := False;
48 end
49 else
50 DefProc;
51 end;
52
53 procedure TForm1.DestroyWnd;
54 begin
55 if not FUpdating then
56 inherited DestroyWnd;
57 end;
58
59 procedure TForm1.FormCreate(Sender: TObject);
60 begin
61 OldWndProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
62 NewWndProc := MakeObjectInstance(ClientWndProc);
63 SetWindowLong(ClientHandle, GWL_WNDPROC, Longint(NewWndProc));
64 SetWindowLong(ClientHandle, GWL_EXSTYLE, GetWindowLong(ClientHandle,
65 GWL_EXSTYLE) and not WS_EX_CLIENTEDGE);
66 SetWindowPos(ClientHandle, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE
67 or SWP_NOSIZE or SWP_NOZORDER or SWP_FRAMECHANGED);
68 end;
69
70 procedure TForm1.FormDestroy(Sender: TObject);
71 begin
72 if Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC)) = NewWndProc then
73 begin
74 SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(OldWndProc));
75 FreeObjectInstance(NewWndProc);
76 end;
77 end;
78
79 end.
|