一 介绍
本文将以一个实例来说明如何将WPF技术集成在基于MFC的应用程序中 这种技术的主要目的是为了增强基于Win /MFC的应用程序的在图形方面的表现能力 本文所提供的演示程序将在MFC对话框架应用程序中显示一个WPF动画时钟 界面如图 所示
本文需要的开发工具和开发库 为了建立和运行demo程序 我们需要安装如下的组件
Visual Studio 或Visual Studio NET Framework 或 NET Framework
所需要的平台 demo程序必须在下面支持 NET Framework 的 *** 作系统平台上运行
Windows Vista Windows XP SP Windows Server SP
如果你是一名C++开发人员 并且想使用WPF技术来增强自己的基于Win /MFC应用程序 本文非常适合你 为了能从本文学习到更多的知识 我们需要熟悉VC++/CLi MFC XAML和C# 但是 如果我们不了解C#或XAML 我们仍然可以通过引用现成的DLL来使用WPF程序
二 什么是WPF
WPF是Windows Presentation Foundation的缩写 它是微软 NET Framework 的一个子系统 这种技术允许开发人员高效地创建可视化的应用程序 并改善用户体验 由于WPF的发布 使用Windows程序在富控件的设计 开发上更如虎添翼 WPF主要关注一套应用程序服务 用户接口 D和 D 矢量图 动画 数据绑字 音频 并提供一个在UI和商业逻辑之间的非常清晰的界限
WPF API是被管制的代码 但是大多数Win /MFC程序是非管制的C++代码 按著惯例 WPF API不能通过非常制程序调用 然后 通过使用VC编译器的/clr选项 我们可以建立一个由管制和非管制混合而面的系统 在这个系统中 我们可以使管制和非管制代码无缝地混合在一起
有一个要注意的是在C++工程中不允许编译XAML文件 因此 我们必须建立一个包含在本例中所需要的所有XAML而的C# DLL 然后在C++工程中包含这个Dll引用
有两种基本的技术可以融合WPF和Win /MFC代码
将WPF放到Win /MFC程序中 使用这种技术 开发人员可以使用WPF的高级图形能力来渲染Win /MFC应用程序
将Win /MFC放到WPF中 使用这种技术 开发人员可以在WPF中使用已经存在的
Win /MFC控件 并通过一定的机制来传递数据
在本文中将采用第一种方法
三 融合Win /MFC和WPF程序
上面部分所说的是本例的基本规则 下面在本节中将介绍如何编写具体的实现代码 在本例中 我首先会演示使用XAML和C#建立WPF内容 并在VC++中引用这个DLL
本例的目的是建立一个用于设置日期和时间的设置工具 其中动画部分使用WPF实现 程序的其他部分仍然使用MFC实现
这个演示程序由两部分组成 一个是MFCHostMPF(由VC++/MFC代码组成) 另一个是WPFControls(由XAML和C#代码组成) 这个MFCHostWPF工程将由WPFControls工程所产生的DLL作为一个外部的引用 如图 所示
向MFC工程中加入一个WPF引用 如图 和图 所示
三 在MFC应用程序中加入和WPF相关的代码
先提一下 gcnew关键字被用于建立一个管制类型的实例 在本例中将建立一个垃圾回收集合栈的实例 所有被gcnew分配的内存空间将被垃圾回收器自动管理 而开发人员并不需要为什么时间释放它们而 *** 心
为了使用WPF程序 关键是System::Windows::Interop::HwndSource类 这个类将在Win 窗口中使用WPF程序 因此 WPF程序可以作为MFC窗口的子窗口放到UI上 而在WPF对象和Win 窗口之间的通讯要通过引用C++程序中被存储的静态字段 这些静态字段的代码如下
ref class Globals { public: static System::Windows::Interop::HwndSource^ gHwndSource; static WPFControls::AnimClock^ gwcClock; };
HWND hwndWPF; // 和WPF相关的hwnd 为了建立一个HwndSource 首先需要建立一个HwndSourceParameters结构 这个结构需要如下的参数 类 窗口 窗口类型 窗口的初始位置 窗口的初始尺寸 父窗口 一但我们将HwndSourceParameters结构编写完 就可以将这个结构到HwndSource的构造方法HwndSource(HwndSourceParameters)中 最后 我们将WPF时钟的引用赋值给HwndSource对象的RootVisual属性 并通过调用Handle ToPointer()返回HwndSource的HWND 代码如下HWND GetHwnd(HWND parent int x int y int width int height) { System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters ( MFCWPFApp ); sourceParams >PositionX = x; sourceParams >PositionY = y; sourceParams >Height = height; sourceParams >Width = width; sourceParams >ParentWindow = IntPtr(parent); sourceParams >WindowStyle = WS_VISIBLE | WS_CHILD; Globals::gHwndSource = gcnew System::Windows::Interop::HwndSource(sourceParams); DateTime tm = DateTime::Now; Globals::gwcClock = gcnew WPFControls::AnimClock(); Globals::gwcClock >ChangeDateTime(tm Year tm Month tm Day tm Hour tm Minute tm Second); FrameworkElement^ myPage = Globals::gwcClock; Globals::gHwndSource >RootVisual = myPage; return (HWND) Globals::gHwndSource >Handle ToPointer(); }
因此 无论用户如何变化时钟 我们的MFC代码都会调用RefereshWPFControl()来刷新WPF时钟void RefreshWPFControl() { FrameworkElement^ page; DateTime tm = DateTime::Now; Globals::gwcClock >ChangeDateTime(tm Year tm Month tm Day tm Hour tm Minute tm Second); page = Globals::gwcClock; Globals::gHwndSource >RootVisual = page; return; }
现在我们已经有了大部分我们需要的功能了 而最后的任务是在MFC对话框代码中找个地方调用HwndSource实现创建函数 当然 有很多地方可以做这个工作 但是OnCreate也许是最好的位置 在OnCreate事件句柄中调用GetHwnd()函数的代码如下int CMFCHostWPFDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == ) return ; hwndWPF = GetHwnd(this >GetSafeHwnd() ); return ; }
四 结论 lishixinzhi/Article/program/net/201311/11996
你要理解每种工程的作用需要很多基础知识,我只能简单的跟你说一下:
ATL COM AppWizard 用来新建一个COM组件的向导,比如WORD里用的公式编辑器就是一个COM组件。
Cluster Resource Type Wizard 群集资源类型向导,用来创建可以到处用的资源项目,比如字体就是一种资源。
Custom AppWizard 这个是给高档用户用的自定义向导。
Database Project 数据库项目,顾名思义,用来创建数据库用的。
DevStudio Add-in Wizard 是给微软的Visual系列工具做插件的向导。
Extended Stored Proc Wizard 扩展存储过程向导,用C++代码来扩展SQL存储过程用的项目。
ISAPI Extension Wizard 用C++代码扩展网站服务器功能的项目。
Makefile 编译指示文件,用这个东西,你可以做一个编译gpp的自己的g++编译器。
MFC ActivceX ControlWizard 这个是用MFC做ActiveX控件的向导,所谓MFC是微软的一个编程框架,所谓ActiveX控件么举例来说按钮、文本框等都是……
MFC AppWizard (dll) 用MFC框架生成一个DLL的项目,所谓DLL就相当于工具包,可以给其它项目用里面的功能。
MFC AppWizard (exe) 用MFC框架生成一个EXE项目,所谓EXE就是真正能执行的程序,比如IE就是个EXE,一个EXE经常会用到别的DLL里面的功能。
Utility Project 老实说没用过这个。
Win32 Application 也是生成一个EXE项目,但是不用MFC框架,所以这种项目对使用者的能力要求更高,但是功能更强,适合高档用户用的。
Win32 Console Application 和上面差不多,唯一区别是它生成一个的程序是运行在黑窗口里的,不是一个平时喜闻乐见的样子。
Win32 Dynamic-Link Library 生成一个DLL,但是仍然不用MFC框架。
Win32 Static Library 生成一个LIB,LIB和DLL差不多都是工具包,但是区别在于没法动态替换。举例说QQ这个EXE用到一个语音功能包的DLL,这样QQ装好之后你还可以把这个DLL换成高版本的以获得更好的语音效果。但是如果QQ用LIB来做这个功能,你一单装好之后就不能动了,想升级语音就得升级整个QQ。(虽然这种描述不准确,但是大概就是这个意思)。
一、创建基于对话框的MFC程序
先打开Visual Studio 2013开发环境,如图1所示。依次点击文件> 新建> 项目创建一个新的项目。接下来进入创建项目界面如图2所示。依次选择已安装 > 模版 > Visual C++ > MFC来到MFC程序类型选择界面,选择MFC应用程序这一列。在创建项目界面的最下方分别输入自定义的工程名称、项目保存路径以及项目名称,点击确定即可来到MFC工程创建界面
二、对工程进行个性化设置
依次点击菜单的项目 > 工程选项,如图5所示,可来到工程配置界面。
三、给对话框添加各种控件
首先要打开资源视图。在整个VS2013开发环境左下角有一行视图按钮,其中包含“解决方案资源管理器”、“类视图”、“资源视图”等Tab项,这3个视图是开发过程中使用较多的视图方式。如果选择“解决方案资源管理器”则通过文件的方式来查看整个工程;“类视图”则查看代码中的所有所有常量宏定义、全局函数及全局变量和类的定义及成员变量等;如果选择“资源视图”则程序中的对话框资源、菜单资源、Icon资源、以及Version和一些自定义资源等都在这里能看到。
MFC主要有以下几个缺点:
大量使用稀奇古怪的宏,会使代码可读性很差。要掌握MFC需要编程人员耐心的去分析它们。
消息映射的现实机制十分笨拙,没有采用继承机制,也没有采用委托技术,而是采用表驱动。
对于底层SDK的封装太薄,面向对象的感觉不足。
自己编写了RTTI,SHE,CObjXXX(Container)等,实现起来不太理想。
很多场合本来是标准库可以一展身手的地方,MFC完全没用上。
为了迎合MFC,编译器的很多地方都违反标准。
Doc/View体系的局限性,想图破很难。
所以建议楼主在编程时不要集中所有精力学习MFC,而应该掌握标准的C==库,特别是使用STL。
用visual studio 自带的visio,office的没用,能做逆向工程的visio只有vs自带的,我之前找过,没有下,那个是在vs2003/2005增值包里的,除非去买正版的
还有一个使用ibm 的rose, 我个人觉得效果不是太好,只能逆向成class diagram,其他的uml都出不来
MFC注入DLL显示窗口的bug主要是由于DLL的加载顺序所导致的,当我们注入DLL时,DLL会把自己的资源加载到MFC程序中,但是由于加载顺序的问题,DLL中的资源可能会覆盖MFC程序中的资源,从而导致程序出现显示窗口的bug。为了解决这个问题,我们可以在MFC程序中使用AfxSetResourceHandle函数来设置资源句柄,以确保DLL中的资源不会覆盖MFC程序中的资源。
void CTectCreateFileView::OnDraw(CDC pDC)
{
CTectCreateFileDoc pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CFont font;
LOGFONT lf;
// Do something with the font just created
memset(&lf, 0, sizeof(LOGFONT)); // zero out structure
CFont def_font;
int y = 5;
for( int i = 8; i<28; )
{
lflfHeight = i; // request a 12-pixel-height font
strcpy(lflfFaceName, "宋体"); // request a face name "Arial"
VERIFY(fontCreateFontIndirect(&lf)); // create the font
def_font = pDC->SelectObject(&font);
CString strmsg;
strmsgFormat("这是%d号宋体",i);
pDC->TextOut(5, y,strmsg);
pDC->SelectObject(def_font);
fontDeleteObject();
i += 2;
y += lflfHeight;
}
}
在CView::OnDraw里画即可实现
以上就是关于在MFC中使用WPF技术全部的内容,包括:在MFC中使用WPF技术、我想学C++和逆向工程、求助:使用 MFC 开发图形界面程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)