为啥 ChangeWindowMessageFilter 会导致 Qt 崩溃?

Posted

技术标签:

【中文标题】为啥 ChangeWindowMessageFilter 会导致 Qt 崩溃?【英文标题】:Why does ChangeWindowMessageFilter cause Qt to crash?为什么 ChangeWindowMessageFilter 会导致 Qt 崩溃? 【发布时间】:2013-11-27 20:04:23 【问题描述】:

为什么下面的程序会崩溃?

#include <QApplication>

#include <windows.h>
#include <QFrame>


uint MSGFLT_ADD = 1;
uint WM_COPYGLOBALDATA = 0x0049;

int main(int argc, char *argv[])

    BOOL (*ChangeWindowMessageFilter)(UINT,DWORD) = NULL;

    HINSTANCE hDLL = LoadLibraryA("User32.dll");               // Handle to DLL
    if (hDLL != NULL)
        ChangeWindowMessageFilter = (BOOL (*)(UINT,DWORD))GetProcAddress(hDLL, "ChangeWindowMessageFilter");
    

    if (ChangeWindowMessageFilter != NULL)
        if (!(*ChangeWindowMessageFilter)(WM_DROPFILES, MSGFLT_ADD))
            printf("Failed to add exception for WM_DROPFILES\n");
        
        if (!(*ChangeWindowMessageFilter)(WM_COPYDATA, MSGFLT_ADD))
            printf("Failed to add exception for WM_COPYDATA");
        
        if (!(*ChangeWindowMessageFilter)(WM_COPYGLOBALDATA, MSGFLT_ADD))
            printf("Failed to add exception for WM_COPYGLOBALDATA");
        
        printf("Added filters\n");
        fflush(0);
    
    if (hDLL != NULL)
        FreeLibrary(hDLL);
    

    QApplication a(argc, argv);
    QFrame w; //debug crashes here
    w.show();

    return a.exec();

QFrame::QFrame(QWidget* parent, Qt::WindowFlags f)
    : QWidget(*new QFramePrivate, parent, f) //on this line in particular

    Q_D(QFrame);
    d->init();

编辑:

if (!(*ChangeWindowMessageFilter)(WM_COPYDATA, MSGFLT_ADD)) //if i disable this everything works
    printf("Failed to add exception for WM_COPYDATA");

【问题讨论】:

您的输出设置为 64 位还是 32 位? 这是个好问题,它是 32 位的。我可能正在加载 64 位版本吗? 您的 Windows 是 64 位的吗? @Extrakun 这不是问题,请参阅编辑 【参考方案1】:
   BOOL (*ChangeWindowMessageFilter)(UINT,DWORD) = NULL;

您的函数指针声明错误。 Winapi 函数总是 __stdcall。毫无疑问,您的编译器使用默认值 __cdecl。当您通过函数指针进行调用时,您得到的堆栈不平衡可能会产生许多副作用。如果您使用 MSVC++ 并运行调试版本,那么您将始终获得即时诊断。修复:

   BOOL (WINAPI * ChangeWindowMessageFilter)(UINT,DWORD) = NULL;

Fwiw,如果这是为了将拖放功能启用到提升的程序中,那么只需删除所有这些,它将无法正常工作。 D+D 是基于 COM 的,它不使用消息。

【讨论】:

啊,谢谢。它是为了启用 DnD(但没用,哈哈)。是否有解决方法来启用它? 谷歌“uiaccess = true”

以上是关于为啥 ChangeWindowMessageFilter 会导致 Qt 崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?