在网上也搜索了一番,但都太麻烦,或者不太实用。只好自己摸索了。终于搞定。记录一下。
宗旨:
一:尽量不修改原有 VC EXE 工程的源代码;
二:尽量具有通用性;
VC 的窗体有两种:基于对话框(Dialog)的窗体(QT窗体和这个是类似的)、基于 MFC 的窗体。下面分情况说明。
一:基于对话框(Dialog)的窗体(QT窗体)
基于对话框(Dialog)的窗体,因为没有封装,所以程序的入口点是 WinMain(QT 窗体可能是 WinMain,也可能是 main)。
所以我们新建一个dll.cpp 文件,输出函数 ShowDllForm,ShowDllForm 函数调用 WinMain,就可以了。
不用修改原有工程的源代码。
将这个dll.cpp 编译(只编译,不连接),再和原有的 EXE 工程编译出来的 OBJ、RES、库文件,一起连接成 DLL 就可以了。
#include <windows.h>
HINSTANCE hinst = NULL;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hinst = (HINSTANCE)hModule;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow);
extern "C" __declspec(dllexport) void ShowDllForm()
{
WinMain(hinst, 0, (LPSTR)"", 1);
}
二:基于 MFC 的窗体
MFC 是经过微软封装的。和基于对话框的 EXE 有区别。
MFC EXE/DLL 程序的入口被封装了,不在我们的工程代码中。
而是调用我们工程中的 CxxxApp::InitInstance() 代码。
因此从这个函数入手。
1、将 MFC EXE 工程修改为 DLL 类型;
2、修改 CxxxApp::InitInstance 里面的内容。因为 DLL 一初始化,就会调用这里的代码。
在行首(最前面),添加代码:
(g_bInit 为新添加的 bool 类型变量。意思很明确,为 false 时,不执行后面的代码,直接返回了)
BOOL CxxxApp::InitInstance()
{
if(!g_bInit)
return TRUE;
3、在此单元,CxxxApp::InitInstance 代码上面,添加 DLL 输出函数 ShowDllForm,再次调用 InitInstance() 函数:
BOOL g_bInit=FALSE;
extern "C" __declspec(dllexport) void ShowDllForm()
{
g_bInit = TRUE;
theApp.InitInstance();
}
编译,得到 DLL ,调用OK。
QT 窗体EXE封装成DLL,和 VC 的基于对话框是一样的。
实例:
基于对话框:
7zip https://github.com/dbyoung720/PB/tree/master/modules/7-zip
Notepad 2 https://github.com/dbyoung720/PB/tree/master/modules/Notepad2
MFC 窗体:
mpc-be https://github.com/dbyoung720/PB/tree/master/modules/mpc-be
QT 窗体:
CMake-gui https://github.com/dbyoung720/PB/tree/master/modules/cmake-gui
qBittorent https://github.com/dbyoung720/PB/tree/master/modules/qBittorrent
GOOD LUCK!