【问题标题】:Catching WM_POWERBROADCAST in a TWinControl child control在 TWinControl 子控件中捕获 WM_POWERBROADCAST
【发布时间】:2022-09-13 03:32:09
【问题描述】:

我有一个TWinControl 需要捕获WM_POWERBROADCAST 消息,但尽管将消息处理程序添加到控件的VCL_MESSAGE_MAP,但它们似乎从未到达它。我还尝试了自定义 WndProc() 并且也从未收到这些消息。其他消息工作正常。

我可以在主窗体中成功捕获消息,但它从未传递给我的控件。

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);

【问题讨论】:

  • 最佳猜测:该消息不会发送到您的控件,但可能发送到它所在的表单或应用程序。尝试在那里捕捉它(只是为了验证或不验证)。
  • 是的,消息到达表单:控件可以通知表单它想要消息吗? (表格可以将消息显式转发给控件,但这反而会颠倒架构。
  • @Roddy没有机制可以自动处理。您必须自己编写代码。

标签: c++builder vcl


【解决方案1】:

WM_POWERBROADCAST 只发送到顶级窗口,从不发送到子窗口。所以,你有几个选择:

  • 让您的 WinControl 使用TApplication.HookMainWindow() 方法拦截发送到隐藏的TApplication 窗口的消息。当你的 WinControl 被销毁时,一定要移除钩子。
__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 窗口的消息,通过将MESSAGE_MAP 应用到Form 类,或者通过覆盖Form 的虚拟WndProc() 方法,然后让From 将消息转发到您的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);
}

或者:

void __fastcall TForm1::WndProc(TMessage &Message)
{
    inherited::WndProc(Message);
    if (Message.Msg == WM_POWERBROADCAST)
        MyControl->Perform(Message.Msg, Message.WParam, Message.LParam);
}
  • 让您的 WinControl 使用 RTL 的 AllocateHWnd() 函数创建自己的隐藏顶层窗口。
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);
    }
}

【讨论】:

  • 谢谢雷米,#1 对我来说很好用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
相关资源
最近更新 更多