青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天下

記錄修行的印記

有關窗口繪制的消息整理

窗口繪制有關的消息整理
WM_PAINTWM_NCPAINTWM_ERASEBKGND

WM_PAINT
WM_PAINT是Windows窗口系統中一條重要的消息,應用程序通過處理該消息實現在窗口上的繪制工作。

WM_NCPAINT
當窗口客戶區以外的部分(如窗口標題欄、菜單欄等)需要需要重畫時,系統向程序發出該消息。因標準窗口的客戶區以外部分為窗口必需部分,因而該消息將默認被發送到DefWindowProc函數進行默認處理。程序可通過截獲該消息來實現窗口其他部分的自定義繪制。

WM_ERASEBKGND

The WM_ERASEBKGND message is sent when the window background must be erased (for example, when a window is resized). The message is sent to prepare an invalidated portion of a window for painting.

一、WM_PAINT消息
在系統繪制窗口時向程序發出WM_PAINT消息。程序在接收到WM_PAINT消息后調用BeginPaint函數獲取當前的Device Context進行繪圖操作,繪圖完畢后使用EndPaint釋放Device Context。

1. 系統何時發送WM_PAINT消息?

系統會在多個不同的時機發送WM_PAINT消息:當第一次創建一個窗口時,當改變窗口的大小時,當把窗口從另一個窗口背后移出時,當最大化或最小化窗口時,等等,這些動作都是由 系統管理的,應用只是被動地接收該消息,在消息處理函數中進行繪制操作;大多數的時候應用也需要能夠主動引發窗口中的繪制操作,比如當窗口顯示的數據改變的時候,這一般是通過InvalidateRect和 InvalidateRgn函數來完成的。InvalidateRect和InvalidateRgn把指定的區域加到窗口的Update Region中,當應用的消息隊列沒有其他消息時,如果窗口的Update Region不為空時,系統就會自動產生WM_PAINT消息。

系統為什么不在調用Invalidate時發送WM_PAINT消息呢?又為什么非要等應用消息隊列為空時才發送WM_PAINT消息呢?這是因為系統把在窗口中的繪制操作當作一種低優先級的操作,于是盡 可能地推后做。不過這樣也有利于提高繪制的效率:兩個WM_PAINT消息之間通過InvalidateRect和InvaliateRgn使之失效的區域就會被累加起來,然后在一個WM_PAINT消息中一次得到 更新,不僅能避免多次重復地更新同一區域,也優化了應用的更新操作。

像這種通過InvalidateRect和InvalidateRgn來使窗口區域無效,依賴于系統在合適的時機發送WM_PAINT消息的機 制實際上是一種異步工作方式,也就是說,在無效化窗口區域和發送WM_PAINT消息之間是有延遲的;
//有時候這種延遲并不是我們希望的,這時我們當然可以在無效化窗口區域后利用SendMessage 發送一條WM_PAINT消息來強制立即重畫。
注解:
SendMessage會block到被發送的消息被處理完才返回,但是WM_PAINT消息的處理時間又是用戶不可控制的:“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. ”(MSDN原文),那么也就是說,你調用SendMessage之后,這個方法需要等待多長時間才能返回是不可控制的。所以MSDN不推薦用戶直接發送WM_PAINT消息:“The WM_PAINT message is generated by the system and should not be sent by an application”
但不如使用Windows GDI為我們提供的更方便和強大的函數:
UpdateWindow和RedrawWindow。UpdateWindow會檢查窗口的Update Region,當其不為空時才發送WM_PAINT消息;
RedrawWindow則給我們更多的控制:是否重畫非客戶區和背景,是否總是發送WM_PAINT消息而不管Update Region是否為空等。

WM_PAINT觸發機制
如果WM_PAINT不是由InvalidateRect或InvalidateRgn產生時,先發WM_ERASEBKGND,再發WM_PAINT
如果WM_PAINT是由InvalidateRect或InvalidateRgn產生時,則先發WM_PAINT,
然后beginPaint()再根據Invalidate的bErase參數(重畫背景)來決定是否發WM_ERASEBKGND消息


當WM_PAINT不是由InvalidateRect產生時,即由最大化,最小化等產生時,或者移動產生(移動有時只會產生WM_ERASEBKGND消息)系統先發送WM_ERASEBKGND消息,再發送WM_PAINT消息.
當WM_PAINT由InvalidateRect()產生時,先發送WM_PAINT消息(異步),如果InvalidateRect的bErase為TRUE,BeginPaint檢查到更新區域需要刪除背景,向窗口發送一個WM_ERASEBKGND
消息


二、WM_ERASEBKGND消息
Parameters
wParam
Handle to the device context.

lParam
This parameter is not used.

Return Value
An application should return nonzero if it erases the background; otherwise, it should return zero.
也就是說WM_ERASEBKGND消息重繪了背景,應該返回非0值,否則返回0;


Remarks
The DefWindowProc function erases the background by using the class background brush specified by the hbrBackground member of the WNDCLASS structure. If hbrBackground is NULL, the application should process the WM_ERASEBKGND message and erase the background.

An application should return nonzero in response to WM_ERASEBKGND if it processes the message and erases the background; this indicates that no further erasing is required. If the application returns zero, the window will remain marked for erasing. (Typically, this indicates that the fErase member of the PAINTSTRUCT structure will be TRUE.)

補充:
DefWindowProc(hWnd, message, wParam, lParam)處理WM_ERASEBKGND消息時默認用下面的畫刷清除背景
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

三、WM_NCPAINT消息
The WM_NCPAINT message is sent to a window when its frame must be painted.

A window receives this message through its WindowProc function.

LRESULT CALLBACK WindowProc(
  HWND hwnd,       // handle to window
  UINT uMsg,       // WM_NCPAINT
  WPARAM wParam,   // handle to update region (HRGN)
  LPARAM lParam    // not used
);
Parameters
wParam
Handle to the update region of the window. The update region is clipped to the window frame. When wParam is 1, the entire window frame needs to be updated.
lParam
This parameter is not used.
Return Values
An application returns zero if it processes this message.

Remarks
The DefWindowProc function paints the window frame.

An application can intercept the WM_NCPAINT message and paint its own custom window frame. The clipping region for a window is always rectangular, even if the shape of the frame is altered.

The wParam value can be passed to GetDCEx as in the following example.

case WM_NCPAINT:
{
    HDC hdc;
    hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
    // Paint into this DC
    ReleaseDC(hwnd, hdc);
}

四、PAINTSTRUCT結構體
The PAINTSTRUCT structure contains information for an application. This information can be used to paint the client area of a window owned by that application.

typedef struct tagPAINTSTRUCT {
HDC  hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;

Members
hdc
Handle to the display DC to be used for painting.

fErase
Specifies whether the background must be erased. This value is nonzero if the application should erase the background. The application is responsible for erasing the background if a window class is created without a background brush. For more information, see the description of the hbrBackground member of the WNDCLASS structure.

rcPaint
Specifies a RECT structure that specifies the upper left and lower right corners of the rectangle in which the painting is requested, in device units relative to the upper-left corner of the client area.

五、相關函數
1) BeginPaint
The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with information about the painting.
HDC BeginPaint(
  HWND hwnd,            // handle to window
  LPPAINTSTRUCT lpPaint // paint information
);
Parameters
hwnd
[in] Handle to the window to be repainted.
lpPaint
[out] Pointer to the PAINTSTRUCT structure that will receive painting information.
Return Values
If the function succeeds, the return value is the handle to a display device context for the specified window.
If the function fails, the return value is NULL, indicating that no display device context is available.
Windows NT/2000/XP: To get extended error information, call GetLastError.

Remarks
The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.

An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.

If the caret is in the area to be painted, BeginPaint automatically hides the caret to prevent it from being erased.

If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning.

BeginPaint
BeginPaint和WM_PAINT消息緊密相關。試一試在WM_PAINT處理函數中不寫BeginPaint會怎樣?
程序會像進入了一個死循環一樣達到驚人的CPU占用率,你會發現程序總在處理一個接一個的WM_PAINT消息。這是因為在通常情況下,當應用收到WM_PAINT消息時,窗口的Update Region都是非空的(如果為空就不需要發送WM_PAINT消息了),BeginPaint的一個作用就是把該Update Region置為空,這樣如果不調用BeginPaint,窗口的Update Region就一直不為空,如前所述,系統就會一直發送WM_PAINT消息。
BeginPaint和WM_ERASEBKGND消息也有關系。當窗口的Update Region被標志為需要擦除背景時,BeginPaint會發送WM_ERASEBKGND消息來重畫背景,同時在其返回信息里有一個標志表明窗口背景是否被重畫過。當我們用InvalidateRect和InvalidateRgn來把指定區域加到Update Region中時,可以設置該區域是否需要被擦除背景,這樣下一個BeginPaint就知道是否需要發送WM_ERASEBKGND消息了。
如果處理WM_ERASEBKGND時返回TRUE,BeginPaint標記ps.fErase為FALSE,
如果處理WM_ERASEBKGND消息時返回FALSE,BeginPaint標記ps.fErase 為TRUE.

另外要注意的一點是,BeginPaint只能在WM_PAINT處理函數中使用。


2)InvalidateRect
   InvalidateRect只是增加重繪區域,在下次WM_PAINT的時候才生效,InvalidateRect函數中的參數TRUE表示系統會在你畫之前用背景色將所選區域覆蓋一次,默認背景色為白色,可以通過設置BRUSH來改變背景色。

   InvalidateRect(hWnd,
&rect,TRUE);向hWnd窗體發出WM_PAINT的消息,強制客戶區域重繪制,rect是你指定要刷新的區域,此區域外的客戶區域不被重繪,這樣防止客戶區域的一個局部的改動,而導致整個客戶區域重繪而導致閃爍,如果最后的參數為TRUE,則還向窗體發送WM_ERASEBKGND消息,使背景重繪,當然在客戶區域重繪之前。

(3)UpdateWindow
   UpdateWindow只向窗體發送WM_PAINT消息,在發送之前判斷GetUpdateRect(hWnd,NULL,TRUE)看有無可繪制的客戶區域,如果沒有,則不發送WM_PAINT。如果希望立即刷新無效區域,可以在調用InvalidateRect之后調用UpdateWindow,如果客戶區的任一部分無效,則UpdateWindow將導致Windows用WM_PAINT消息調用窗口過程(如果整個客戶區有效,則不調用窗口過程)。這一WM_PAINT消息不進入消息隊列,直接由WINDOWS調用窗口過程。窗口過程完成刷新以后立刻退出,WINDOWS將控制返回給程序中UpdateWindow調用之后的語句。(windows程序設計第5版 P98)

4)EndPaint
The EndPaint function marks the end of painting in the specified window. This function is required for each call to the BeginPaint function, but only after painting is complete.

BOOL EndPaint(
  HWND hWnd,                  // handle to window
  CONST PAINTSTRUCT *lpPaint  // paint data
);
Parameters
hWnd
[in] Handle to the window that has been repainted.
lpPaint
[in] Pointer to a PAINTSTRUCT structure that contains the painting information retrieved by BeginPaint.
Return Values
The return value is always nonzero.

Remarks
If the caret was hidden by BeginPaint, EndPaint restores the caret to the screen.


posted on 2011-04-15 11:46 天下 閱讀(2314) 評論(1)  編輯 收藏 引用 所屬分類: Win32

評論

# re: 有關窗口繪制的消息整理 2012-06-15 14:30 開通

很好。
能再詳細點就更好了  回復  更多評論   

<2015年12月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

導航

統計

常用鏈接

留言簿(4)

隨筆分類(378)

隨筆檔案(329)

鏈接

最新隨筆

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久综合狠狠综合久久综合88| 99精品国产99久久久久久福利| 国产精品国产福利国产秒拍| 欧美精品一区二区在线播放| 欧美激情日韩| 欧美国产欧美综合| 欧美天堂亚洲电影院在线观看| 国产精品播放| 好吊色欧美一区二区三区视频| 在线看无码的免费网站| 亚洲美女精品成人在线视频| 中文国产成人精品久久一| 亚洲一区二区三区视频| 久久精品欧洲| 亚洲国产另类 国产精品国产免费| 欧美福利一区二区三区| 日韩视频中文字幕| 欧美在线播放| 欧美色精品天天在线观看视频 | 国产精品日韩高清| 国产三级精品在线不卡| 91久久精品国产91久久性色tv | 国产婷婷97碰碰久久人人蜜臀| 一区在线播放| 亚洲一区二区网站| 久久综合色一综合色88| 亚洲精选一区二区| 久久国产精品一区二区三区四区| 欧美精品精品一区| 伊人久久亚洲热| 亚洲一级在线| 亚洲福利专区| 久久成人18免费网站| 欧美精品在线视频观看| 狠狠久久亚洲欧美| 欧美一区二区三区视频在线| 亚洲国产精品女人久久久| 欧美在线网址| 国产精品极品美女粉嫩高清在线 | 亚洲作爱视频| 久热精品在线视频| 国产一区二区av| 亚洲视频免费在线观看| 欧美成人午夜激情视频| 欧美在线视频a| 国产精品看片你懂得| 一本色道久久综合亚洲精品按摩 | 日韩午夜av| 亚洲视屏在线播放| 欧美日本亚洲| 国产亚洲欧洲| 99国产精品久久久久久久久久| 新67194成人永久网站| 99精品免费| 亚洲国产欧美一区二区三区久久| 亚洲电影在线免费观看| 久久天堂国产精品| 亚洲男人的天堂在线观看| 欧美国产日本高清在线| 揄拍成人国产精品视频| 久久综合九色综合欧美就去吻| 亚洲欧美国产va在线影院| 欧美日韩小视频| 在线视频欧美日韩精品| 亚洲精一区二区三区| 欧美日韩国产片| 亚洲天堂第二页| 一区二区三区四区国产| 国产精品高清一区二区三区| 亚洲欧美日韩国产一区二区三区| aa级大片欧美| 国产乱子伦一区二区三区国色天香| 亚洲视频网在线直播| 正在播放欧美一区| 国产农村妇女精品| 看片网站欧美日韩| 六月丁香综合| 99精品福利视频| 亚洲一卡久久| 国产亚洲制服色| 欧美国产国产综合| 欧美日韩国产成人| 欧美在线1区| 麻豆精品视频在线观看| 亚洲美女视频在线观看| 99精品国产热久久91蜜凸| 国产乱肥老妇国产一区二 | 欧美激情综合色综合啪啪| 亚洲免费精彩视频| 一区二区不卡在线视频 午夜欧美不卡在 | 国产在线精品成人一区二区三区| 另类综合日韩欧美亚洲| 欧美精品激情blacked18| 国产精品免费看| 久久国产福利| 欧美日韩爆操| 免费看亚洲片| 国产精品久久99| 亚洲日本无吗高清不卡| 国产精品女主播| 亚洲性视频网站| 欧美一区二区三区日韩| 中国成人在线视频| 亚洲一区日韩在线| 亚洲激情校园春色| 校园激情久久| 一区二区激情视频| 久久亚洲私人国产精品va媚药| 在线视频一区二区| 久久综合图片| 亚洲一线二线三线久久久| 久久精品亚洲乱码伦伦中文| 亚洲一区精彩视频| 蜜臀久久99精品久久久久久9| 午夜视黄欧洲亚洲| 欧美日韩 国产精品| 免费看成人av| 国产亚洲一本大道中文在线| 日韩午夜视频在线观看| 亚洲精品在线视频| 久久综合综合久久综合| 久久免费视频一区| 国产欧美日本一区视频| 亚洲视频免费观看| 一本色道久久综合| 欧美精品日韩综合在线| 欧美韩国在线| 亚洲电影成人| 久久精品在线免费观看| 欧美怡红院视频| 国产精品亚洲а∨天堂免在线| 一区二区冒白浆视频| 一本色道婷婷久久欧美| 欧美日本不卡高清| 日韩午夜av| 亚洲综合精品一区二区| 欧美日韩国产页| 亚洲精品国产精品国自产观看| 亚洲巨乳在线| 欧美人妖另类| 亚洲视屏在线播放| 久久xxxx精品视频| 国产一区二区三区av电影| 午夜欧美理论片| 久久久国产精品一区二区三区| 国产欧美视频在线观看| 久久精品官网| 欧美高清一区| aa亚洲婷婷| 国产精品日韩一区| 久久久91精品国产一区二区三区| 久久久久久网站| 亚洲国产欧美不卡在线观看| 欧美激情成人在线视频| 亚洲美女黄色| 国产精品乱人伦一区二区| 久久久综合网站| 蜜臀av性久久久久蜜臀aⅴ| 欧美国产日韩精品| 国产精品国产自产拍高清av王其| 国产嫩草一区二区三区在线观看| 国产亚洲一级高清| 亚洲综合日韩中文字幕v在线| 久久久久国产免费免费| 亚洲国产日韩在线一区模特| 亚洲国产成人porn| 欧美精品乱人伦久久久久久 | 国产精品国产| 欧美一区二区女人| 欧美xx69| 亚洲曰本av电影| 国内精品一区二区三区| 欧美激情成人在线| 亚洲综合色在线| 美女主播视频一区| 亚洲午夜久久久久久久久电影院 | 欧美大片网址| 亚洲一区三区视频在线观看| 国产日韩视频| 欧美日韩一本到| 久久九九国产| 在线一区二区视频| 欧美ed2k| 久久久午夜电影| 亚洲欧美另类国产| 亚洲精品少妇| 国内精品模特av私拍在线观看| 欧美极品色图| 久久久蜜臀国产一区二区| 亚洲视频一区二区| 最新国产成人在线观看| 美日韩精品免费观看视频| 午夜视频精品| 一区二区精品国产| 亚洲电影免费在线观看| 国产亚洲一区在线播放| 国产女主播一区二区三区| 欧美日韩综合在线| 欧美激情一区在线| 久久综合给合|