在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^ gHwndSourcestatic 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 = xsourceParams >PositionY = ysourceParams >Height = heightsourceParams >Width = widthsourceParams >ParentWindow = IntPtr(parent)sourceParams >WindowStyle = WS_VISIBLE | WS_CHILDGlobals::gHwndSource = gcnew System::Windows::Interop::HwndSource(*sourceParams)DateTime tm = DateTime::NowGlobals::gwcClock = gcnew WPFControls::AnimClock()Globals::gwcClock >ChangeDateTime(tm Year tm Month tm Day tm Hour tm Minute tm Second)FrameworkElement^ myPage = Globals::gwcClockGlobals::gHwndSource >RootVisual = myPagereturn (HWND) Globals::gHwndSource >Handle ToPointer()}

        因此 无论用户如何变化时钟 我们的MFC代码都会调用RefereshWPFControl()来刷新WPF时钟

void RefreshWPFControl() { FrameworkElement^ pageDateTime tm = DateTime::NowGlobals::gwcClock >ChangeDateTime(tm Year tm Month tm Day tm Hour tm Minute tm Second)page = Globals::gwcClockGlobals::gHwndSource >RootVisual = pagereturn}

        现在我们已经有了大部分我们需要的功能了 而最后的任务是在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

全局变量不能定义在H文件中,否则会因为重复的包含连接错误,你可以扮薯将全局变量定义在CPP中,在H文件中引用,如:

def.cpp:

#include "def.h"

int a = 0

int b = 0

def.h

#include "要包含的头文件"

//老野结构定义等

extern int a

extern int b

然后你其他需要使用变量的在包含def.h就可以了侍缺喊

MFC中有两类线程,分别称之为工作者线程和用户界面线程。扰扒二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。

工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32的API编程而言,这两种线程是没有区别孝李芦的,它们都只需线程的启动地址即可启动线程来执行任务

1、WIN的API函数CreateThread

HANDLE CreateThread(

LPSECURITY_ATTRIBUTESlpThreadAttributes, // SD

DWORDdwStackSize,// initial stack size

LPTHREAD_START_ROUTINElpStartAddress,// thread function

LPVOIDlpParameter, // thread argument

DWORDdwCreationFlags,// creation option

LPDWORDlpThreadId// thread identifier

)

//lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。

dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。

lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:

DWORD WINAPI ThreadProc (LPVOID lpParam) ,格式不正确将无法调用成功。

lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。

dwCreationFlags :线程标志,可取值如下

(1)CREATE_SUSPENDED-----创建一个挂起的线程,

(2)0---------------------------------表示创建后立即激活。

lpThreadId:保存新线程的id。

2、MFC的全局函数AfxBeginThread

CWinThread* AfxBeginThread( AFX_THREADPROCpfnThreadProc, LPVOIDpParam, intnPriority= THREAD_PRIORITY_NORMAL, UINTnStackSize= 0, DWORDdwCreateFlags= 0, LPSECURITY_ATTRIBUTESlpSecurityAttrs= NULL )

//用于创建工作者线程 其中pfnThreadProc指向线程函数 pParam为传递给线程函数的参数

CWinThread* AfxBeginThread( CRuntimeClass*pThreadClass, intnPriority= THREAD_PRIORITY_NORMAL, UINTnStackSize= 0, DWORDdwCreateFlags= 0, LPSECURITY_ATTRIBUTESlpSecurityAttrs= NULL )

//用于创建用户界巧带面线程 其中pThreadClass为CWinThread派生对象的RUNTIME_CLASS

3、MFC的CWinThread类的CreateThreat成员函数

BOOL CreateThread( DWORD dwCreateFlags = 0, UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL )

//CWinThread类支持工作者线程和用户界面线程 可以将一个CWinThread派生类的CRUNTIMECLASS的指针作为参数传递给AfxBeginThread函数以创建一个用户界面线程 CWinThread类的CreateThread成员函数创建一个调用进程的地址空间中执行的线程

VC 6.0 创建线程的三种方法

CreateThread/ExitThread

_beginthreadex/_endthreadex

AfxBeginThread /AfxEndThread

对以上三种方式的选择:

1.在使用了MFC的程序中使用AfxBeginThread函数或者CWinThread::CreateThread函数创建线程。

2.在非MFC工程中,如果要创建多线程,建议使用_beginthreadex

3.避免使用CreateThread函数。不使用_beginthread.

4.线程内部退出函数使用与创建函数配套的函数。


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

原文地址: http://outofmemory.cn/yw/12298264.html

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

发表评论

登录后才能评论

评论列表(0条)

保存