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

天下

記錄修行的印記

有關窗口繪制的消息整理

窗口繪制有關的消息整理
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 天下 閱讀(2307) 評論(1)  編輯 收藏 引用 所屬分類: Win32

評論

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

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

<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

導航

統計

常用鏈接

留言簿(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>
            亚洲视频在线二区| 国模精品娜娜一二三区| 久久综合给合久久狠狠色 | 亚洲精品一区二区三区福利| 久久久久国产一区二区| 亚洲欧美一区二区三区久久| 在线天堂一区av电影| 一区二区三区视频观看| 亚洲一级网站| 久久久久一区| 蜜臀av一级做a爰片久久| 亚洲黑丝在线| 一二三区精品福利视频| 新67194成人永久网站| 欧美一区二区精品在线| 久久在线91| 国产精品久久久久久久浪潮网站 | 亚洲视频在线观看三级| 久久riav二区三区| 亚洲精品资源| 免费影视亚洲| 国产日韩欧美自拍| 亚洲欧美精品在线观看| 亚洲黄色三级| 女同性一区二区三区人了人一| 国产精品乱码| 日韩视频在线你懂得| 亚洲乱码日产精品bd| 久久国产精品久久国产精品| 欧美日韩精品免费观看视频完整| 中文网丁香综合网| 欧美黑人在线观看| 亚洲精品日日夜夜| 亚洲精品一级| 欧美日韩精品高清| 亚洲欧美一区二区三区极速播放 | 亚洲综合国产激情另类一区| 亚洲第一综合天堂另类专| 久久人体大胆视频| 亚洲人成亚洲人成在线观看图片| 欧美一区二区三区精品电影| 亚洲一区二区欧美日韩| 亚洲免费网站| 国产精品欧美风情| 久久精品国产亚洲一区二区| 久久aⅴ国产欧美74aaa| 最近中文字幕日韩精品| 亚洲精品乱码久久久久久黑人| 欧美精品一区二区三区在线播放| 夜夜嗨av一区二区三区四季av| 99精品视频免费| 国产综合色一区二区三区| 欧美激情视频给我| 国产精品红桃| 亚洲高清视频在线观看| 国产精品日韩电影| 亚洲人成网站在线播| 国产精品jizz在线观看美国| 美女黄色成人网| 国产精品视频精品| 亚洲精品久久久久久久久| 狠狠久久五月精品中文字幕| 日韩视频―中文字幕| 欧美成va人片在线观看| 亚洲美女黄色| 久久综合给合久久狠狠色| 先锋影音久久| 欧美大片91| 亚洲第一色在线| 海角社区69精品视频| 亚洲校园激情| 久久精品国产亚洲高清剧情介绍| 欧美天天在线| 久久成人精品无人区| 欧美视频一区在线观看| 亚洲第一视频网站| 欧美日本韩国一区二区三区| 欧美亚洲一区二区三区| 亚洲国产精品视频| 你懂的网址国产 欧美| 欧美成人午夜影院| 亚洲精选久久| 欧美视频在线观看免费网址| 99精品国产在热久久| 亚洲一区二区在线播放| 国产网站欧美日韩免费精品在线观看 | 国产综合视频| 美女主播精品视频一二三四| 亚洲第一搞黄网站| 午夜日韩福利| 在线观看日韩av电影| 欧美性久久久| 久久人人爽爽爽人久久久| 日韩午夜激情av| 蜜桃久久av| 久久视频国产精品免费视频在线| 亚洲人体1000| 最新高清无码专区| 欧美在线观看视频在线| 亚洲国产欧美久久| 国产亚洲一区二区三区| 欧美国产一区二区| 久久在线免费| 久久激情五月丁香伊人| 中文久久乱码一区二区| 亚洲经典三级| 亚洲激情小视频| 亚洲国产岛国毛片在线| 裸体一区二区| 免费不卡欧美自拍视频| 久久这里有精品15一区二区三区| 欧美一区二区三区婷婷月色 | 欧美色视频日本高清在线观看| 久久漫画官网| 美女被久久久| 欧美经典一区二区三区| 欧美激情一区二区三区在线视频 | 亚洲欧美在线免费| 欧美一级播放| 裸体丰满少妇做受久久99精品| 久久综合导航| 亚洲精品亚洲人成人网| 亚洲性线免费观看视频成熟| 亚洲欧美日韩国产综合| 久久爱另类一区二区小说| 久久伊人精品天天| 欧美日韩国产区一| 国产精品一区二区你懂得| 欧美亚洲视频| 久久久综合精品| 欧美视频一区在线| 亚洲大胆av| 西瓜成人精品人成网站| 国产精品中文字幕欧美| 一色屋精品视频免费看| 在线一区亚洲| 欧美国产精品一区| 欧美一级日韩一级| 国产精品成人av性教育| 亚洲国产成人久久综合一区| 亚洲午夜在线| 亚洲欧洲精品一区二区三区不卡 | 欧美.日韩.国产.一区.二区| 亚洲最新中文字幕| 欧美成人免费在线视频| 国产一区二三区| 久久av资源网| 欧美一区二区精品久久911| 国产精品麻豆成人av电影艾秋 | 黄色小说综合网站| 性色av一区二区怡红| 亚洲视频免费| 国产精品久久久久9999高清| 一区二区三区不卡视频在线观看 | 久久精品国产亚洲aⅴ| 午夜欧美大片免费观看 | 欧美性色视频在线| 亚洲免费一级电影| 日韩视频在线你懂得| 亚洲精品国产精品国自产观看浪潮| 欧美在线91| 日韩亚洲不卡在线| 99精品视频免费观看| 亚洲国产欧美一区二区三区久久| 久久一二三国产| 久久综合给合久久狠狠狠97色69| 精品成人一区| 久久亚洲不卡| 一本色道久久88精品综合| 亚洲一区影院| 亚洲日本成人| 欧美一级理论性理论a| 亚洲精品久久久蜜桃| 亚洲视频在线一区| 亚洲欧洲在线观看| 久久av免费一区| 亚洲欧美日韩国产另类专区| 久久久久久久久久久一区| 亚洲深夜福利视频| 亚洲欧美国产毛片在线| 亚洲福利在线观看| 欧美一区二区三区在线视频| 99国产精品| 欧美激情在线免费观看| 麻豆国产精品777777在线| 欧美吻胸吃奶大尺度电影| 亚洲高清在线精品| 亚洲国产成人久久综合一区| 亚洲精品中文字幕女同| 亚洲三级电影全部在线观看高清 | 亚洲精品一区中文| 免费h精品视频在线播放| 你懂的视频一区二区| **性色生活片久久毛片| 久久久久久久久综合| 欧美高清不卡在线| 亚洲国产一区在线观看| 另类尿喷潮videofree| 欧美国产高潮xxxx1819| 91久久精品日日躁夜夜躁国产|