文章目录
Qt是一个优秀的C++开源套件,但是发布特定的应用程序时,也存在文件太多的问题,如何开发一个Qt子模块嵌入到目标程序,同时将所有的Qt模块放在一个指定的文件夹,就是一个需要解决的问题。
1.导出函数声明
- 1.导出函数声明
- 2.函数类型和动态加载
- 3.修改工作目录和动态加载
- 4.修改DLL搜索路径
- 5.修改Qt加载动态库路径
- 6.Qt嵌入目标应用程序
- 7.修改窗口过程
申明为C兼容的导出函数,然后采用动态加载库的形式动态加载。
#ifdef__cplusplus
#define DLLEXPORT extern "C" _declspec(dllexport)
#else
#define DLLEXPORT _declspec(dllexport)
#endif
DLLEXPORT BOOL FUN();//这就是要导出函数
2.函数类型和动态加载
动态加载Dll,然后通过GetProcAddress函数来调用对应的API。范例代码如下所示:
typedef void (*ShowMainUIType)(void *hWnd);//申明函数类型
void CallFunc()
{
HINSTANCE hDLL = LoadLibraryA("SVGApp13.dll"); //加载dll文件
//如果加载失败的话, 通过GetLastError()进行获取,看失败原因。
auto code5 = GetLastError();
void *pfunc = GetProcAddress(hDLL, "ShowMainUI");
ShowMainUIType ShowMainUI = (ShowMainUIType)pfunc;//直接使用原工程函数名
code5 = GetLastError();
if (ShowMainUI)
{
ShowMainUI(hWnd);
}
}
3.修改工作目录和动态加载
修改应用程序当前目录,有利于控制应用程序的工作目录,主要调用SetCurrentDirectory和GetCurrentDirectory两个函数来切换。
char chCurDir[MAX_PATH] = {0};
GetCurrentDirectory(MAX_PATH, chCurDir);
SetCurrentDirectory(_T("E:\\test\\"));
4.修改DLL搜索路径
修改Dll的搜索路径,该函数影响后续LoadLibraryA类函数寻找dll路径位置:
SetDllDirectoryA("E:/Project/SVGApp13/Win32/Debug");
5.修改Qt加载动态库路径
在QApplication对象申明之前,加载Qt库路径,能够将Qt的动态连接库其它位置的路径包含进来,从而可以将对应的库文件放在子文件夹下。
QCoreApplication::addLibraryPath(QString::fromLocal8Bit("\\Debug\\"));
QCoreApplication::addLibraryPath(QString::fromLocal8Bit("\\Debug\\platforms"));
6.Qt嵌入目标应用程序
Qt嵌入目标应用程序作为子窗口,需要替换主应用程序的窗口消息循环,这往往难度较大,或者采用双线程,这样又会导致线程调度等许多问题,除非主程序采用Qt开发,否则不建议采用Qt作为子窗口嵌入,问题还是比较多。建议在比较简单的程序中采用这种方法。
7.修改窗口过程如果想在宿主应用程序的窗口过程中,夹带一些自定义功能,就需要Hook窗口过程。
//修改窗口过程函数
WNDPROC lpfnOldProc = 0;
LRESULT CALLBACK NewWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch (wMsg) {
case WM_USER + 99:
{
//MessageBoxA(NULL, "窗口过程", "调试", MB_OK);
g_pACPGMainWindowPlugin->StartSeBiaoMainUI();
break;
}
}
return CallWindowProc(lpfnOldProc, hWnd, wMsg, wParam, lParam);
}
//修改位置
//lpfnOldProc = (WNDPROC)SetWindowLongPtrA(m_hCDRMainWindow, GWLP_WNDPROC, (DWORD)NewWndProc);
lpfnOldProc = (WNDPROC)SetWindowLongPtrW(m_hCDRMainWindow, GWLP_WNDPROC, (DWORD)NewWndProc);
DWORD code = GetLastError();