duilib中实现弹出模态框时要注意的地方

在duilib中,可以调用CWindowWnd::ShowModal()来实现模态框的显示,该接口的代码如下所示:

[cpp]  view plain  copy
  1. UINT CWindowWnd::ShowModal()  
  2. {  
  3.     ASSERT( ::IsWindow(m_hWnd) );  
  4.     UINT nRet = 0;  
  5.     HWND hWndParent = GetWindowOwner( m_hWnd );  
  6.     ::ShowWindow( m_hWnd, SW_SHOWNORMAL );  
  7.     ::EnableWindow( hWndParent, FALSE );  
  8.     MSG msg = { 0 };  
  9.     while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) )   
  10.     {  
  11.         if( WM_CLOSE == msg.message && msg.hwnd == m_hWnd )   
  12.         {  
  13.             nRet = msg.wParam;  
  14.             ::EnableWindow( hWndParent, TRUE );  
  15.             ::SetFocus( hWndParent );  
  16.         }  
  17.   
  18.         if( !CPaintManagerUI::TranslateMessage(&msg) )   
  19.         {  
  20.             ::TranslateMessage( &msg );  
  21.             ::DispatchMessage( &msg );  
  22.         }  
  23.   
  24.         if( WM_QUIT == msg.message )   
  25.         {  
  26.             break;  
  27.         }  
  28.     }  
  29.     ::EnableWindow( hWndParent, TRUE );  
  30.     ::SetFocus( hWndParent );  
  31.     if( WM_QUIT == msg.message )   
  32.     {  
  33.         ::PostQuitMessage( msg.wParam );  
  34.     }  
  35.   
  36.     return nRet;  
  37. }  
由代码可以看出,先将父窗口Disable掉,然后接管UI主线程的消息循环,在模态框关闭后,再将消息循环放归UI主线程。但在使用时要要稍微注意一下,下面就简单的说明一下。

        先给出几段有问题的代码,先假设CDemoDlg是待显示的模态框窗口,由DUI派生而来,如下所示:

[cpp]  view plain  copy
  1. class CDemoDlg : public CWindowImplBase  
  2. {  
  3. public:  
  4.     CDemoDlg( STRINGorID strUI, unsigned int dwTransparent = 255, bool bDeleteSelf = true );  
  5.     virtual ~CDemoDlg();  
  6. ......  
  7. }  

        代码段1如下所示:(下面的代码均是放置在某一个函数中,即在某一函数中弹出模态框)

[cpp]  view plain  copy
  1. CDemoDlg demoDlg( IDR_XML_DEMO_DLG );  
  2. demoDlg.Create( hParentWnd, _T("CDemoDlg"), UI_WNDSTYLE_BOX, UI_WNDSTYLE_EX_FRAME );  
  3. demoDlg.CenterWindow();  
  4. demoDlg.ShowModal();  
代码中可以看出,CDemoDlg在创建时将使用默认值bool bDeleteSelf = true,所以在WindowImplBase::OnFinalMessage函数中窗口对象会自动被delete掉,看上去好像是没问题。实际上,demoDlg是局部对象,使用的是栈上的内存,但是delete删除的是堆上的内存,这肯定是有问题的,会引起异常。所以这种方法是有问题。

        代码段2如下所示:

[cpp]  view plain  copy
  1. CDemoDlg* pDlg = new CDemoDlg ( IDR_XML_DEMO_DLG, 255, false );  
  2. pDlg->Create( hParentWnd, _T("CDemoDlg"), UI_WNDSTYLE_BOX, UI_WNDSTYLE_EX_FRAME );  
  3. pDlg->CenterWindow();  
  4. pDlg->ShowModal();  
代码1中的自动销毁有问题,那我们就将bDeleteSelf设置为false,不让自动被销毁。但还是有问题,new出来的对象没有释放,会有内存泄漏,其实在ShowModal执行完后把new来的对象delete就好了。

        那么如果不用new的方式,用代码1中的方式如何实现呢?也简单,构造对象时将bDeleteSelf设置为false,不让其自动被销毁,由于是局部变量,函数退出时会被销毁掉,即如下的代码:

[cpp]  view plain  copy
  1. CDemoDlg demoDlg( IDR_XML_DEMO_DLG,255, false );  
  2. demoDlg.Create( hParentWnd, _T("CDemoDlg"), UI_WNDSTYLE_BOX, UI_WNDSTYLE_EX_FRAME );  
  3. demoDlg.CenterWindow();  
  4. demoDlg.ShowModal();  

你可能感兴趣的:(duilib)