User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    Hosting WPF Content in an MFC Application



    Adding WPF-Related Code to an MFC Application

    For your information, the gcnew keyword is used to create an instance of managed type; this will create the instance on the garbage collected heap. All memory allocated by gcnew will be managed automatically by the garbage collector and developers will not need to worry about freeing them up.

    To host WPF content, the key is on the System::Windows::Interop::HwndSource class. This class will take care of wrapping the WPF content in a Win32 window, so that the WPF content can be incorporated into your user interface (UI) as a child window. Communication with the WPF content object is done by using the reference stored in the static fields. They're declared as static to prevent them from being inadvertently garbage collected.

    ref class Globals
    {
    public:
       static System::Windows::Interop::HwndSource^ gHwndSource;
       static WPFControls::AnimClock^ gwcClock;
    };
    
    HWND hwndWPF;    //The hwnd associated with the hosted WPF page
    

    To create an HwndSource, first create an HwndSourceParameters structure and populate it with the following parameters:

    • Class, window, and styles
    • Initial position of the window
    • Initial size of the window
    • The parent window

    Once you have populated the HwndSourceParameters structure, pass it to the HwndSource(HwndSourceParameters) constructor for the HwndSource.

    Then, you create your WPF clock class by calling its constructor WPFControls::AnimClock(). You also initialize the date & time by calling its ChangeDateTime() method.

    Finally, you assign the reference of the WPF clock object to the HwndSource object RootVisual property and return the HWND of the HwndSource by calling Handle.ToPointer().

    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();
    }
    

    So, whenver the user makes date or time changes, your MFC code will call RefereshWPFControl() to refresh the WPF clock.

    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;
    }
    

    Now that you have all your needed functions set, the last task is to find a place in your MFC dialog code to call the HwndSource instance creation function. There are a few possible locations to call it; one good place is in the OnCreate event handler.

    Handle the WM_CREATE notification

    Call the GetHwnd() function in the OnCreate event handler when the application first starts.

    int CMFCHostWPFDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
       if (CDialog::OnCreate(lpCreateStruct) == -1)
          return -1;
    
       hwndWPF = GetHwnd(this->GetSafeHwnd(), 20, 28, 205, 130);
    
       return 0;
    }
    

    Conclusion

    As you can see now, by applying WPF in Win32/MFC applications you can add lots of "perks" to the overall user experience while the program logics remain coded in the Win32/MFC style.

    Comments

    All suggestions and corrections are welcome.

    About the Author

    Kevin is a C++ & C# developer with proven ability to architect, program, and optimize code. He has more than 10 years programming experience for business solutions. He also has the passion for both playing and developing video games. Kevin can be reached via kevin.choong@hotmail.com.

    Downloads

  • MFCHostWPF-Bin.zip
  • MFCHostWPF-Src.zip

  • IT Offers


    Top Authors