在MFC中使用Qt生成的DLL

http://doc.qt.digia.com/solutions/4/qtwinmigrate/winmigrate-walkthrough.html(原文地址)

qtwinmigrate-2.8-opensource.zip可以到csdn资源内下载,点此下载 

这个练习是基于MFC生成的程序迁移到Qt的例子,这个程序通过微软Visual Studio的MFC应用程序向导生成。 

入门(Getting Started)

(注:这个例子在文件qtwinmigrate-2.8-opensource\examples\mfc\step1中,而且这例子要用VC6.0或者用Qt Creator才能打开)

先把工程文件 qtmfc1.dsp 导入到VS的工作空间,并且确保这个VS工程可以正常的编译和运行。(在step1中没有找到qtmfc1.dsp,倒是有个qtmfc.dsp)

这个MFC程序有一个使用DLL提供的对话框接口,这个很简接口很简单:DLL导入一个名字是showDialog的C语言风格的函数,这个函数把整个窗口作为父句柄。这个DLL以模态方式显示它的对话框,并且在函数返回后卸载掉。

以下代码是在MFC应用程序的OnAppAbout消息处理函数。(这个消息处理函数就是响应“关于。。。。。”的单击,源代码在step1目录下qtmfc.cpp中)

void WindowsApp::OnAppAbout()                 //这部分的源代码在step1目录下

 {

     HMODULE mod = LoadLibrary("qtdialog.dll" );     

  //这个是测试Qt生成的Dll的部分,先动态载入,再使用导出的函数

     if ( mod )

{

         typedefBOOL(*pShowDialog)(HWND parent);

         pShowDialog showDialog =(pShowDialog)GetProcAddress( mod, "showDialog" );

         if ( showDialog )

             showDialog(theApp.m_pMainWnd->m_hWnd ); 

         FreeLibrary( mod );

     }

else

 {

         CAboutDlg aboutDlg;

         aboutDlg.DoModal();

       }

  }

  如果这个DLL被正确载入并且showDialog()被正确导出,那么导出的函数就会被调用,否则调用显示默认的MFC关于对话框。

插件扩展

(这个工程生成的dll就是上个例子用的那个)

(注:这个例子在文件qtwinmigrate-2.8-opensource\examples\qtdll中,可以用Qt Creator 编译生成dll,也可以添加到vs新建的工程当中去,已经测试过,可以正常使用)

 

示例目录下的qtdll文件下的工程通过QMessageBox类实现了插件接口。为了使用这个类,一个QApplication对象必须在当前进程中存在,而且除了mfc的标准事件派送外,还要有一个Qt的消息循环。

这个DLL也要确保它和其它的基于Qt的DLL能够运行在同一个进程中,甚至进程中可能已经存在一个QApplication对象,并且这个创建QApplication对象的DLL还要继续运行在内在中,防止其它DLL使用内存地址。

上述所列的事情全部被QMFC::pluginInstance()函数解决。这个函数创建一个QApplication对象,并且安装一个能够使Win32标准消息循环和Qt事件循共同工作的消息钩子函数。如果DLL实例作为参数被传递,那么pluginInstance()也会增加这个DLL的使用计数,直到这个进程结束。

 当DLL被加载的时候,这个pluginInstance()也可以用于DllMain入口函数的重载版本。一个静态的变量被用于记录DLL是否和QApplication对象关联。当DLL被卸载后,这个QAplication对象就可以通过全局指针qApp删除了。

     为了使用这个pluginInstance函数和跟它有相关的Qt类,我们需要包含一些头文件。

#include <qmfcapp.h>
 #include <qwinwidget.h>
 
 #include <QtGui/QMessageBox>
 #include <windows.h>
 
//用DllMain()函数就是为了使用hInstance,作为qwinwidget的参数

 BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/
 {
     static bool ownApplication = FALSE; //这部分内容不用更改,使用时直接copy就行
     if ( dwReason == DLL_PROCESS_ATTACH )
         ownApplication = QMfcApp::pluginInstance( hInstance );
     if ( dwReason == DLL_PROCESS_DETACH && ownApplication )
         delete qApp; 
     return TRUE;
 }

然后DLL的接口就通过导出C语言风格的showDialog函数来实现。QWinWidget类可以在这个时候使用,用于存放对话框,并且关联上Qt 对话框。

extern "C" __declspec(dllexport) bool showDialog( HWND parent )       //这个是导出的函数
 {
     
//到这个地方,看到QWinWidget了吧?它的参数就是使用Dll的主程序的句柄
     QWinWidget win( parent );                               
     win.showCentered();
     QMessageBox::about( &win, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003" );
 
 
     
//这部分官方代码原文中并没有,是我添加的,已经测试过,可以在vs工程下正常使用 

        QMainWindow* mainwin=new QMainWindow();                       
        QLineEdit *edit = new QLineEdit( widget );
        mainwin->setCentralWidget(edit);
        mainwin->show();
     win.show();
     qApp->exec();   //有这个就可以把信号和槽添加进来,已经测试过,支持信号和槽
     return TRUE;
 }

(个人总结:我已经测试过qtwinmigrate-2.8-opensource\examples\qtdll目录下的工程可以在Qt Creator上可以生成dll和lib文件,生成的dll在其它vs工程上完全正常使用。所以如果以后要再用Qt开发vs下用的dll,完全可以把这个作为模板,DllMain()内的代码不用动,只是更换掉要导入的函数即可。

完整的代码如下图:



在上面的代码中,左边的qtwinmingrate.pri提供了一个Qt/MFC 迁移框架,里面有qmfcappp、qwinhost、qwinwidget三个类,就像上面说的,QMfcApp:: pluginInstance(hInstance)提供Qt和MFC消息循环共同工作的机制,并接受DllMian()函数传来的句柄,然后使用qwinwidget类接受这个句柄,有了这个父类,其它的小部件,包括各种控件就可以向上放了,当然,也可以支持信号和槽机制。另外,如果加了信号和槽功能后,最好在return TRUE;前面加上一句 qApp->exec();这样创建的窗口就不会因为导出函数的结束而析构掉。

### 回答1: 在MFC DLL工程使用Qt类,需要进行一些额外的配置和操作。 首先,确保已经正确安装并配置好了Qt开发环境,并在MFC DLL工程添加Qt头文件和库文件的路径。 其次,需要在MFC DLL工程的stdafx.h文件包含Qt头文件,例如: ```cpp #include <QtCore> #include <QtGui> ``` 然后,在MFC DLL工程实现自定义的Qt类,可以通过继承Qt提供的基类来实现,例如: ```cpp class MyQtClass : public QObject { Q_OBJECT public: // 省略构造函数和析构函数 void doSomething() { // Qt的相关操作 } signals: // Qt信号声明 public slots: // Qt槽函数声明 }; ``` 在MFC DLL工程使用这个自定义的Qt类,可以在MFC的代码进行实例化和调用,例如: ```cpp void MyMfcFunction() { MyQtClass myQtObject; myQtObject.doSomething(); // 其他MFC相关操作 } ``` 在使用MFC DLL工程时,需要确保在使用Qt类之前,先调用QCoreApplication::setAttribute函数设置Qt的属性,例如: ```cpp int APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); break; } return TRUE; } ``` 需要注意的是,在MFC DLL工程,可能会涉及到QtMFC的事件循环的冲突问题,需要根据具体情况进行适当的处理。 综上所述,通过上述配置和操作,可以在MFC DLL工程成功使用Qt类。 ### 回答2: 在MFC DLL工程使用Qt类可以通过以下步骤实现: 1. 首先,确保在MFC DLL工程已经正确安装和配置了Qt库。 2. 在MFC DLL工程的头文件包含Qt类所需的头文件,并在对应的源文件实现相关功能。 3. 使用Qt类时,需要在MFC DLL工程的代码使用Qt的命名空间。例如,如果要使用Qt的QMessageBox类,可以将以下代码添加到MFC DLL工程的相应源文件: ``` using namespace Qt; ``` 4. 在使用Qt类之前,需要进行Qt库的初始化。可以在DLL工程的初始化函数调用以下代码: ``` QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); //启用高DPI缩放 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //使用高DPI图标 QApplication a(argc, argv); //初始化Qt应用程序对象 ``` 5. 之后就可以在MFC DLL工程使用Qt类了。例如,可以使用QMessageBox类显示一个消息框: ``` QMessageBox::information(nullptr, "Title", "Message"); ``` 6. 最后,在MFC DLL工程使用Qt类后,还需进行Qt库的清理和关闭。可以在DLL工程的退出函数调用以下代码: ``` QApplication::exit(); //退出Qt应用程序 ``` 以上是在MFC DLL工程使用Qt类的基本步骤,需要根据具体的工程需求进行相应调整和扩展。 ### 回答3: 在MFC DLL工程使用Qt类可以通过以下步骤实现: 1. 首先,在MFC DLL工程添加Qt的头文件和库文件路径。打开工程的属性页,选择C/C++ -> 常规 -> 附加包含目录,添加Qt的头文件路径;选择链接器 -> 常规 -> 附加库目录,添加Qt的库文件路径。 2. 在MFC DLL工程创建一个包含Qt类的功能模块,可以是一个窗口或一个类。例如,我们创建一个Qt窗口类。 3. 在DLL的导出函数创建Qt应用程序对象和Qt窗口对象,并处理相关的事件和逻辑。这样在外部调用该DLL时,可以通过导出的函数来创建和操作Qt窗口。 4. 导出DLL的函数,以供外部调用。在导出函数,将创建的Qt窗口对象指针返回给外部调用者。 5. 在外部调用者(其他MFC项目或应用程序)使用LoadLibrary函数加载该DLL,并使用GetProcAddress函数获取导出的函数指针。 6. 外部调用者使用获取到的函数指针来创建和操作Qt窗口,通过调用导出的函数来获取窗口对象指针并进行相关操作。 需要注意的是,在使用MFC DLL工程使用Qt类时,需要确保MFCQt的运行时库版本兼容,并且正确配置了相关的路径和库文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值