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

天下

記錄修行的印記

有關窗口繪制的消息整理

窗口繪制有關的消息整理
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>
            久久精品日韩欧美| 国产一区二区三区奇米久涩 | 美女任你摸久久| 亚洲精品乱码久久久久久按摩观| 午夜精品久久久久久久蜜桃app| 欧美成人一区二区三区| 韩曰欧美视频免费观看| 欧美制服丝袜第一页| 亚洲香蕉伊综合在人在线视看| 欧美劲爆第一页| 欧美视频在线观看| 国产在线精品一区二区中文| 亚洲在线观看视频| 亚洲午夜一二三区视频| 国产精品黄色| 久久国产黑丝| 久久久久久久一区| 韩国亚洲精品| 农夫在线精品视频免费观看| 久久精品国产99国产精品| 国产亚洲精品久久久久久| 亚洲精品女av网站| 亚洲片国产一区一级在线观看| 能在线观看的日韩av| 亚洲乱码国产乱码精品精可以看 | 午夜一区二区三区不卡视频| 一道本一区二区| 国产欧美日韩亚洲精品| 久久亚洲综合| 欧美激情国产日韩| 亚洲欧美色婷婷| 久久国产精品久久久久久电车| 黑丝一区二区| 亚洲精品小视频在线观看| 国产欧美日韩伦理| 欧美黄网免费在线观看| 欧美日韩精品不卡| 久久久99爱| 欧美激情第1页| 久久都是精品| 欧美精品系列| 久久久国产精品一区| 欧美成人xxx| 欧美一级大片在线观看| 欧美成人69av| 欧美在线不卡视频| 欧美二区在线看| 欧美一区视频| 欧美伦理影院| 美女黄毛**国产精品啪啪| 欧美日韩综合视频| 国产欧美 在线欧美| 美女啪啪无遮挡免费久久网站| 欧美日韩国产三级| 久久综合999| 欧美v亚洲v综合ⅴ国产v| 在线观看欧美黄色| 亚洲国产裸拍裸体视频在线观看乱了| 欧美日韩在线播放一区| 久久精品中文字幕一区| 欧美三级视频| 欧美激情bt| 国产亚洲一本大道中文在线| 亚洲黑丝一区二区| 一区二区三区无毛| 亚洲自拍三区| 亚洲午夜视频在线观看| 媚黑女一区二区| 久久亚洲捆绑美女| 国产欧美 在线欧美| 亚洲日韩第九十九页| 亚洲高清久久| 久久久精品一区| 欧美一级久久| 国产精品日韩电影| 一本大道久久a久久综合婷婷| 亚洲国产一区在线观看| 久久精品一二三| 久久九九国产精品| 国产一在线精品一区在线观看| 一区二区三区波多野结衣在线观看| 在线精品国精品国产尤物884a| 午夜精彩国产免费不卡不顿大片| 亚洲一区二区三区视频| 欧美日本在线看| 亚洲精品国产精品国自产在线| 亚洲国产精彩中文乱码av在线播放| 久久成人免费网| 另类欧美日韩国产在线| 激情亚洲一区二区三区四区| 久久av在线| 美女精品网站| 亚洲国产精选| 欧美激情一区在线| 亚洲卡通欧美制服中文| 9l国产精品久久久久麻豆| 欧美精品久久久久久| 亚洲全部视频| 亚洲制服欧美中文字幕中文字幕| 欧美性大战久久久久久久蜜臀| 9人人澡人人爽人人精品| 9久草视频在线视频精品| 欧美日韩在线免费视频| 亚洲视频久久| 久久美女性网| 最近看过的日韩成人| 欧美经典一区二区三区| 一本一本久久| 久久久国产精品一区| 亚洲精品久久久久久久久久久久 | 亚洲欧美综合v| 性久久久久久久久久久久| 国产精品丝袜白浆摸在线| 亚洲欧美中日韩| 麻豆91精品| 日韩视频中文| 国产精品美女久久久久久2018| 欧美在线亚洲一区| 国产精品中文在线| 久久综合九色综合久99| 日韩天堂在线视频| 久久精品视频导航| 亚洲区一区二| 国产精品手机视频| 欧美电影免费| 欧美永久精品| 亚洲美女黄网| 巨胸喷奶水www久久久免费动漫| 亚洲大片免费看| 国产精品国产a级| 久久久中精品2020中文| av成人免费在线观看| 久久综合久久88| 亚洲视频精选在线| 亚洲成人在线观看视频| 欧美亚州一区二区三区| 久久久水蜜桃av免费网站| 夜夜夜久久久| 欧美激情精品久久久久久久变态| 亚洲欧美一区二区三区极速播放| 亚洲成人中文| 国产精品每日更新在线播放网址| 久久综合精品一区| 欧美一区二区在线播放| 最新国产の精品合集bt伙计| 欧美在线地址| 亚洲影院高清在线| 亚洲精品免费在线观看| 禁断一区二区三区在线| 国产欧美在线观看| 欧美性大战xxxxx久久久| 欧美高清影院| 久久婷婷一区| 欧美一级专区| 亚洲色诱最新| 一本色道久久综合精品竹菊| 欧美国产日韩精品| 久久亚洲一区二区| 亚洲一区在线直播| 国产精品一区二区你懂的| 欧美成熟视频| 六月婷婷久久| 久久色中文字幕| 久久福利一区| 久久久www成人免费精品| 亚洲一区二区视频| 在线综合欧美| 中文精品视频| 99re6这里只有精品| 亚洲久久在线| 夜夜爽夜夜爽精品视频| 亚洲视频1区2区| 一区二区高清在线| 在线亚洲免费| 亚洲一区在线免费| 性伦欧美刺激片在线观看| 亚洲欧美变态国产另类| 亚洲伊人一本大道中文字幕| 一区二区三区四区精品| 亚洲线精品一区二区三区八戒| 中文欧美在线视频| 日韩午夜高潮| 亚洲一区二区在线免费观看视频| 9i看片成人免费高清| 亚洲一区二区免费| 久久精品99国产精品酒店日本| 欧美一区午夜精品| 久久深夜福利| 欧美激情精品久久久久久变态| 欧美日韩国产丝袜另类| 国产精品久久久久一区| 国产一区二区视频在线观看| 久久久国产一区二区| 麻豆精品在线观看| 欧美大成色www永久网站婷| 欧美福利一区二区| 久久亚洲精选| 国产美女扒开尿口久久久| 亚洲毛片av在线| 亚洲在线观看视频|