首先说下版本:VS2013+qt-opensource-windows-x86-msvc2013-5.7.0.exe
插件:VS:VA_X_Setup2073.exe QT:qt-vs-addin-1.2.5.exe
(使用qtwinmigrate实现) 下载地址:qt-solutions.rar
1.在qtwinmigrate中的qtdll中,只要使用main.cpp的如下代码实现动态库模块的引用:
//name: DLL程序入口点函数 //hInstance参数:指向DLL本身的实例句柄 //dwReason参数:指明了DLL被调用的原因,可以有以下4个取值: //DLL_PROCESS_ATTACH:当DLL被进调用<<第一次> 调用时,导致DllMain函数被调用 //DLL_PROCESS_DETACH:当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain //DLL_THREAD_ATTACH:当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像 //DLL_THREAD_DETACH:如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread //lpReserved参数:保留,目前没什么意义 BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/ ) { static bool ownApplication = FALSE; if ( dwReason == DLL_PROCESS_ATTACH ) { ownApplication = QMfcApp::pluginInstance( hInstance );//创建一个QApplication对象 } if ( dwReason == DLL_PROCESS_DETACH && ownApplication ) { delete qApp; } return TRUE; } //动态库可以提供的接口 //__declspec(dllexport):可以直接定位到动态库中的函数地址 extern "C" __declspec(dllexport) bool showDialog( HWND parent, void * pMfc = NULL, int (*p)(void*) = NULL, bool canDrag = false) { pWin = new QWinWidget(parent); pWin->showCentered(); pWidget = new PieWidget(pWin, pMfc, p, canDrag); RECT r; GetWindowRect(pWin->parentWindow(), &r); pWidget->move((r.right-r.left-pWidget->width())/2+r.left, (r.bottom-r.top-pWidget->height())/2+r.top); pWidget->show(); return TRUE; } //动态库关闭接口 extern "C" __declspec(dllexport) void closeDialog() { if (pWin) { delete pWin; pWin = NULL; } }
以上是动态库的极简的模块接口,一个是展示接口,一个是关闭接口,如果自己的动态库还需要其他的接口(肯定不止这两个接口),可以按照这两个接口方式进行开发,当让也可以在QT的界面添加控件回调MFC的函数,
PieWidget::PieWidget(QWidget *parent, void *pMfc, int (*p)(void*), bool canDrag): QWidget(parent), ui(new Ui::PieWidget), m_pMfc(pMfc), m_canDrag(canDrag), m_pCallback(p) { ui->setupUi(this); //add your code }
其中:QWidget *parent是继承Qt界面父控件的对象,void *pMfc是mfc程序的函数指针,m_pCallback是回调函数的指针,m_canDrag是bool类型的状态变量
需要在这里面配置mfc编译好的EXE文件,放到qt编译版本(relaese/debug)的同级目录下,调试的话可以在Qt下面调试(需要安装CDB调试器),也可以在MFC下调试,这个相对方便些
接下来就是mfc的编写程序,可以在MFC的UI界面添加自己需要的控件,调用方式
void CsecondMFCDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
if (m_hDLL) { // 已加载
return;
}
const char* dllName = "xxxx.dll";//qt编译好的动态库
m_hDLL = LoadLibrary(dllName); // 如果失败,则返回值为NULL
int index = ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
bool canDrag = index;
if (m_hDLL != NULL)
{
typedef bool(*pShow)(HWND parent,void *pMfc, int (*p)(void*), bool canDrag);
int(*pCallback)(void*) = qtCallback;
pShow fp1 = pShow(GetProcAddress(m_hDLL, "showDialog"));
if (fp1 != NULL)
{
fp1(theApp.m_pMainWnd->m_hWnd, this, pCallback, canDrag); //
}
//FreeLibrary(m_hDLL);
//m_hDLL = NULL;
}
else
{
CString strInfo("Cannot Find dll");
MessageBox(strInfo);
}
}
最后就是调试环节了,其中的问题多半是百度帮忙。