我对C++和Windows API还很陌生。
我想不出如何使用WM_CTLCOLORBTN
更改按钮的背景色,同时在按钮上有位图。当我尝试这样做时,程序崩溃。
我创建了一个按钮,如下所示:
HINSTANCE hInstance = GetModuleHandle(NULL);
HWND hbutton = CreateWindow(L"BUTTON", NULL, WS_VISIBLE | WS_CHILD | BS_BITMAP | BS_PUSHBUTTON, 15, 202.5, 96.5, 72.5, hWnd, (HMENU)301, hInstance, NULL);
在WndProc
函数中,我编写了:
case WM_CTLCOLORBTN:
switch (((LPNMHDR)lParam) -> code)
{
MessageBox(hWnd, L"made it inside of the switch statement", L"Debug", 1);
}
我也试过:
case WM_CTLCOLORBTN:
LPNMHDR button = (LPNMHDR)lParam;
if(button->idfrom == 301 && button->code == NM_CUSTOMDRAW)
{
}
此外,我还试过:
case CDDS_PREERASE:
LPNMHDR button = (LPNMHDR)lParam;
if(button->idfrom == 301 && button->code == NM_CUSTOMDRAW)
{
}
此外,我还尝试:
case WM_NOTIFY:
MessageBox(hWnd, L"Code in wm_notify got ran", L"Debug", 1);
上面的代码不会导致消息框出现,因此假定它从未运行过。
所有这些方法都导致了程序崩溃。
我在其他一些帖子中看到人们把他们的代码放在WM_NOTIFY
中,但这会导致代码根本无法运行。
有人知道我做错了什么吗?
1条答案
按热度按时间icnyk63a1#
首先,在创建系统定义的窗口类时不需要指定
HINSTANCE
,因此,可以将hInstance
参数设置为NULL
。第二,所有消息处理程序都是错误的:
WM_CTLCOLORBTN
消息的lParam
参数是HWND
窗口句柄,而不是LPNMHDR
结构指针。NMHDR
结构仅在WM_NOTIFY
消息中使用。CDDS_PREERASE
不是窗口消息。它是NM_CUSTOMDRAW
消息使用的绘图阶段的值。CDDS_PREERASE
具有数值3,该数值与WM_MOVE
窗口消息的值相同,WM_MOVE
窗口消息的lParam
包含X/Y坐标,而不是LPNMHDR
指针。WM_COMMAND
消息传送到按钮的父窗口。只有3个按钮通知使用WM_NOTIFY
消息传送到父窗口-BCN_DROPDOWN
、BCN_HOTITEMCHANGE
和NM_CUSTOMDRAW
。前2个不适用于您的按钮示例。第3个仅适用于您的应用具有Comctl32.dll v6 enabled的情况。在这种情况下,lParam
参数是LPNMCUSTOMDRAW
结构指针,而不是LPNMHDR
指针。现在,
WM_CTLCOLORBTN
文档说明:参数
w参数
一个HDC,它指定按钮的显示上下文的句柄。
l参数
HWND,指定按钮的句柄。
返回值
如果应用程序处理这个消息,它必须返回一个画笔的句柄。系统使用画笔来绘制按钮的背景。
所以,不妨试试类似这样的方法:
或者:
但是,
WM_CTLCOLORBTN
文档还指出:但是,只有所有者描述的按钮响应处理此消息的父窗口。
...
默认情况下,
DefWindowProc
函数为按钮选择默认系统颜色。**具有BS_PUSHBUTTON
、BS_DEFPUSHBUTTON
或BS_PUSHLIKE
样式的按钮不使用返回的画笔。具有这些样式的按钮始终使用默认系统颜色绘制。**绘制按钮需要几种不同的画笔-表面、突出显示、和阴影-但WM_CTLCOLORBTN
消息只允许返回一个画笔。**要为按钮提供自定义外观,请使用所有者描述的按钮。**有关详细信息,请参见Creating Owner-Drawn Controls。因此,您应该将
BS_OWNERDRAW
样式添加到按钮中,在这种情况下,您需要处理WM_DRAWITEM
消息,而不是按照您想要的方式自定义绘制按钮。