2010. december 6., hétfő
How to remove the client edge of a MDI parent form
Problem/Question/Abstract:
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:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FUpdating: Boolean;
OldWndProc: TFarProc;
NewWndProc: Pointer;
procedure ClientWndProc(var Message: TMessage);
protected
procedure DestroyWnd; override;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ClientWndProc(var Message: TMessage);
procedure DefProc;
begin
with Message do
Result := CallWindowProc(OldWndProc, ClientHandle, Msg, wParam, lParam);
end;
begin
if Message.Msg = $3F then
begin
FUpdating := True;
FormStyle := fsNormal;
DefProc;
FormStyle := fsMDIForm;
FUpdating := False;
end
else
DefProc;
end;
procedure TForm1.DestroyWnd;
begin
if not FUpdating then
inherited DestroyWnd;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
OldWndProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
NewWndProc := MakeObjectInstance(ClientWndProc);
SetWindowLong(ClientHandle, GWL_WNDPROC, Longint(NewWndProc));
SetWindowLong(ClientHandle, GWL_EXSTYLE, GetWindowLong(ClientHandle,
GWL_EXSTYLE) and not WS_EX_CLIENTEDGE);
SetWindowPos(ClientHandle, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE
or SWP_NOSIZE or SWP_NOZORDER or SWP_FRAMECHANGED);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC)) = NewWndProc then
begin
SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(OldWndProc));
FreeObjectInstance(NewWndProc);
end;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése