【问题标题】:mfc - sendmessage/postmessage with custom parametersmfc - 使用自定义参数发送消息/发布消息
【发布时间】:2013-03-25 18:03:45
【问题描述】:

我想在 MFC 中有一个消息处理程序,它接受我在消息映射中定义的任何参数。

例如,

static UINT UWM_STATUS_MSG = RegisterWindowMessage("Status message");
static UINT UWM_GOT_RESULT= RegisterWindowMessage("Result has been obtained");

//{{AFX_MSG(MyClass)
    afx_msg void OnCustomStringMessage(LPCTSTR);
    afx_msg void OnStatusMessage();
//}}AFX_MSG


BEGIN_MESSAGE_MAP(MyClass, CDialog)
    //{{AFX_MSG_MAP(MyClass)
        ON_REGISTERED_MESSAGE(UWM_STATUS_MSG, OnStatusMessage)
        ON_REGISTERED_MESSAGE(UWM_GOT_RESULT, OnCustomStringMessage)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void MyClass::OnCustomStringMessage(LPCTSTR result)
{
    m_result.SetWindowText(result);
}

void MyClass::OnStatusMessage()
{
    // Do something
}

DWORD WINAPI MyClass::thread(LPVOID lParam)
{
    char result[256] = { 0 };
    SendMessage(UWM_STATUS_MSG);

    // Do some stuff and store the result

    PostMessage(UWM_GOT_RESULT, result);
}

这样的事情可能吗?

【问题讨论】:

    标签: c++ mfc sendmessage


    【解决方案1】:

    通过 ON_MESSAGE 或 ON_REGISTERED_MESSAGE 调用的成员函数的签名必须是:

    afx_msg LRESULT OnMyFunction(WPARAM p1, LPARAM p2);

    您必须使用强制转换运算符来处理。

    因此你应该这样写:

    ...
    afx_msg LRESULT OnCustomStringMessage(WPARAM p1, LPARAM p2);
    ...
    
    LRESULT MyClass::OnCustomStringMessage(WPARAM p1, LPARAM p2)
    {
      LPCTSTR result = (LPCTSTR)p1 ;
       m_result.SetWindowText(result);
    }
    
    DWORD WINAPI MyClass::thread(LPVOID lParam)
    {
        static char result[256] = { 0 };   // we need a static here
                                           // (see explanations from previous answers)
        SendMessage(UWM_STATUS_MSG);
    
        // Do some stuff and store the result
    
        PostMessage(UWM_GOT_RESULT, (WPARAM)result);
    }
    

    如果 MyClass::thread 打算从多个不同的线程调用,您需要以更复杂的方式处理 result 数组,只需将其声明为静态,例如在 MyClass 中分配数组::thread 并按照 user2173190 的回答建议在 OnCustomStringMessage 中删除它。

    【讨论】:

    • 所以没有办法绕过将WPARAMLPARAM 变量作为参数?我只是认为所有这些强制转换和额外的变量都是不必要的。我想知道是否还有其他更适合我的任务的消息处理方法。因此问题。不过感谢您的回答!
    • 另外,关于result,是的。但这只是我想要的一些小演示。我会处理这一切的。谢谢:)
    • 不,您不能将其他类型的参数传递给此类成员函数。如果您担心额外的变量,您也可以编写“m_result.SetWindowText((LPCTSTR)p1)”。
    • 请注意 OnMessage* 函数的原型必须是“afx_msg LRESULT OnCustomStringMessage(WPARAM p1, LPARAM p2)”。根据编译器,即使原型错误,您的源代码也可能会编译,然后您可能会在运行时遇到奇怪的崩溃(发生在我身上)。
    • 是的。奇怪的崩溃也发生在我身上。也仅在发布模式下!哈哈
    【解决方案2】:

    尝试使用 WM_USER 消息作为您的自定义消息,并通过覆盖它在 OnMessage 方法中处理它。要了解 WM_USER 消息,请参阅 here

    【讨论】:

    • ON_MESSAGE 会有同样的问题。它期望消息处理程序接受 WPARAMLPARAM 类型的参数。
    【解决方案3】:

    如果您将 WM_USER 以下范围内的消息发送到异步消息函数(PostMessage、SendNotifyMessage 和 SendMessageCallback),则其消息参数不能包含指针。否则,操作将失败。这些函数将在接收线程有机会处理消息之前返回,发送方将在内存使用之前释放内存。

    PostMessage 的消息参数可以包含指针 您可以包含指针作为参数。将它们转换为整数,不要在触发 PostMessage 的线程或函数上释放或释放它们,而是在接收线程或函数上释放或释放它们。 只需确保在使用指针时,您只对一条消息使用一种指针类型,不要将指向不同对象的指针与同一条消息混用。

    http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms644944(v=vs.85).aspx

    【讨论】:

    • 我可以传递指针,正确。但是如果我想传递对象或者什么都不传递怎么办?这是不可能的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 2021-07-18
    • 1970-01-01
    • 2020-02-07
    相关资源
    最近更新 更多