BEGIN_MESSAGE_MAP vs 调度 vs WndProc

BEGIN_MESSAGE_MAP vs Dispatch vs WndProc

提问人:Coder12345 提问时间:11/15/2023 最后编辑:Coder12345 更新时间:11/15/2023 访问量:37

问:

在阅读了大量内容后,我得出的结论是,这 3 个本质上是处理自定义消息的相同内容:

使用 BEGIN_MESSAGE_MAP 宏:

#define WM_CUSTOM_MESSAGE WM_APP + 12345

BEGIN_MESSAGE_MAP
    VCL_MESSAGE_HANDLER(WM_CUSTOM_MESSAGE, TMessage, WMCustomMessageHandler);
END_MESSAGE_MAP(TForm)

void TForm1::WMCustomMessageHandler(TMessage &message)
    {
    // <code to handle custom message here>
    }

或者扩展它并直接覆盖 Dispatch()(与上面的作用相同):

void __fastcall TForm1::Dispatch(void* message)
    {
    switch ((TMessage*)message->Msg)
        {
        case WM_CUSTOM_MESSAGE: // <code to handle custom message here>
                                break;

        default:                TForm::Dispatch(message);
                                break; 
        }
    }

或覆盖 WndProc:

void __fastcall TForm1::WndProc(TMessage &message)
    {
    switch (message.Msg)
        {
        case WM_CUSTOM_MESSAGE: // <code to handle custom message here>
                                message.Result = 0;
                                break; 

        default:                TForm::WndProc(message);
                                break;
        }
    }

在此示例中,使用一个比另一个有优势吗?从我收集到的信息来看,前两种方法级别较高,而最后一种方法级别较低,尽管不确定它会有什么区别。

我之所以问,是因为我收到WM_SETICON消息,当我的程序退出时,偶尔会因读取地址00000018而崩溃(崩溃跟踪到 )。这可能是我的程序中的错误,但也可能是我正在使用的 RAD Studio 10.4.2 中的错误。但是,当我使用 BEGIN_MESSAGE_MAP 时,这似乎不是问题,我切换到 WndProc 以提高可读性。TForm::WndProc(message);

解决此问题的另一种方法可能是在退出程序(事件)之前删除 WndProc 为默认值(例如保存然后),我发现这是不必要的,因为上面的代码实际上与原始 WndProc 没有任何不同,当它崩溃时没有处理自定义消息,因为它崩溃了 WM_SETICON,或者我在这里弄错了?DefaultWndProcthis->WindowProc = DefaultWndProc;OnClose

C++生成器 WNDPROC系列 Windows消息

评论

3赞 Remy Lebeau 11/15/2023
WindowProc默认指向,并调用任何未处理的消息。所以真的没有什么区别。 只是先得到消息。但是,地址 0 附近的访问冲突通常意味着正在取消引用空指针,这更有可能是你自己的代码中的错误,而不是 VCL 代码中的错误。WndProcWndProc()Dispatch()WndProc()

答: 暂无答案