一介紹
本文將以一個實例來說明如何將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(tmYeartmMonthtmDay
tmHourtmMinutetmSecond);
FrameworkElement^ myPage = Globals::gwcClock;
Globals::gHwndSource>RootVisual = myPage;
return (HWND) Globals::gHwndSource>HandleToPointer();
}
因此
無論用戶如何變化時鐘
我們的MFC代碼都會調用RefereshWPFControl()來刷新WPF時鐘
void RefreshWPFControl()
{
FrameworkElement^ page;
DateTime tm = DateTime::Now;
Globals::gwcClock>ChangeDateTime(tmYeartmMonthtmDay
tmHourtmMinutetmSecond);
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 ;
}
四結論
我們現在可以看到通過集成WPF和Win/MFC應用程序可以為我們增添很多非常酷的特性來加強用戶體驗本文所提供的實例只是拋磚引玉讀者可以使用這項技術做出更復雜的應用程序來
From:http://tw.wingwit.com/Article/program/net/201311/11996.html