【发布时间】:2016-04-22 14:15:40
【问题描述】:
我想,我的问题是相当常见的:当第二个实例运行时,在我的应用程序的第一个实例中打开一个文件(例如,通过在资源管理器中打开一个关联文件)。
我在 Windows 上实现此功能的方式是使用 SendMessage Win API 并通过在 Qt 窗口中重新实现 winEvent 来接收消息。这在 Qt4 上运行良好。但由于某种原因,在我将应用程序更新到 Qt 5 后,它完全停止工作。
我编写了一个最小的测试(见下文)来重现该行为:在 Qt 4 上也很好,但在 Qt 5 上不起作用(未收到消息)。我正在使用mingw32 (gcc) 以防万一。我对 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 );
}
【问题讨论】:
-
我认为 Qt5 中
winEvent(MSG * message, long * result)已被nativeEvent(const QByteArray &eventType, void *message, long *result)取代,这可以解释为什么您没有收到消息 -
Q_DECL_OVERRIDE makro 是避免@AlexisP 这类问题的有用工具。指着。请注意,它需要一个支持 C++11 的编译器。
-
现在我觉得有点尴尬,这确实是问题所在!我必须养成总是添加“覆盖”(我使用 C++11)来检测此类问题的习惯。非常感谢两位,请随时写一个回复,以便我接受。
-
另外,只要 SendMessage 是程序中的最后一条语句,您的示例可能还可以,但通常从不使用 Send 而使用 PostMessage 进行进程间甚至线程间通信。
-
我的意思是“覆盖”关键字!掌心。那就是总是正确地重载虚函数。