在Windows和Qt5上与SendMessage进行进程间通信

时间:2016-04-22 14:15:40

标签: c++ windows qt winapi

我认为,我的问题是相当常见的:在第二个实例运行时打开我的应用程序的第一个实例中的文件(例如,通过在资源管理器中打开一个相关文件)。

我在Windows上实现此功能的方法是使用SendMessage Win API并通过在Qt窗口中重新实现winEvent来接收消息。这在Qt4上运作良好。但出于某种原因,在我将我的应用更新到Qt 5后,它完全停止了工作。

我已经编写了一个最小化测试(见下文)来重现行为:在Qt 4上也没问题,但在Qt 5上没有工作(没有收到消息)。我正在使用mingw32gcc),以防它有任何区别。我对Windows API非常不熟悉,如果有人能解释这种奇怪的行为,我会很高兴。

非常感谢!

server.c:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winuser.h>
#include <windef.h>

#include <QApplication>
#include <QLabel>
#include <QDialog>

#include "winmessagelistener.h"

bool WinMessageListener::winEvent( MSG* message, long* result ) {
    if( message->message == WM_COPYDATA ) {
        label->setText( "Message!" );
        // We process the event here
        *result = 0;
        return true;
    }
    else {
        // Give the event to qt
        return false;
    }
}

WinMessageListener::WinMessageListener() : QDialog() {
    setWindowTitle( "blah" );
    label = new QLabel( this );
    label->setText("no message");
}

int main(int argc, char **argv) {
    QApplication app (argc, argv);
        WinMessageListener listener;

    listener.show();

    return app.exec();
}

winmessagelistener.h:

#include <QDialog>
#include <QLabel>

class WinMessageListener : public QDialog {
    Q_OBJECT

    public:
        WinMessageListener();

    private:
        // Override the default event message
        bool winEvent( MSG* message, long* result );
        QLabel* label;
};

client.c:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winuser.h>
#include <windef.h>

#include <iostream>
#include <QString>

const QString WINDOW_TITLE = "blah";

int main(int argc, char **argv) {
    LPCWSTR window_title = (LPCWSTR) WINDOW_TITLE.utf16();
    HWND window_handle_ = FindWindow( NULL, window_title );

    std::cerr << "Window handle = " << window_handle_ << std::endl;

    COPYDATASTRUCT data = { 0, 0, 0 };

    SendMessage( window_handle_, WM_COPYDATA, 0, (LPARAM) &data );
}

1 个答案:

答案 0 :(得分:1)

由于答案可以比评论更好地帮助他人,所以在这里。问题是在Qt5中,函数bool QWidget::winEvent(MSG * message, long * result)不再可用。它已被函数bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)取代,正如documentation

中所述
  

注意:此函数取代Qt 4的事件过滤器函数x11Event(),winEvent()和macEvent()。

请注意,以更一般的方式,正如@Paul R.所说,在评论中,不要忘记使用宏Q_DECL_OVERRIDE,以便让编译器生成错误,如果你的覆盖虚函数什么都不做。在这种情况下,它可以像这样使用:

bool WinMessageListener::winEvent(MSG * message, long * result) Q_DECL_OVERRIDE;

注意:这是一个C ++ 11上下文关键字,因此如果您想使用它,您的编译器需要支持C ++ 11。如果您没有使用支持C ++ 11的编译器,那么您将无法获得任何诊断信息。