在MFC中使用WPF技术

来源:互联网 发布:36周胎儿发育标准数据 编辑:程序博客网 时间:2024/06/11 08:21

在MFC中使用WPF技术

   一、介绍

    本文将以一个实例来说明如何将WPF技术集成在基于MFC的应用程序中。这种技术的主要目的是为了增强基于Win32/MFC的应用程序的在图形方面的表现能力。本文所提供的演示程序将在MFC对话框架应用程序中显示一个WPF动画时钟。界面如图1所示:

 


    
    本文需要的开发工具和开发库
    为了建立和运行demo程序,我们需要安装如下的组件:


    1. Visual Studio 2005 或Visual Studio 2008
    2. .NET Framework 3.0 或.NET Framework3.5

   所需要的平台
    demo程序必须在下面支持.NET Framework3.0的操作系统平台上运行:

   1. Windows Vista
   2. Windows XP SP2
   3. Windows Server 2003 SP1

   如果你是一名C++开发人员,并且想使用WPF技术来增强自己的基于Win32/MFC应用程序,本文非常适合你。为了能从本文学习到更多的知识,我们需要熟悉VC++/CLi, MFC, XAML和C#。但是,如果我们不了解C#或XAML,我们仍然可以通过引用现成的DLL来使用WPF程序。

二、什么是WPF

    WPF是Windows Presentation Foundation的缩写。它是微软.NET Framework3.0的一个子系统。这种技术允许开发人员高效地创建可视化的应用程序,并改善用户体验。由于WPF的发布,使用Windows程序在富控件的设计、开发上更如虎添翼。WPF主要关注一套应用程序服务:用户接口、2D和3D、矢量图、动画、数据绑字、音频,并提供一个在UI和商业逻辑之间的非常清晰的界限。

    WPF API是被管制的代码,但是大多数Win32/MFC程序是非管制的C++代码。按着惯例,WPF API不能通过非常制程序调用。然后,通过使用VC编译器的/clr选项,我们可以建立一个由管制和非管制混合而面的系统。在这个系统中,我们可以使管制和非管制代码无缝地混合在一起。

    有一个要注意的是在C++工程中不允许编译XAML文件。因此,我们必须建立一个包含在本例中所需要的所有XAML而的C# DLL,然后在C++工程中包含这个Dll引用。

    有两种基本的技术可以融合WPF和Win32/MFC代码:

    1. 将WPF放到Win32/MFC程序中:使用这种技术,开发人员可以使用WPF的高级图形能力来渲染Win32/MFC应用程序。

    2.       将Win32/MFC放到WPF中:使用这种技术,开发人员可以在WPF中使用已经存在的

    Win32/MFC控件,并通过一定的机制来传递数据。

    在本文中将采用第一种方法。

   三、     融合Win32/MFC和WPF程序

    上面部分所说的是本例的基本规则,下面在本节中将介绍如何编写具体的实现代码。在本例中,我首先会演示使用XAML和C#建立WPF内容,并在VC++中引用这个DLL。

    本例的目的是建立一个用于设置日期和时间的设置工具,其中动画部分使用WPF实现。程序的其他部分仍然使用MFC实现。

    这个演示程序由两部分组成:一个是MFCHostMPF(由VC++/MFC代码组成),另一个是WPFControls(由XAML和C#代码组成)。这个MFCHostWPF工程将由WPFControls工程所产生的DLL作为一个外部的引用。如图2所示:

 

    
    向MFC工程中加入一个WPF引用。如图3和图4所示:

 

 

 

    三、在MFC应用程序中加入和WPF相关的代码

    先提一下,gcnew关键字被用于建立一个管制类型的实例,在本例中将建立一个垃圾回收集合栈的实例。所有被gcnew分配的内存空间将被垃圾回收器自动管理,而开发人员并不需要为什么时间释放它们而操心。

    为了使用WPF程序,关键是System::Windows::Interop::HwndSource类。这个类将在Win32窗口中使用WPF程序,因此,WPF程序可以作为MFC窗口的子窗口放到UI上。而在WPF对象和Win32窗口之间的通讯要通过引用C++程序中被存储的静态字段。这些静态字段的代码如下:

ref class Globals
{
public
:
static System::Windows::Interop::HwndSource^
gHwndSource;
static WPFControls::AnimClock^
gwcClock;
};
    
    HWND hwndWPF;    // 和WPF相关的hwnd
    为了建立一个HwndSource,首先需要建立一个HwndSourceParameters结构,这个结构需要如下的参数:
    1. 类、窗口、窗口类型
    2. 窗口的初始位置
    3. 窗口的初始尺寸
    4. 父窗口
    一但我们将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) == -1
)
return -1
;
hwndWPF = GetHwnd(this->GetSafeHwnd(), 20, 28, 205, 130
);
return 0
;
}

    
    四、结论

    我们现在可以看到,通过集成WPF和Win32/MFC应用程序可以为我们增添很多非常酷的特性来加强用户体验。本文所提供的实例只是抛砖引玉,读者可以使用这项技术做出更复杂的应用程序来。

来自: http://hi.baidu.com/vipver/blog/item/df6255829037f0b26d81195d.html
原创粉丝点击