sendmessage WM_PAINT 無效(6月19日)

今天意外發現替一哥們做的程序還有漏洞,點擊彈出來的對話框的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

,只有一種情況例外,那就是更新區域爲空(我的理解就是沒有無效區域).所以我認爲:要使得窗口立刻更新,則聯用這兩個函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章