sendmessage WM_PAINT 无效(6月19日)

来源:互联网 发布:蔚来电动车知乎 编辑:程序博客网 时间:2024/04/29 11:04

今天意外发现替一哥们做的程序还有漏洞,点击弹出来的对话框的BUTTON时,发现主窗口(实际是VIEW啦)不自动重绘以产生相应图形。我就纳闷了,我明明已经给VIEW类发送WM_PAINT重绘消息了啊,怎么回事?搜索MSDN,发现以下一段话:

 The WM_PAINT message is generated by the system and should not be sent by an application. To force a window to draw into a specific device context, use the WM_PRINT or WM_PRINTCLIENT message.

Note that this requires the target window to support the WM_PRINTCLIENT message. Most common controls support the WM_PRINTCLIENT message. The DefWindowProc function validates the update region. The function may also send the WM_NCPAINT message to the window procedure if the window frame must be painted and send the WM_ERASEBKGND message if the window background must be erased.

 The system sends this message when there are no other messages in the application's message queue. DispatchMessage determines where to send the message; GetMessage determines which message to dispatch. GetMessage returns the WM_PAINT message when there are no other messages in the application's message queue, and DispatchMessage sends the message to the appropriate window procedure.

 A window may receive internal paint messages as a result of calling RedrawWindow with the RDW_INTERNALPAINT flag set. In this case, the window may not have an update region. An application should call the GetUpdateRect function to determine whether the window has an update region. If GetUpdateRect returns zero, the application should not call the BeginPaint and EndPaint functions.

 An application must check for any necessary internal painting by looking at its internal data structures for each WM_PAINT message, because a WM_PAINT message may have been caused by both a non-NULL update region and a call to RedrawWindow with the RDW_INTERNALPAINT flag set. The system sends an internal WM_PAINT message only once. After an internal WM_PAINT message is returned from GetMessage or PeekMessage or is sent to a window by UpdateWindow, the system does not post or send further WM_PAINT messages until the window is invalidated or until RedrawWindow is called again with the RDW_INTERNALPAINT flag set. For some common controls, the default WM_PAINT message processing checks the wParam parameter. If wParam is non-NULL, the control assumes that the value is an HDC and paints using that device context.

所以说,要使得窗口重绘,最好还是使用Invalidate(),而不要使用sendmessage来实现。因为,正如以上提及的,windows不是对每个WM_PAINT都去调用相应OnDraw函数的:An application must check for any necessary internal painting by looking at its internal data structures for each WM_PAINT message

但是奇怪的是,我去给对话框发送该消息时,对话框是去响应的。

最后提下一般的使用方式,如在E:/c++/Projects/xiongjiDOC中的对话框类中:

 CMainFrame* pMF=(CMainFrame*)AfxGetMainWnd(); //获取当前视图的指针

CxiongjiDOCView* myView=(CxiongjiDOCView*)pMF->GetActiveView();

//myView->SendMessage(WM_PAINT,0,0);

 myView->Invalidate();

 

PS:2009.12.07

事实上,让程序立刻响应WM_PAINT的最好的方式是Invalidate+UpdateWindow.

因为我今天写的一个程序里面又用到了这些东西,我发现单用Invalidate还是不能响应WM_PAINT.于是找MSDN,发现有以下说明:

Invalidate使得窗口客户区无效,一般这个时候系统发现有无效区域后就会发送WM_PAINT消息,但是如果这时候该窗口消息队列里面有其他的消息,则不会响应该消息。但是UpdateWindow就不一样,它不管消息队列里面有没有其他消息在前面,都会直接发送WM_PAINTxiaoxi

,只有一种情况例外,那就是更新区域为空(我的理解就是没有无效区域).所以我认为:要使得窗口立刻更新,则联用这两个函数。

原创粉丝点击