金山界面库分析(4)

如何创建一个模态对话框


我们创建的窗口类从CBkDialogImpl继承而来,这个窗口就是一个模态的窗口,我们需要调用其DoModal方法,但是在界面库里面是如何实现的一个模态的对话框呢。

核心就在这个类中的_ModalMessageLoop方法,我们来研究一下。

 

  void _ModalMessageLoop()
   {
       BOOL bRet;
       MSG msg;
 
       for(;;)
       {
            if(::PeekMessage(&msg,NULL, 0, 0, PM_NOREMOVE))
            {
                if(WM_QUIT == msg.message)
                    break;
            }
 
            if(m_bExitModalLoop || NULL == m_hWnd || !::IsWindow(m_hWnd))
                break;
 
            bRet= ::GetMessage(&msg,NULL, 0, 0);
 
            if(bRet == -1)
            {
                continue;   // error, don'tprocess
            }
            elseif (!bRet)
            {
                ATLTRACE(L"Why ReceiveWM_QUIT here?\r\n");
                break;   // WM_QUIT, exitmessage loop
            }
 
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
       }
}

在这个函数里面建立了一个消息处理循环。

首先进行WM_QUIT消息的检测,并且采用PM_NOREMOVE的方式,如果获得了这个消息,那么退出消息循环,在之后的DoModal函数中模态窗口就被销毁了。

然后检测bExitModalLoop标志,如果这个标志位为TRUE的话那么也退出处理。我们来看一下退出模态的函数:

   void EndDialog(UINT uRetCode)
   {
       m_uRetCode = uRetCode;
       m_bExitModalLoop = TRUE;
       // DestroyWindow里面直接Send了WM_DESTROY,所以不会跑到DoModal的消息循环里,所以有了下面那行代码
       // DestroyWindow();
       // 这句非常重要,可以让DoModal消息循环再跑一次,防止卡死在GetMessage,泪奔
       ::PostThreadMessage(::GetCurrentThreadId(), WM_NULL,0, 0);
    }

可见就是设置m_bExitModalLoop这个标志位,使窗口退出。

         之后就是GetMessage,TranslateMessage和DispatchMessage了,就完成了常见的消息处理。当我们创建窗口并运行在ModalMessageLoop函数当中时就形成了模态窗口的效果,也就是接管了消息的分发和处理,其他的窗口就被模住了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值