Wrapping Interop HwndSource in c++/cli to be used in native c++ / MFC application

巧了我就是萌 提交于 2019-12-11 13:57:34

问题


I got an MFC application in native c++, that can not use \clr. I need to show a WPF Window inside a frame in this MFC application, so I am trying to make a wrapper in mixed C++(cli), that contains this WPF page and can be used by my MFC program.

So far I got the HwndSource to contain my WPF window:

WPFPageHost::WPFPageHost(){} 
HWND GetHwnd(HWND parent, int x, int y, int width, int height)
{

System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters(
"hi" // NAME
);
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; // style

source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
gcroot<Frame^> myPage = gcnew Frame();
myPage->Height = height;
myPage->Width = width;
myPage->Background = gcnew SolidColorBrush(Colors::LightGray);
gcroot<MyWindow^> newWindow = gcnew MyWindow;
myPage->Content = newWindow->Content;
source->RootVisual = myPage;
return (HWND) source->Handle.ToPointer();
}

the .h:

#pragma once
#include "resource.h"
#include <vcclr.h>
#include <string.h>
#include "stdafx.h"


using namespace System;
using namespace System::Windows;
using namespace System::Windows::Controls;
using namespace System::Windows::Interop;
using namespace System::Windows::Media;
using namespace MyAPP::WPF;

public class WPFPageHost
{
public:
    WPFPageHost();
};

gcroot<HwndSource^> source;

HWND GetHwnd(HWND parent, int x, int y, int width, int height);

Now I need a way to wrap it so I can call this to be added in the MFC Window. Does someone know how to do it? I am not sure if the code I have is legit enough too, so correct me if I am wrong pls.

Thanks!


回答1:


OK, this took some time and I still have performance issues but here is one way to do it.

First of all I got 2 new Projects. One is a MFC with \clr and one is a native MFC.

In the clr project you make a new class. Here the .h :

#pragma once
class AFX_EXT_CLASS WpfHostWindow : public CWnd
{
DECLARE_DYNAMIC(WpfHostWindow)

public:
WpfHostWindow();
virtual ~WpfHostWindow();

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

#ifdef _MANAGED
gcroot<System::Windows::Controls::Frame^> windowHandle;
#else
intptr_t windowHandle;
#endif

protected:
DECLARE_MESSAGE_MAP()
};

In the .cpp file you generate the hwndsource:

int WpfHostWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
    return -1;

CRect rect;
GetClientRect(&rect);

HwndSourceParameters^ sourceParams= gcnew HwndSourceParameters("CustomHost");
sourceParams->PositionX = 0;
sourceParams->PositionY = 0;
//sourceParams.Height = rect.Height();
//sourceParams.Width = rect.Width();
sourceParams->ParentWindow = (IntPtr)m_hWnd;
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;

System::Windows::Interop::HwndSource^ source  = gcnew HwndSource(*sourceParams);
source->SizeToContent = System::Windows::SizeToContent::WidthAndHeight;

Frame^ mainFrame = gcnew Frame();
mainFrame->UpdateLayout();
windowHandle = mainFrame;

source->RootVisual = windowHandle;

return 0;
}

In the native MFC project you only need to make a normal CDialog (Or whatever you want) and add a WpfHostWindow Object (Dont forget to reference and stuff). In the OnInitDialog() you can now use the .Create Funktion of the WpfHostWindow Object to make the WpfHostWindow as a Child. Now you can use (theoretically) the native MFC class to make an WPF instance inside your native MFC host.



来源:https://stackoverflow.com/questions/29918179/wrapping-interop-hwndsource-in-c-cli-to-be-used-in-native-c-mfc-applicatio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!