在MFC中使用WPF技术

在MFC中使用WPF技术,第1张

一 介绍

本文将以一个实例来说明如何将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

Windows Presentation Foundation (WPF) 中的大部分类都从四个类派生而来 这四个类在 SDK 文档中常常被称为基元素类 这些类包括 UIElement FrameworkElement ContentElement 和 FrameworkContentElement DependencyObject 也是一个相关类 因为它是 UIElement 和 ContentElement 的通用基类

WPF 类中的基元素 APIUIElement 和 ContentElement 都是从 DependencyObject 派生而来 但途径略有不同 此级别上的拆分涉及到 UIElement 或 ContentElement 如何在用户界面上使用 以及它们在应用程序起到什么作用 UIElement 在其类层次结构中也有 Visual 该类为 Windows Presentation Foundation (WPF) 公开较低级别的图形支持 Visual 通过定义独立的矩形屏幕区域来提供呈现框架 实际上 UIElement 适用于支持大型数据模型的元素 这些元素用于在可以称为矩形屏幕区域的区域内进行呈现和布局 在该区域内 内容模型特意设置得更加开放 以允许不同的元素进行组合 ContentElement 不是从 Visual 派生的 它的模型由其他对象(例如 阅读器或查看器 用来解释元素并生成完整的 Visual 供 Windows Presentation Foundation (WPF) 使用)来使用 ContentElement 某些 UIElement 类可用作内容宿主 它们为一个或多个 ContentElement 类(如 DocumentViewer)提供宿主和呈现 ContentElement 用作以下元素的基类 所具有的对象模型较小 并且多用于寻址可能宿主在 UIElement 中的文本 信息或文档内容

框架级和核心级UIElement 用作 FrameworkElement 的基类 ContentElement 用作 FrameworkContentElement 的基类 对于此下一级类 原因是要支持与 WPF 框架级相分离的 WPF 核心级 这种分离还存在于 API 如何在 PresentationCore 和 PresentationFramework 程序集之间进行划分 WPF 框架级为基本应用程序需要提供了一个更完整的解决方案 包括用于表示的布局管理器的实现 WPF 核心级提供了一种方法 以充分利用 WPF 而又不至于产生附加程序集开销 对于大多数典型的应用程序开发方案而言 这些级别之间的区别很少有影响 而且一般情况下应将 WPF API 视为一个整体 而无需担心 WPF 框架级与 WPF 核心级之间有何区别 如果您的应用程序设计选择替换大量 WPF 框架级功能 例如 如果您的整体解决方案已经有其自己的用户界面 (UI) 组合和布局实现 则可能需要了解级别之间的差异

选择从哪个元素派生创建用于扩展 WPF 的自定义类的最实用方法是从某个 WPF 类中派生 这样您可以通过现有的类层次结构获得尽可能多的所需功能 本节列出了三个最重要的元素类附带的功能 以帮助您决定要从哪个类进行派生

如果您要实现控件(这的确是从 WPF 类派生的更常见的原因之一) 您可能需要从以下类中派生 实际控件 控件系列基类或至少是 Control 基类

如果您不是创建控件 并且需要从层次结构中较高的类进行派生

则可以参考下列各节的内容 了解每个基元素类定义了哪些特征

如果您创建从 DependencyObject 派生的类 则将继承以下功能

GetValue 和 SetValue 支持以及一般的属性系统支持

使用依赖项属性以及作为依赖项属性实现的附加属性的能力

如果您创建从 UIElement 派生的类 则除了能够继承 DependencyObject 提供的功能外 还将继承以下功能

对动画属性值的基本支持

对基本输入事件和命令的支持

可以重写以便为布局系统提供信息的虚方法

如果您创建从 FrameworkElement 派生的类 则除了能够继承 UIElement 提供的功能外 还将继承以下功能

对样式设置和演示图板的支持

对数据绑定的支持

对动态资源引用的支持

对属性值继承以及元数据中有助于向框架服务报告属性的相关情况(如数据绑定 样式或布局的框架实现)的其他标志的支持

逻辑树的概念

对布局系统的实际 WPF 框架级实现的支持 包括 OnPropertyChanged 重写(该重写可以检测到影响布局的属性更改)

如果您创建从 ContentElement 派生的类 则除了能够继承 DependencyObject 提供的功能外 还将继承以下功能

对动画的支持

对基本输入事件和命令的支持

如果您创建从 FrameworkContentElement 派生的类 则除了能够继承 ContentElement 提供的功能外 还将获得以下功能

对样式设置和演示图板的支持

对数据绑定的支持

对动态资源引用的支持

对属性值继承以及元数据中有助于向框架服务报告属性情况(如数据绑定 样式或布局的框架实现)的其他标志的支持

您不会继承对布局系统修改(如 ArrangeOverride)的访问权限 布局系统实现只在 FrameworkElement 上提供 但是 您会继承 OnPropertyChanged 重写(可以检测影响布局的属性更改并将这些更改报告给任何内容宿主)

记录了各种类的内容模型 如果您要找到一个合适的类以便从该类进行派生 其内容模型是一个应该考虑的可能因素

其他基类

DispatcherObjectDispatcherObject 为 WPF 线程模型提供支持 并允许为 WPF 应用程序创建的所有对象与 Dispatcher 相关联 即使您不从 UIElement DependencyObject 或 Visual 派生 也应考虑从 DispatcherObject 派生 以获得此线程模型支持

VisualVisual 实现二维对象在近似矩形的区域中通常需要具有可视化表示的概念 Visual 的实际呈现发生在其他类中(不是独立的) 但是 Visual 类提供了一个由各种级别的呈现处理使用的已知类型 Visual 实现命中测试 但它不公开报告命中测试结果的事件(这些都位于 UIElement 中)

FreezableFreezable 通过在出于性能原因需要不可变对象时提供为对象生成副本的途径 来模拟可变对象的不变性 Freezable 类型为某些图形元素(如几何形状 画笔以及动画)提供了一个通用的基础 值得注意的是 Freezable 不是一个 Visual 当应用 Freezable 以填充另一个对象的属性值时 它包含的属性将变成子属性 而这些子属性可能会影响呈现

AnimatableAnimatable 是一个 Freezable 派生类 它特别添加了动画控件层和某些实用工具成员 从而使当前动画的属性可以与未动画的属性区分开

lishixinzhi/Article/program/ASP/201311/21854

给你推荐真正的经典

Applications=Code+Markup(WPF程序设计指南)Charles Petzold

windows presentation foundation unleashed(WPF揭秘)Adam Nathan

Programming Windows Presentation Foundation

网上都可以下载到书籍和源码,找不到我给你传一个。

以上就是关于在MFC中使用WPF技术全部的内容,包括:在MFC中使用WPF技术、WPF基础教程之基元素、求葵花宝典—WPF自学手册,中的代码等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10124100.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存