转:http://blog.csdn.net/kof2001kop/article/details/7233844
BS_OWNERDRAW用于自绘按钮,通常与WM_CTLCOLORBTN消息连用,如下:
- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static HWND button0;
- switch (message)
- {
- case WM_CREATE:
- button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 20, 20, 400, 200,
- hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
- return 0;
- case WM_CTLCOLORBTN:
- return (LRESULT)CreateSolidBrush(RGB(0, 255, 0));
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND button0;
switch (message)
{
case WM_CREATE:
button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 20, 20, 400, 200,
hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
return 0;
case WM_CTLCOLORBTN:
return (LRESULT)CreateSolidBrush(RGB(0, 255, 0));
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
上述代码的结果会显示出一个绿色的按钮。
但如果想在按钮上显示一个位图或图标,则不能使用BS_OWNERDRAW,而要用BS_ICON或BS_BITMAP,并和SendMessage函数连用,如下:
- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static HWND button0;
- switch (message)
- {
- case WM_CREATE:
- button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 20, 20, 400, 200,
- hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
- SendMessage(button0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, IDI_ERROR));
- return 0;
- case WM_CTLCOLORBTN: //因为没有了BS_OWNERDRAW,所以被忽略了
- return (LRESULT)CreateSolidBrush(RGB(0, 255, 0)); //不起任何作用
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND button0;
switch (message)
{
case WM_CREATE:
button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 20, 20, 400, 200,
hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
SendMessage(button0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, IDI_ERROR));
return 0;
case WM_CTLCOLORBTN: //因为没有了BS_OWNERDRAW,所以被忽略了
return (LRESULT)CreateSolidBrush(RGB(0, 255, 0)); //不起任何作用
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
上述代码会显示出一个带有错误标记的按钮,而WM_CTLCOLORBTN的触发标志是按钮被重绘,因为没有了BS_OWNERDRAW,所以按钮不能被重绘,即WM_CTLCOLORBTN消息不会被触发。
但如果在上述代码中,再加入BS_OWNERDRAW,那么按钮会既有位图,又有自绘颜色吗?
即:
- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static HWND button0;
- switch (message)
- {
- case WM_CREATE:
- button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | BS_ICON, 20, 20, 400,
- 200, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
- SendMessage(button0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, IDI_ERROR)); //因为有了BS_OWNERDRAW,导致不起作用
- return 0;
- case WM_CTLCOLORBTN: //因为有了BS_OWNERDRAW,再次被触发
- return (LRESULT)CreateSolidBrush(RGB(0, 255, 0));
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND button0;
switch (message)
{
case WM_CREATE:
button0 = CreateWindow(L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | BS_ICON, 20, 20, 400,
200, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
SendMessage(button0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, IDI_ERROR)); //因为有了BS_OWNERDRAW,导致不起作用
return 0;
case WM_CTLCOLORBTN: //因为有了BS_OWNERDRAW,再次被触发
return (LRESULT)CreateSolidBrush(RGB(0, 255, 0));
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
上述代码的结果是显示一绿色的按钮,而按钮上不见任何的位图。所以,如果在创建按钮的窗口句柄时,在CreateWindow中使用了BS_OWNERDRAW,那么就不能用SendMessage函数在按钮上载入位图或图标了,即使有BS_ICON也不能载入。
PS: 在WM_CTLCOLORBTN内所做的一切代码,只与设备环境句柄(HDC)有关,如果尝试通过窗口句柄(HWND)来更改什么,例如用SetWindowText(用到hwnd)来改变按钮内文字,都将无效或陷入死循环。