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

天下

記錄修行的印記

有關窗口繪制的消息整理

窗口繪制有關的消息整理
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>
            亚洲视频www| 亚洲午夜一区| 免费观看成人网| 久久久久久久久岛国免费| 国产一区999| 欧美成人精品1314www| 欧美成人四级电影| 亚洲一区二区久久| 午夜免费日韩视频| 亚洲国产你懂的| 亚洲九九爱视频| 国产精品综合| 亚洲二区视频| 欧美日韩一区二区三区在线| 欧美在线免费观看| 麻豆精品国产91久久久久久| 夜夜嗨av一区二区三区四区| 亚洲在线成人| 亚洲国产高清视频| 亚洲视频欧美视频| 亚洲国产成人av好男人在线观看| 日韩网站在线| 国内久久精品视频| 日韩一级黄色片| 永久久久久久| 一区二区三区高清视频在线观看| 在线观看91久久久久久| 99视频国产精品免费观看| 国产精品亚洲欧美| 亚洲美女淫视频| 亚洲大片av| 亚洲先锋成人| 亚洲精品孕妇| 久久精品日产第一区二区三区| 亚洲作爱视频| 老司机一区二区| 久久成人资源| 国产精品久久久久aaaa| 欧美激情第9页| 国内成人在线| 亚洲视频在线免费观看| 亚洲精品一区二区三区四区高清| 午夜精品久久久久久久99樱桃| 亚洲精品欧美| 免费在线观看精品| 久久久亚洲综合| 国产九区一区在线| 亚洲午夜成aⅴ人片| 一区二区三区日韩精品视频| 美女视频一区免费观看| 久久久五月天| 激情欧美一区二区三区在线观看| 亚洲一区在线播放| 午夜精品福利电影| 欧美视频在线观看| 一本久久a久久精品亚洲| 日韩一级大片在线| 欧美精品免费在线观看| 亚洲盗摄视频| 亚洲精品色婷婷福利天堂| 美女爽到呻吟久久久久| 亚洲第一精品久久忘忧草社区| 亚洲丰满在线| 男女激情视频一区| 亚洲日本免费| 亚洲一级黄色av| 国产精品免费一区豆花| 亚洲一区二区欧美| 久久精品国产第一区二区三区最新章节 | 国产一区av在线| 欧美在线视频一区二区| 久久久久国色av免费观看性色| 国内一区二区三区在线视频| 久久久久久久波多野高潮日日 | 欧美一级片久久久久久久| 国产精品日韩电影| 性欧美8khd高清极品| 久久夜色撩人精品| 亚洲日本欧美天堂| 欧美日韩一区二区免费在线观看 | 91久久精品日日躁夜夜躁国产| 亚洲精品乱码久久久久久日本蜜臀 | 久久婷婷蜜乳一本欲蜜臀| 免费观看成人鲁鲁鲁鲁鲁视频| 1000部精品久久久久久久久| 欧美成人午夜激情视频| av成人免费观看| 欧美一区三区三区高中清蜜桃| 好吊妞这里只有精品| 欧美大色视频| 亚洲一级黄色片| 欧美v亚洲v综合ⅴ国产v| 亚洲美女视频在线免费观看| 国产精品国产三级国产aⅴ9色 | 美女在线一区二区| 亚洲私人影院在线观看| 国产亚洲欧美日韩在线一区| 欧美成人午夜激情视频| 亚洲欧美激情在线视频| 嫩草国产精品入口| 亚洲欧美国产另类| 亚洲国产小视频| 国产精品免费电影| 牛牛影视久久网| 午夜精品免费在线| 日韩一级不卡| 亚洲电影一级黄| 久久精品免费电影| 亚洲网址在线| 亚洲国产精品ⅴa在线观看| 国产精品三级久久久久久电影| 久久综合色影院| 欧美一区二区三区视频免费| 亚洲精品久久久久久下一站 | 一个色综合导航| 免费久久99精品国产自| 欧美在线视频观看免费网站| av不卡在线看| 亚洲日本成人女熟在线观看| 国产在线精品二区| 国产精品久久久久久久久婷婷 | 欧美午夜一区二区三区免费大片 | 国产亚洲精品成人av久久ww| 欧美日韩精品一区| 欧美凹凸一区二区三区视频| 久久国产精品久久国产精品| 亚洲视频1区| 99精品黄色片免费大全| 亚洲精品乱码视频| 91久久精品一区二区别| 欧美高清不卡| 欧美成人在线免费观看| 美女诱惑一区| 美女性感视频久久久| 久久久之久亚州精品露出| 欧美一区二区在线免费观看| 午夜在线一区二区| 先锋影音网一区二区| 国内一区二区在线视频观看| 久久不射网站| 国产午夜久久| 久久综合网络一区二区| 亚洲人永久免费| 欧美激情第8页| 亚洲国产精品激情在线观看| 欧美激情免费在线| 亚洲黄网站黄| 亚洲人成毛片在线播放| 亚洲美女中出| 亚洲在线黄色| 欧美在线视频一区二区| 这里只有精品在线播放| 亚洲视频二区| 欧美在线日韩在线| 久久综合国产精品| 久久最新视频| 91久久久精品| 亚洲欧美国产日韩中文字幕| 欧美中文在线视频| 免费短视频成人日韩| 欧美久久视频| 国产日韩欧美不卡在线| 在线精品福利| 一区二区日韩欧美| 久久精品视频免费观看| 欧美高清在线视频观看不卡| 99视频精品全部免费在线| 亚洲欧美视频在线观看| 六月婷婷久久| 欧美午夜女人视频在线| 韩国一区二区在线观看| 一区二区三区偷拍| 久久久久国内| 99综合在线| 久久久久国产免费免费| 欧美日韩国产片| 国产综合视频在线观看| 99re热这里只有精品免费视频| 午夜在线成人av| 欧美国产精品中文字幕| 亚洲综合色婷婷| 欧美激情一区二区三区蜜桃视频| 国产精品一区久久久久| 亚洲韩国日本中文字幕| 亚洲欧美日韩精品综合在线观看| 久久伊伊香蕉| 亚洲中字在线| 欧美激情一区二区三区高清视频| 国产亚洲女人久久久久毛片| 99精品视频免费全部在线| 久久九九国产精品怡红院| 日韩写真视频在线观看| 久色婷婷小香蕉久久| 国产亚洲成av人片在线观看桃| 日韩一级大片| 欧美大片va欧美在线播放| 欧美亚洲一区在线| 国产精品国产三级国产普通话蜜臀 | 99www免费人成精品| 久久一区二区三区四区|