C++第四十三篇 -- VS2017創建控制台程序勾選MFC類庫


用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>
View Code

 

4. targetver.h

#pragma once

// // 包含 SDKDDKVer.h 可定義可用的最高版本的 Windows 平台。
// 如果希望為之前的 Windows 平台構建應用程序,在包含 SDKDDKVer.h 之前請先包含 WinSDKVer.h 並
// 將 _WIN32_WINNT 宏設置為想要支持的平台。
#include <SDKDDKVer.h>
View Code

 

這樣就不會編譯出錯了。

 

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;
}
View Code

 

可以看到窗口已經成功調用了

 

創建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;
}
View Code

 

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
View Code

 

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
View Code

 

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
View Code

 

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中調出窗口。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM