I have a TWinControl
that needs to catch WM_POWERBROADCAST
messages, but they never seem to reach it despite adding the message handler to the control's VCL_MESSAGE_MAP
. I've also tried a custom WndProc()
and that also never receives these messages. Other messages are working fine.
I can catch the message successfully in the main form, but it's never passed to my controls.
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_PAINT, TMessage, WMPaint); // Works
VCL_MESSAGE_HANDLER(WM_ERASEBKGND, TMessage, WMEraseBackground); // Works
VCL_MESSAGE_HANDLER(WM_POWERBROADCAST, TMessage, WMPower); // Doesn't work!
END_MESSAGE_MAP(inherited);
WM_POWERBROADCAST
is sent only to top-level windows, never to child windows. So, you have a few choices:
TApplication
window by using the TApplication.HookMainWindow()
method. Be sure to remove the hook when your WinControl is destroyed.__fastcall TMyControl::TMyControl(TComponent *Owner)
: TWinControl(Owner)
{
Application->HookMainWindow(&AppHook);
}
__fastcall TMyControl::~TMyControl()
{
Application->UnhookMainWindow(&AppHook);
}
bool __fastcall TMyControl::AppHook(TMessage &Message)
{
if (Message.Msg == WM_POWERBROADCAST)
{
// ...
}
return false;
}
TForm
window, either by applying a MESSAGE_MAP
to the Form class, or by overriding the Form's virtual WndProc()
method, and then have the From forward the message to your WinControl.BEGIN_MESSAGE_MAP
...
VCL_MESSAGE_HANDLER(WM_POWERBROADCAST, TMessage, WMPowerBroadcast);
END_MESSAGE_MAP(inherited);
...
void __fastcall TForm1::WMPowerBroadcast(TMessage &Message)
{
inherited::Dispatch(&Message);
MyControl->Perform(Message.Msg, Message.WParam, Message.LParam);
}
Or:
void __fastcall TForm1::WndProc(TMessage &Message)
{
inherited::WndProc(Message);
if (Message.Msg == WM_POWERBROADCAST)
MyControl->Perform(Message.Msg, Message.WParam, Message.LParam);
}
AllocateHWnd()
function.private:
HWND FPowerWnd;
void __fastcall PowerWndProc(TMessage &Message);
...
__fastcall TMyControl::TMyControl(TComponent *Owner)
: TWinControl(Owner)
{
FPowerWnd = AllocateHWnd(&PowerWndProc);
}
__fastcall TMyControl::~TMyControl()
{
DeallocateHWnd(FPowerWnd);
}
void __fastcall TMyControl::PowerWndProc(TMessage &Message)
{
if (Message.Msg == WM_POWERBROADCAST)
{
// ...
}
else
{
Message.Result = ::DefWindowProc(FPowerWnd, Message.Msg, Message.WParam, Message.LParam);
}
}