知了博客

集天地之精华,吸日月之灵气

« 使用虚列表和自画实现文件夹的缩略图显示ATL.SubclassWindow分析 »

WM_DESTROY与WM_CLOSE

由于wce中,要重写wtl的CFrameWindow,然后采用CWindowImpl去实现View,view里面加入了函数:
并加入CWindowImpl实现的CButton成员函数:
CMYButton m_btn1;
 void OnFinalMessage(HWND /*hWnd*/)
 {
  delete this;
 }
 
然后再在其实的地放用new的方式把View new出来,当窗口关闭时,并在_DEBUG模式下就出现问题,:
若用WM_DESTROY时,在CMYButton 虚构函数里会Assert出,因m_hWnd 不为空
若用WM_CLOSE时,则在CMYButton 虚构函数里不会Assert出
在msdn中在wce的描述:

WM_CLOSE

This message is sent as a signal that a window or an application should terminate.

WM_CLOSE wParam = 0;
  lParam = 0;

Return Values

An application should return zero if it processes this message.

Default Action
The DefWindowProc function calls the DestroyWindow function to destroy the window.

Remarks

An application can prompt the user for confirmation, prior to destroying a window, by processing the WM_CLOSE message and calling the DestroyWindow function only if the user confirms the choice.

WM_DESTROY

This message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.

This message is sent first to the window being destroyed and then to the child windows, if any, as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist.

WM_DESTROY wParam = 0;   lParam = 0; 

Return Values

An application should return zero if it processes this message.

Remarks

In Windows CE, DefWindowProc does not automatically call PostQuitMessage in its handling of WM_DESTROY.

If the window being destroyed is part of the clipboard viewer chain (set by calling the SetClipboardViewer function), the window must remove itself from the chain by processing the ChangeClipboardChain function before returning from the WM_DESTROY message.

再对CWindowImplBaseT 中的WindowProc分析:

template <class TBase, class TWinTraits>
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
 // set a ptr to this message and save the old value
 _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
 const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
 pThis->m_pCurrentMsg = &msg;
 // pass to the message map to process
 LRESULT lRes;
 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
 // restore saved value for the current message
 ATLASSERT(pThis->m_pCurrentMsg == &msg);
 // do the default processing if message was not handled
 if(!bRet)
 {
  if(uMsg != WM_NCDESTROY)
   lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  else
  {
   // unsubclass, if needed
   LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
   lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
   if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
    ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
   // mark window as destryed
   pThis->m_dwState |= WINSTATE_DESTROYED;
  }
 }
 if((pThis->m_dwState & WINSTATE_DESTROYED) && pOldMsg== NULL)
 {
  // clear out window handle
// CMYbutton在虚构函数中报错,应该是没有处理到这里的消息,
//如果处理到了这里的消息m_hWnd会设置为NULL,
//所以可以认为WM_DESTROY 消息发出后,立即处理了view OnFinalMessage,并把
//view销毁了,而CMYbutton里的对像也随之销毁掉,并没来得及运行到这里
//WM_CLOSE,则并没有立即运行view OnFinalMessage,所以有时间CMYbutton消息运行到这个地方,并把m_hWnd销毁掉
  HWND hWndThis = pThis->m_hWnd;
  pThis->m_hWnd = NULL;
  pThis->m_dwState &= ~WINSTATE_DESTROYED;
  // clean up after window is destroyed
  pThis->m_pCurrentMsg = pOldMsg;
  pThis->OnFinalMessage(hWndThis);
 }else {
  pThis->m_pCurrentMsg = pOldMsg;
 }
 return lRes;
}
 
 
从网上找到WM_DESTORY,WM_CLOSE,主要讲的是MFC中有功能区别,如下:
WM_DESTROY,WM_CLOSE   功能有什么不同 
  下面程序执行时出错 
  void   CMainFrame::OnClose()   
  { 
        CMDIFrameWnd::OnClose(); 
        CDocument   *doc; 
        doc=this->GetActiveDocument(); 
  } 
  下面程序执行时不出错, 
  void   CMainFrame::OnDestroy()   
  { 
        CDocument   *doc; 
        doc=this->GetActiveDocument(); 
        CMDIFrameWnd::OnDestroy(); 
  }  
原因分析:
WM_CLOSE是在窗口关闭前发送的,你还可以决定是否真的关闭窗口 
  WM_DESTROY是在窗口关闭过程中发送的,窗口已被移出屏幕 
  你的程序的错误在于调用   CMDIFrameWnd::OnClose();   后窗体已经 
  被Destroy掉了,this指针指向的窗口对象已经不存在了,所以出错
也就是处理顺序是先处理WM_CLOSE(窗口未关闭),后处理WM_DESTROY(窗口已关闭) 
  CMDIFrameWnd::OnClose();后的部分不执行,如需要执行,可放到OnDestroy()中,即你的第二段
调用父类缺省处理   CMDIFrameWnd::OnClose()时,   系统又发出了 
  WM_DESTROY消息将窗口destroy了,所以OnDestroy中this指针还可以用, 
  等出了CMDIFrameWnd::OnClose()后this指针指向的窗口对象已经不存在了
同理:
  void   CMainFrame::OnClose()   
  { 
      CDocument   *doc; 
      doc=this->GetActiveDocument(); 
      CMDIFrameWnd::OnClose(); 
  }   
  将不出错 
  下面程序执行时出错, 
  void   CMainFrame::OnDestroy()   
  { 
      CMDIFrameWnd::OnDestroy(); 
      CDocument   *doc; 
      doc=this->GetActiveDocument(); 
  } 
  原因如下: 
  OnClose()中调用DestoryWindow(),而DestoryWindow()中发送   WM_DESTROY   和   WM_NCDESTROY;DestoryWindow()执行结束时,OnDestroy()、OnNcDestory()也都执行了,在 CMDIFrameWnd::OnClose()返回后,CMainFrame   的对象已被释放,this指针不可再用。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Arwen Build 90619 Code detection by Codefense  theme by BokeZhuti

Copyright know blog. Some Rights Reserved.站长(msn):webmaster#webgou.info(#换成@) 粤ICP备09183716号