我從MSDN瞭解Windows如何處理髮送到特定窗口的WM_PAINT消息。兒童窗口繪畫參考
一件事MSDN似乎並沒有文檔的實際過程,通過該窗口管理器決定哪個窗口應該收到WM_PAINT消息,以及以什麼順序。
據我瞭解的事情(從閱讀雷蒙德陳和MSDN)有與子窗口相關聯的無效區域 - 當子窗口是無效的父窗口上相應的區域被無效。
其WM_PAINT一代混淆我...這一個窗口無效區域被標記爲有效的精確點(尤其是寫入多線程) - 當子窗口被捲入它變得特別有意思。 GetMessage如何決定哪一組窗口(父母+與無效區域相交的子窗口)獲取WM_PAINT消息,以及以何種順序?以及WS_CLIPSIBLINGS,WS_CLIPCHILDREN,WS_EX_COMPOSITED,WS_EX_TRANSPARENT等等如何改變?如果另一個線程在這個過程的中途使頂層窗口的一部分失效,會發生什麼?
,然後在Windows V6.0 +,請問DWM鉤到這個進程?
這是一個C程序示例表明使用WS_EX_COMPOSITED時出現毛刺: -
#include <windows.h>
#include <windowsx.h>
INT delay = 50;
INT nPad = 32;
struct wnd_ctx {
COLORREF base;
char index;
};
HMODULE GetWindowModuleHandle(HWND hwnd){
return (HMODULE)GetWindowLongPtr(hwnd,GWLP_HINSTANCE);
}
struct wnd_ctx* GetContext(HWND hWnd){
struct wnd_ctx* pctx = (LPVOID)GetWindowLongPtr(hWnd,GWLP_USERDATA);
if(!pctx)
{
pctx = malloc(sizeof(struct wnd_ctx));
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)pctx);
}
return pctx;
}
LRESULT CALLBACK wnd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
HBRUSH hbr;
struct wnd_ctx* self;
switch (message){
case WM_LBUTTONUP:
GetClientRect(hWnd,&rect);
rect.top += nPad;
rect.bottom -= nPad;
rect.left += nPad;
rect.right -= nPad;
InvalidateRect(hWnd,&rect,TRUE);
return 0;
case WM_ERASEBKGND:
DefWindowProc(hWnd, message, wParam, lParam);
Sleep(delay);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if(self = GetContext(hWnd)){
hbr = CreateSolidBrush(self->base + ((self->index++ <<5) & 0x7f));
GetClientRect(hWnd,&rect);
FillRect(hdc,&rect,hbr);
DeleteObject(hbr);
}
EndPaint(hWnd, &ps);
Sleep(delay);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM CreateClass(HINSTANCE hInstance,LPCTSTR strClass,COLORREF brush,HICON hIcon){
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc = wnd_WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = hIcon;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(brush);
wcex.lpszMenuName = 0;
wcex.lpszClassName = strClass;
wcex.hIconSm = hIcon;
return RegisterClassEx(&wcex);
}
BOOL CreateWindows(HINSTANCE hInstance, INT nCmdShow, LPCTSTR strTitle){
HWND hWnd, hChild;
ATOM atm;
RECT rect;
DWORD dwStyleEx, dwStyle, dwChildStyle, dwChildStyleEx;
struct wnd_ctx* pctx;
dwStyleEx = WS_EX_COMPOSITED;
dwStyle = WS_OVERLAPPEDWINDOW;//|WS_CLIPCHILDREN;
dwChildStyle = WS_CHILD|WS_VISIBLE;//|WS_CLIPSIBLINGS;
atm = CreateClass(hInstance, TEXT("APPWINDOW"), RGB(0x80,0x80,0x80), LoadIcon(NULL,IDI_APPLICATION));
hWnd = CreateWindowEx(dwStyleEx,(LPCTSTR)atm, strTitle, dwStyle,
CW_USEDEFAULT, 0, 256, 256, NULL, NULL, hInstance, NULL);
pctx = GetContext(hWnd);
pctx->base = RGB(0x00,0xff,0xff);
pctx->index=0;
atm = CreateClass(hInstance,TEXT("CONTROL1"),RGB(0x00,0x80,0x40),0);
GetClientRect(hWnd,&rect);
hChild = CreateWindowEx(0L,(LPCTSTR)atm, TEXT("Top"), dwChildStyle,
rect.right/2, rect.top, rect.right/2, rect.bottom, hWnd, NULL, hInstance, NULL);
pctx = GetContext(hChild);
pctx->base = RGB(0x00,0xff,0x80);
pctx->index=0;
atm = CreateClass(hInstance,TEXT("CONTROL2"),RGB(0x00,0x40,0x80),0);
hChild = CreateWindowEx(0L,(LPCTSTR)atm, TEXT("Bottom"), dwChildStyle,
rect.left, rect.bottom/2, rect.right , rect.bottom/2, hWnd, NULL, hInstance, NULL);
pctx = GetContext(hChild);
pctx->base = RGB(0x00,0x80,0xff);
pctx->index=0;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow){
MSG msg;
CreateWindows(hInstance,nCmdShow,TEXT("Test Child Painting"));
while(GetMessage(&msg, NULL, 0, 0)>0){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
我想知道的一件事就是爲什麼當DWM組合處於活動狀態時,您認爲WS_EX_COMPOSITED不起作用。 – 2011-04-21 11:13:36
嗯,我懷疑它沒有記錄,因爲它不應該*相關*。他們不想承諾以任何特定的順序發送WM_PAINT消息,這是一個非常不尋常的情況,應用程序會關心它們被髮送的順序。實現應該是透明的。你是純粹出於好奇,還是想解決一些特殊問題?就DWM而言,它根本沒有涉及到這個過程。每個頂層窗口都會自動分層並重定向到屏幕外緩衝區。這個緩衝區隨後被傳送到屏幕上。 – 2011-04-21 11:13:59
同意。這是由窗口管理器完成的,這是一個特別沒有文檔的代碼塊。有很多關於它如何工作的軼事證據,但這不是你要求的。把這個問題帶到你想要解決的具體問題的牆上,所以我們不必寫一本關於無證代碼的書。 – 2011-04-21 11:47:22