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.
			
           |