在使用MDI介面时,有时候需要在MDI客户窗口中显示一些图形或软件封面,使得软件介面不会显得空旷,软件功能也能一目了然。然而在Delphi中并没有直接给出这些接口。在MDI窗体中放入任何图形控件在运行时都不能显示。因此需要对MDI窗体进行改造。 申明: 本方案仅针对MDI窗体,如果应用在非MDI窗体中,后果难说,你自已试试吧。 记住,窗体的FormStyle属性要设置为:fsMDIForm。 解决方案: 1. 在MDI主窗体中无法接收到MDI客户窗口的消息(Message),因此,需要自已定义客户窗口的处理过程(Window Procedure),并接管MDI客户窗口(需在重载的CreateWnd过程中实现): procedure TMDIForm.CreateWnd; begin inherited; FNewWndProc := MakeObjectInstance(ClientWndProc); FOldWndProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC)); SetWindowLong(ClientHandle, GWL_WNDPROC, Longint(FNewWndProc)); end; 其中,ClientWndProc为自定义的窗口过程: procedure ClientWndProc(var Message: TMessage); FOldWndProc用来存放旧的窗口过程的指针。 2. 实现自已的客户窗口过程: procedure TMDIForm.ClientWndProc(var Message: TMessage); var R: TRECT;
procedure Default; begin with Message do Result := CallWindowProc(FOldWndProc, ClientHandle, Msg, wParam, lParam); end; var PS: TPaintStruct; begin R := ClientRect; case Message.Msg of WM_PAINT: begin BeginPaint(ClientHandle,PS); try Canvas.Lock; try Canvas.Handle := PS.hdc; try Paint; if ControlCount > 0 then PaintControls(PS.hdc,Controls[0]); finally Canvas.Handle := 0; end; finally Canvas.Unlock; end; finally EndPaint(ClientHandle,PS); end; end; WM_ERASEBKGND: begin DrawBG(TWMEraseBkGnd(Message).DC); Message.Result := 1; end; WM_VSCROLL,WM_HSCROLL: begin InvalidateRect(ClientHandle,@R,true); Default; end; WM_SIZE: begin InvalidateRect(ClientHandle,@R,true); Default; end; else Default; end; end; 上面的DrawBG是用于画窗口背景的。 3. 实现窗口背景。 为了可以让继承者也能定义自已的背景,故此过程说明为virtual: protected procedure DrawBG(DC: HDC); virtual; 在此,DrawBG过程只是简单的填充窗口背景: procedure TMDIForm.DrawBG(DC: HDC); begin if Brush.Color <> clNone then FillRect(DC, ClientRect, Brush.Handle); end; 4. 综上所述,总结TMDIFrom类定义如下: TMDIForm = class(TForm) private FOldWndProc: TFarProc; FNewWndProc: TFarProc; procedure ClientWndProc(var Message: TMessage); protected procedure DrawBG(DC: HDC);virtual; procedure CreateWnd; override; end; 5. 经过以上改造后,就可以在DrawBG中画出指定的背景(需直接调用Windows 的GUI接口),或者直接使用图形控件,或者实现窗体的OnPaint事件,MDI窗口从此多姿多彩。
|
请发表评论