Web Runtime:Win32应用的核反应堆

2,124 阅读6分钟

\

 

目录

创建MFC工程

开发环境

准备工作

创建一个MDI或者MDT类型的MFC工程

复制MFCPlus文件夹

修改App类的基类

修改 CMainFrame类的基类(MDT工程没有这一步)

修改CFirstMFCApp::InitInstance()

修改CFirstMFCApp::InitInstance()(二)

修改CFirstMFCView::OnInitialUpdate()

文档序列化支持

修改工程的Manifest配置

方法一:

方法二:

已有MFC工程的迁移

编译您的代码

Sample

技术支持


       对****WebRuntime****的技术目标而言,SDI以及基于对话框的应用程序结构并不合适,所以我们只考虑MDI(多文档)以及MDT(多顶层窗口)架构的MFC应用。本文是基础篇,是创建MFC互联网工程的入门指南,开发者只需按照指定的步骤操作即可,普通开发者完成本文的步骤应该在3-5分钟左右的时间。

创建MFC工程

开发环境

        我们建议的开发环境是Visual Studio 2019。

准备工作

        下载 (点击)WebRuntime运行时支撑包 下载之后,将二进制包解压缩,找到MFCPlus子文件夹。

创建一个MDI或者MDT类型的MFC工程

        为了行文方便,我们预设工程的名字为FirstMFCApp,是MDI类型的MDI工程:

(创建新MFC工程)

工程的App类为CFirstMFCApp:

(App类:CFirstMFCApp) 

 工程的View类为 CFirstMFCView:

(工程的View类:CFirstMFCView,是一个CFormView类)

 其他方面都是默认的选项。

复制MFCPlus文件夹

        将****MFCPlus****文件夹复制到刚刚生成的工程文件夹,这一步替换了新工程的pch,h以及pch.cpp文件,事实上相当于在已有的pch,h以及pch.cpp文件之中分别添加

#include "WebRuntimeApp.h"

(pch,h中增加如上一行代码)

以及

#include "WebRuntimeApp.cpp"

(pch,cpp中增加如上一行代码)

复制工作相当于给所创建的MFC工程同时增加了一组C++源文件以及一个mfcapp.manifest文件。

修改App类的基类

        将CFirstMFCApp的基类修改为CWebRuntimeApp:

class CFirstMFCApp : public CWebRuntimeApp

修改 CMainFrame类的基类(MDT工程没有这一步)

        将CMainFrame的基类修改为:

class CMainFrame : public CWebMDIFrameWnd

同时在MainFrm.cpp文件中修改如下部分:

IMPLEMENT_DYNAMIC(CMainFrame, CWebMDIFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CWebMDIFrameWnd)

注意以上宏之中的CWebMDIFrameWnd部分

修改CFirstMFCApp::InitInstance()

        这一步MDI、MDT工程类型都需要。在这个函数开始部分增加如下代码:

BOOL CFirstMFCApp::InitInstance()
{
	m_mapDOMObj[_T("main_panel")] = RUNTIME_CLASS(CFirstMFCView);
	if (!InitApp())
		return false;

	// InitCommonControlsEx() is required on Windows XP if an application

注意如下一行:

    m_mapDOMObj[_T("main_panel")] = RUNTIME_CLASS(CFirstMFCView);

事实上这里建立了一个字符串与CView类之间的一个“映射”,可以包含多个类似的行,这个映射为以后扩展Web DOM奠定基础,也就是说,每一个映射里面的“字符串名字”,将体现为一个新的Web页面元素类型。

        这里添加的代码对MDI、MDT工程类型都需要。如果您创建的工程是MDT类型的工程,需要在CFirstMFCApp::InitInstance()函数体之中将如下代码块删除:

	// create main MDI Frame window
	CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
	{
		delete pMainFrame;
		return FALSE;
	}
	m_pMainWnd = pMainFrame;

	// call DragAcceptFiles only if there's a suffix
	//  In an MDI app, this should occur immediately after setting m_pMainWnd
	// Enable drag/drop open
	m_pMainWnd->DragAcceptFiles();

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Enable DDE Execute open
	EnableShellOpen();
	RegisterShellFileTypes(TRUE);


	// Dispatch commands specified on the command line.  Will return FALSE if
	// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;
	// The main window has been initialized, so show and update it
	pMainFrame->ShowWindow(m_nCmdShow);
	pMainFrame->UpdateWindow();

(MDT工程之中,如上的代码块直接删除)

    相当于执行完

	m_pDocTemplate = pDocTemplate;
	AddDocTemplate(pDocTemplate);

函数直接返回“TRUE”。

修改CFirstMFCApp::InitInstance()(二)

        如果创建的是MDI工程,那么需要在CFirstMFCApp::InitInstance()中找到如下一行代码:

    EnableTaskbarInteraction();

将这一行替换为如下代码块:

	EnableTaskbarInteraction();

	return TRUE;
}

BOOL CFirstMFCApp::CreateCosmosApp(CWebPageImpl* pWebPageImpl, CBrowserImpl* pBrowserImpl, CString strObjID, CString strAppData)
{

替换之后,CFirstMFCApp::InitInstance()被分裂成两个函数,需要在CFirstMFCApp的类之中声明一个“虚函数”:

class CFirstMFCApp : public CWebRuntimeApp
{
public:
	CMFCApp() noexcept;


	// Overrides
public:
	virtual BOOL InitInstance();
	virtual int ExitInstance();

	// Implementation
	UINT  m_nAppLook;
	BOOL  m_bHiColorIcons;

	virtual void PreLoadState();
	virtual void LoadCustomState();
	virtual void SaveCustomState();

    //针对MDI类型的应用,需要重载CWebRuntimeApp的虚函数:
	virtual BOOL CreateCosmosApp
	(
		CWebPageImpl* pWebPageImpl,
		CBrowserImpl* pBrowserImpl,
		CString strObjID,
		CString strAppData
	);

	afx_msg void OnAppAbout();
	DECLARE_MESSAGE_MAP()
};

(注意增加的函数:CreateCosmosApp,
这个函数由CWebRuntimeApp提供,这里重载)

修改CFirstMFCView::OnInitialUpdate()

        由于CFirstMFCView是CFormView,其OnInitialUpdate()需要如下修改:

void CMFCApplication1View::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();

    //以下代码只针对CFormView派生类:
	if (m_pDocument)
	{
		theApp.SetFrameInfo(m_hWnd);
	}
}

文档序列化支持

        按照如下代码重载序列化支持函数:

// CFirstMFCAppDoc serialization

void CFirstMFCAppDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << theApp.GetDocTemplateID(this);
		// TODO: add storing code here
	}
	else
	{
		ar >> theApp.m_strCreatingDOCID;
		// TODO: add loading code here
	}
}

打开资源面板,修改ID为“IDR_FirstMFCAppTYPE”的“字符串表资源”:

 修改后字符串值如下:这里“*.xxx”为MFC程序支持的文档的扩展名(由于Visual Studio 应用程序向导的Bug,生成的资源有问题) 

FirstMFCApp\nFirstMFCApp\nFirstMFCApp\nFirstMFCApp files\n.xxx\nFirstMFCApp.Document\nFirstMFCApp.Document

到现在为止我们完成了MFC工程支持WebRuntime的代码修改部分。

修改工程的Manifest配置

由于需要支持现代浏览器的全部功能,需要修改工程的Manifest配置,有如下两个方法。 

方法一:

        打开工程配置,直接修改Debug、Release模式的Manifest配置,其中MfcApp.manifest文件由****MFCPlus****提供,需要复制到创建工程的源文件文件夹:

(修改Debug、Release编译模式的manifest配置) 

方法二:

        可以导入工程的属性表文件MFCApp.props,步骤如下:

第一步:按如下图操作打开工程的属性管理工具箱:

 第二步:在属性管理工具箱之中选择目标工程,右键操作鼠标打开快捷菜单,选择添加已存在的工程属性项

 第三步:选择MfcApp.props,完成操作。

 完成以上步骤之后,我们完成了支持****WebRuntime****的全部工作。 

已有MFC工程的迁移

        对已存在的MFC工程(MDI、MDT类型的工程,其他类型的可以联系我们),由于设计者的很多MFC类对象是自己定义的,所以其基础类环节与我们这里的示范有一些差异,开发者可以按照如上步骤,依据自己的设计思路做适当调整,即可完整支持****WebRuntime****。

        可供参考的迁移步骤如下(对新创建的工程依然适用):

  1. 将App类的基类由“CWinAppEx”替换为“CWebRuntimeApp”,对MDI应用类型,在工程级别,将“CMDIFrameWndEx”替换为“CWebMDIFrameWnd”,如下图所示:

  2. 参考本文之中针对InitInstance()的修改部分修改目标工程App类的InitInstance()函数;

  3. 按照本文之中介绍MFCPlus的部分将必要的代码复制到目标工程的源文件文件夹;

  4. 按照本文介绍的方式处理CFormView的派生类(重载OnInitialUpdate函数);

  5. 按照本文介绍的方式处理文档序列化。

  6. 按照本文介绍的方式调整目标工程的Manifest配置;

 以上步骤当然也适合新创建的MFC工程。

编译您的代码

        将创建的工程编译,注意我们只支持x64编译,也就是说,我们只支持64位Windows应用。将****WebRuntime二进制包****复制到编译之后的输出目录,即exe文件所在的文件夹。关于如何运行编译之后的程序,我们会在其他博文之中详细的解释,这里只介绍如何创建、迁移这类工程。 

Sample

        WebRuntime源代码之中,包含两个例子****,一个是MFCApplication1(MDI),另外一个是TheUniverse(MDT),开发者可以看例子源代码,在二进制包里面包含例子的编译版本以及相关的Web页面,可以直接运行。

技术支持

        有问题的朋友,可以微信联系:

\