我想在 C++Builder 中为
TButton
控件着色。我正在尝试遵循我发现的建议使用 SetWindowLong()
为我的 BS_OWNERDRAW
控件启用 TButton
样式的信息,然后捕获 WM_DRAWITEM
消息。
虽然我确实看到了该按钮的消息,但从未出现过
WM_DRAWITEM
消息。
我正在使用以下代码:
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
OldButtonWndProc = bTest->WindowProc;
bTest->WindowProc = NewButtonWndProc;
SetWindowLong(bTest->Handle,
GWL_STYLE,
GetWindowLong(bTest->Handle,
GWL_STYLE) | BS_OWNERDRAW);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::NewButtonWndProc(TMessage &AMsg)
{
if (AMsg.Msg == WM_DRAWITEM)
{
Beep();
}
else
{
OldButtonWndProc(AMsg); // default handling.
}
}
//---------------------------------------------------------------------------
我只能假设
BS_OWNERDRAW
标志没有发挥其魔力。我在前后捕获了 GWL_STYLE
以确保设置了 BS_OWNERDRAW
标志。据我所知,确实如此。我还检查了没有设置其他 BS
标志,但它们没有设置。
也许
GWL_STYLE
不是设置这个标志的地方?
您应该使用
(Get|Set)WindowLongPtr()
,否则您的代码可能无法在 64 位版本中正常工作。
无论如何,
BS_OWNERDRAW
标志都工作正常。 WM_DRAWITEM
消息只是被发送到按钮的 父窗口,这就是为什么您在子类中看不到它。 您需要改为处理 CN_DRAWITEM
消息,父窗口会将其反射回按钮。
另外,请注意,如果按钮(或父表单)在运行时动态地重新创建其
HWND
(这可能发生),您将丢失 BS_OWNERDRAW
样式,除非您在按钮的新 HWND
上重置它。 处理这种情况的更好方法是从 TButton
派生一个新类,并让它覆盖虚拟 CreateParams()
和 WndProc()
方法,例如:
class TMyButton : public TButton
{
protected:
void __fastcall CreateParams(TCreateParams &Params);
void __fastcall WndProc(TMessage &Message);
};
void __fastcall TMyButton::CreateParams(TCreateParams &Params)
{
TButton::CreateParams(Params);
Params.Style |= BS_OWNERDRAW;
}
void __fastcall TMyButton::WndProc(TMessage &Message)
{
if (Message.Msg == CN_DRAWITEM)
{
Beep();
}
else
{
TButton::WndProc(Message);
}
}
或者,您可以只使用
TBitBtn
来代替,它已经应用了 BS_OWNERDRAW
样式。