在MFC下调用WPF控件的总结

为了在原有MFC程序上支持WPF的Ink功能,看了N天的.Net相关知识。我的机器上,开发环境实在是令人发指,如果有人碰到了我现在的问题,希望这篇文章能够对他有所帮助。

    我安装了Visusal Studio 2005,.Net Framework 2.0, 3.5, 以及不知道啥时候装的3.0版本(我怀疑是安装3.5时候带进来的版本)。在我的2005的开发环境里面,找不到WPF的模版。去网上搜索,说是需要安装2005的一个extension for wpf。我很辛苦的找到了这个extension(在MS的官网上没有找到能够下载的链接),安装时候告诉我没有Framework 3.0(实际上我的磁盘上有这个版本的所有dll)。我又尝试了下载 .Net Framework3.0,安装时候告诉我已经有了更高的版本(3.5),不能继续安装3.0了。接下来我就没有继续尝试其他动作了(想先卸载3.5来着,怕影响其他project,没有这么做)。

    ok,看看如何在上面这个环境下来开发WPF程序:
    1,创建一个C# 应用程序。(我选择的是Console)
    2,添加一个xaml页面(new或者add exist)
    3,添加一个对应的c#页面(new或者add exist)
    4,添加对Framework的引用,分别是PresentationCore, PresentationFramework, WindowsBase。它们应该在C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\下面。

    5,Unload Project。
    6,右键单击被关闭的项目,选择编辑对应的工程文件(*.csproj)。
    7,找到响应的xaml文件名字,把它前面的<None 改为 <Page 。
    8,找到最后面这样一行:
         <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
        在它下面添加一行:
         <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
    9,保存工程文件,关闭。右键点击关闭的项目,选择 Reload Project

    在Reload的时候,有可能visual studio 2005会提示工程文件格式的有关问题,你需要选择继续。

    这样之后,就能正常编译xaml文件了。


    在能够正常编译WPF项目之后,可以把该项目的输出类型更改为:类库,这样我们才能在MFC程序里面调用C#编写的WPF控件。
    下面是如果在MFC程序里面调用WPF控件的步骤:

    1,打开你原有的MFC程序,或者新创建一个MFC应用程序。
    2,打开工程属性面板,把配置属性-常规-公共语言运行库支持(CLR)的属性更改为“公共语言运行库支持(/clr)”;
    3,在通用属性里面,添加对 .Net Framework 3.0相关的运行库的引用。(和上面第四个步骤一样)
    4,添加下面这段代码:
    using namespace System;
    using namespace System::Windows;
    using namespace System::Windows::Controls;
    using namespace System::Windows::Media;
    using namespace System::Runtime;
    using namespace System::Runtime::InteropServices;
    using namespace System::Windows::Interop;
    ref class Globals {
    public:
      static System::Windows::Interop::HwndSource^ gHwndSource;
      static TuioInk::TuioInkCanvas^ inkCanvas;
    };
    HWND hwndWPF; //The hwnd associated with the hosted WPF page
    HWND GetHwnd(HWND parent, int x, int y, int width, int height)
    {
        System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters ("TestMFCWPF");
     sourceParams->PositionX = x;
     sourceParams->PositionY = y;
     sourceParams->Height = height;
     sourceParams->Width = width;
     sourceParams->ParentWindow = IntPtr(parent);
     sourceParams->WindowStyle = WS_VISIBLE | WS_POPUP;
     //sourceParams->ExtendedWindowStyle = (int)WS_EX_TRANSPARENT;
     sourceParams->UsesPerPixelOpacity = true;
     Globals::gHwndSource = gcnew System::Windows::Interop::HwndSource(*sourceParams);
     Globals::inkCanvas = gcnew TuioInk::TuioInkCanvas();
     //Globals::inkCanvas->Background = System::Windows::Media::Brushes::Transparent;
     //Globals::gHwndSource->CompositionTarget->BackgroundColor = System::Windows::Media::Colors::Transparent;
     FrameworkElement^ myPage = Globals::inkCanvas;
     Globals::gHwndSource->RootVisual = myPage;
     return (HWND) Globals::gHwndSource->Handle.ToPointer();
    }

    5,在你的MFC窗口的OnCreate事件里面,调用GetHwnd函数获取控件窗口句柄。

    OK,做完上面这些事情,基本上就能够编译运行了。如果出现编译错误,看看是不是编译选项冲突,去网上找找就能知道如果解决这些编译选项冲突了。

    在MFC下调用WPF程序,关键的类是HwndSource,可以去MSDN上查一下这个类的说明,以便做更深入的了解。MS的msdn官网上也讲了如何做MFC与WPF的混合编程(我忘记了地址)。

    另外上面代码里面有2行很关键:
    sourceParams->WindowStyle = WS_VISIBLE | WS_POPUP;
    sourceParams->UsesPerPixelOpacity = true;
    如果不是WS_POPUP的类型(比如WS_CHILD),那么透明的效果也不会出现,表现的结果很是怪异。

没有更多推荐了,返回首页