我认为,我的问题是相当常见的:在第二个实例运行时打开我的应用程序的第一个实例中的文件(例如,通过在资源管理器中打开一个相关文件)。
我在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 );
}
答案 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的编译器,那么您将无法获得任何诊断信息。