1. 程式人生 > >MFC呼叫QT編寫的DLL動態庫

MFC呼叫QT編寫的DLL動態庫

MFC呼叫QT編寫的動態庫,如果QT dll裡面用到了一些訊息迴圈相關的介面,比如QTimer,QEventLoop等,會由於沒有QAppAplication而導致這些調用出現異常,如果DLL裡面沒有介面顯示的話,解決方法還是相對比較簡單的。主要思想是使用windows API hook函式,將MFC的訊息丟入QT去繞一圈,然後再交由MFC去處理,這樣QT便有啟用處理自己的訊息,如果本生已經是QT應用,則不做任何處理。

    static bool g_bOwnApplication = false;
    static HINSTANCE g_hInstance;

    BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/
) { if (dwReason == DLL_PROCESS_ATTACH) g_hInstance = hInstance; if (dwReason == DLL_PROCESS_DETACH && g_bOwnApplication) delete qApp; return TRUE; } bool InitSdk() { if ( !g_bOwnApplication ) g_bOwnApplication = CMfcApp::pluginInstance(g_hInstance); }

這裡放在InitSdk裡面去呼叫CMfcApp::pluginInstance而不在dllmain裡面去掉用,主要是防止靜態載入導致的QApplication衝突問題。

下面是CMfcApp的實現:

//.h
#pragma once
//for MFC use qt dll
//this solution from qt-solutions git-hub

#include <QCoreApplication>
#include <qnamespace.h>
#include <windef.h>

class CMfcApp
{
public:
    CMfcApp();
    ~CMfcApp();

    static
LRESULT CALLBACK QtFilterProc(int nCode, WPARAM wParam, LPARAM lParam); static bool pluginInstance(Qt::HANDLE plugin); private: static HHOOK s_hHook; };
//.cpp
#include "MfcApp.h"
#include <WinBase.h>
#include <WinUser.h>
#include <processthreadsapi.h>


HHOOK CMfcApp::s_hHook = NULL;

LRESULT CALLBACK CMfcApp::QtFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (qApp) {
        // don't process deferred-deletes while in a modal loop
        qApp->sendPostedEvents(0, -1);
    }

    return CallNextHookEx(s_hHook, nCode, wParam, lParam);
}

CMfcApp::CMfcApp()
{
}


CMfcApp::~CMfcApp()
{
}

bool CMfcApp::pluginInstance(Qt::HANDLE plugin)
{
    if (qApp)
        return false;

    s_hHook = SetWindowsHookEx(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
    int argc = 0;
    (void)new QCoreApplication(argc, 0);

    if (plugin) {
        char filename[MAX_PATH] = { 0 };
        if (GetModuleFileNameA((HINSTANCE)plugin, filename, MAX_PATH))
            LoadLibrary(filename);
    }
    return true;
}