如何重载MDI程序中客户窗口的消息处理过程?

来源:互联网 发布:js 控制style.display 编辑:程序博客网 时间:2024/04/30 22:02

MDI应用程序分三个部分:框架窗口(Frame Window),客户窗口(Client Window),子窗口(Child Window) ,在VCL中,这个Client Window已经被封装了,你不能直接使用消息映射或者Application.OnMessage来得到发送到Client Window的消息,所以须在启动时使用SetWindowLog更改客户窗口的默认消息处理过程,在程序退出时恢复.

.h
...

private:
void __fastcall ClientProc(TMessage &msg);
Pointer ClientObjInstance;
LONG OldClientProc;
...

.cpp
...
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    ClientObjInstance = MakeObjectInstance(ClientProc);
    OldClientProc = SetWindowLong(ClientHandle,GWL_WNDPROC,(long)ClientObjInstance);
}
void __fastcall TForm1::FormClose(TObject *Sender)
{
    SetWindowLong(ClientHandle,GWL_WNDPROC,OldClientProc);
    FreeObjectInstance(ClientObjInstance);
}
//下面函数用来讲子窗体列表加入到ListBox1中,记得在最后调用默认的ClientWindow处理过程
void __fastcall TForm1::ClientProc(TMessage &msg)
{
    if (msg.Msg == WM_PARENTNOTIFY) {
        if (msg.WParamLo == WM_CREATE) {
            TForm *r = (TForm *)(FindControl((HWND)msg.LParam));
            ListBox1->Items->AddObject(r->Caption,r);
        }
        else if (msg.WParamLo == WM_DESTROY) {
            TForm *r = (TForm *)(FindControl((HWND)msg.LParam));
            ListBox1->Items->Delete(ListBox1->Items->IndexOfObject(r));
        }
    }
    msg.Result = CallWindowProc((FARPROC)OldClientProc,
                            ClientHandle,msg.Msg,msg.WParam,msg.LParam);

}
//点击ListBox激活相应子窗体
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
    TForm *AForm = (TForm *) ListBox1->Items->Objects[ListBox1->ItemIndex];
    if (AForm->WindowState == wsMinimized)
        SendMessage(AForm->Handle,WM_SYSCOMMAND,SC_RESTORE,0);
    AForm->BringToFront();
}

WM_PARENTNOTIFY是子窗体向ClientWindow发送的消息,使用参数WParamLo判定事件,详情看帮助,如果使用WM_MDICREATE和WM_MDIDESTROY也是可以的,但是要注意调用默认过程CallWindowProc的顺序,因为WM_MDICREATE在处理之后才会返回子窗体句柄,而WM_MDIDESTROY则必须在处理之前使用它的WParam参数作为子窗体句柄.

原创粉丝点击