用VS2017創建EXE帶MFC類庫方法
1. File --> New --> Project
2. Windows桌面向導
3. 勾選MFC類庫
4. 創建成功
如果項目編譯出錯
1. 項目創建成功后編譯報錯界面
原因分析:缺少#include <afxwin.h>頭文件。
解決方案:在#include "Project1.h"后面添加#include <afxwin.h>,編譯通過。
如果上述方法不行,可參考下面解決方法,否則跳過以下內容。
原因分析:對比別人創建成功的項目,發現多了一個#include "framework.h"
解決方案:copy成功項目的framework.h頭文件,並#include "framework.h",另外framework.h頭文件中引用了targetver.h頭文件,因此,將targetver.h頭文件也copy過來
2. 編譯成功后的界面
3. framework.h

#pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 部分 CString 構造函數將是顯式的 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS // 移除對話框中的 MFC 控件支持 #ifndef VC_EXTRALEAN #define VC_EXTRALEAN // 從 Windows 頭文件中排除極少使用的內容 #endif #include <afx.h> #include <afxwin.h> // MFC 核心組件和標准組件 #include <afxext.h> // MFC 擴展 #ifndef _AFX_NO_OLE_SUPPORT #include <afxdtctl.h> // MFC 對 Internet Explorer 4 公共控件的支持 #endif #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC 對 Windows 公共控件的支持 #endif // _AFX_NO_AFXCMN_SUPPORT #include <iostream>
4. targetver.h

#pragma once // // 包含 SDKDDKVer.h 可定義可用的最高版本的 Windows 平台。 // 如果希望為之前的 Windows 平台構建應用程序,在包含 SDKDDKVer.h 之前請先包含 WinSDKVer.h 並 // 將 _WIN32_WINNT 宏設置為想要支持的平台。 #include <SDKDDKVer.h>
這樣就不會編譯出錯了。
EXE調用MFC窗口
1. 新建一個子窗口
2. 修改SubWin1.cpp中#include "stdafx.h"為#include "pch.h"並且注釋掉#include "Project1.h",然后添加#include "resource.h"如下
3. 在Project1.cpp中添加#include "SubWin1.h",然后用以下語句調用SubWin窗口
SubWin1 *chartdialog = new SubWin1; int ReturnValue = chartdialog->DoModal(); // Show the dialog printf("%d\n", ReturnValue);
Project1.cpp

// Project1.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include "pch.h" #include "Project1.h" #include <afxwin.h> #include "win_test.h" #include "SubWin1.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; using namespace std; void win_test_show() { //win_test *chartdialog = new win_test; //int ReturnValue = chartdialog->DoModal(); // Show the dialog //printf("%d\n", ReturnValue); SubWin1 *chartdialog = new SubWin1; int ReturnValue = chartdialog->DoModal(); // Show the dialog printf("%d\n", ReturnValue); } int call() { int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); if (hModule != nullptr) { // initialize MFC and print and error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: code your application's behavior here. wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. win_test_show(); } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; } int main() { int nRetCode = 0; call(); return nRetCode; }
可以看到窗口已經成功調用了
創建DLL帶MFC類庫方法
1. 新建一個Windows Desktop Wizard項目
2. 勾選MFC,新建DLL
3. 編譯程序,編譯成功。
4. 新建一個Win32程序用來測試Dll
5. 在Dll中新建一個MFC的窗口
6. Project2.cpp中調用它,修改Project.cpp如下

// Project2.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include "Project2.h" #include "SubWin1.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; using namespace std; int Function() { int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); if (hModule != nullptr) { // initialize MFC and print and error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: code your application's behavior here. wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. SubWin1 *chartdialog = new SubWin1; int ReturnValue = chartdialog->DoModal(); // Show the dialog printf("%d\n", ReturnValue); } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; }
7. 修改Project.h如下

// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the {0}_EXPORTS // symbol defined on the command line. This symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // {0}_API functions as being imported from a DLL, whereas this DLL sees symbols // defined with this macro as being exported. #ifdef __cplusplus extern "C" { #endif #ifdef PROJECT2_EXPORTS #define PROJECT2_API __declspec(dllexport) #else #define PROJECT2_API __declspec(dllimport) #endif // This class is exported from the dllxiu PROJECT2_API int Function(); #ifdef __cplusplus } #endif
8. 將SubWin1.cpp中添加頭文件#include "resource.h"

// SubWin1.cpp : implementation file // #include "stdafx.h" #include "Project2.h" #include "SubWin1.h" #include "afxdialogex.h" #include "resource.h" // SubWin1 dialog IMPLEMENT_DYNAMIC(SubWin1, CDialog) SubWin1::SubWin1(CWnd* pParent /*=nullptr*/) : CDialog(IDD_SubWin1, pParent) { } SubWin1::~SubWin1() { } void SubWin1::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(SubWin1, CDialog) END_MESSAGE_MAP() // SubWin1 message handlers
9. 編輯Test.cpp調用dll,本次采用的是靜態加載DLL的方法,具體操作方法可以看前文。

// Test.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include "pch.h" #include <iostream> #include "../Project2/Project2.h" int main() { std::cout << "Hello World!\n"; Function(); } // Run program: Ctrl + F5 or Debug > Start Without Debugging menu // Debug program: F5 or Debug > Start Debugging menu // Tips for Getting Started: // 1. Use the Solution Explorer window to add/manage files // 2. Use the Team Explorer window to connect to source control // 3. Use the Output window to see build output and other messages // 4. Use the Error List window to view errors // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
10. 執行結果如下
chartdialog->DoModal()的返回結果居然是-1,這里就是DLL調用MFC類和EXE調用MFC類的區別所在了。解決這個問題的關鍵就是要在調用窗口語句之前加上AFX_MANAGE_STATE(AfxGetStaticModuleState());這句話。
Project2.cpp
// Project2.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include "Project2.h" #include "SubWin1.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; using namespace std; int Function() { int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); if (hModule != nullptr) { // initialize MFC and print and error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: code your application's behavior here. wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. AFX_MANAGE_STATE(AfxGetStaticModuleState()); SubWin1 *chartdialog = new SubWin1; int ReturnValue = chartdialog->DoModal(); // Show the dialog printf("%d\n", ReturnValue); } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; }
這樣就可以成功的在DLL中調出窗口。