mfc对话框中如何嵌入c#winform窗口,类似下图把图一嵌入到图2指定的位置
用winexec启动程序,FindWindow找到C#的窗口(最好循环获取,因为启动需要时间,不是立刻调用就能得到)
然后用 SetWindowLong 修改窗体的样式去掉边框,用SetParent将窗体装入mfc
以下代码你需要根据实际,略微修改
#include <afxwin.h>
// 声明全局变量用于存储C#窗口的句柄
HWND g_hCSharpWnd = NULL;
// MFC对话框类
class CMyDialog : public CDialog
{
public:
CMyDialog(CWnd* pParent = NULL) : CDialog(IDD_MYDIALOG, pParent) {}
// MFC消息映射宏
DECLARE_MESSAGE_MAP()
// MFC对话框消息处理函数
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};
// MFC消息映射宏
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_WM_CREATE()
END_MESSAGE_MAP()
// MFC对话框消息处理函数
int CMyDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
// 启动C#程序
WinExec("YourCSharpProgram.exe", SW_SHOW);
// 循环获取C#窗口句柄,直到找到为止
while (g_hCSharpWnd == NULL)
{
// 使用C#窗口的标题或类名进行查找,根据实际情况修改
g_hCSharpWnd = FindWindow(NULL, "YourCSharpWindowTitle");
// 等待一段时间再次尝试查找
Sleep(1000);
}
// 修改C#窗口的样式,去掉边框
LONG style = GetWindowLong(g_hCSharpWnd, GWL_STYLE);
style &= ~WS_BORDER;
SetWindowLong(g_hCSharpWnd, GWL_STYLE, style);
// 将C#窗口装入MFC对话框
CWnd* pCSharpWnd = CWnd::FromHandle(g_hCSharpWnd);
pCSharpWnd->SetParent(this);
// 调整C#窗口的位置和大小
CRect rect;
GetClientRect(&rect);
pCSharpWnd->MoveWindow(rect);
return 0;
}
// MFC应用程序类
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// MFC应用程序初始化函数
BOOL CMyApp::InitInstance()
{
CMyDialog dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
return FALSE;
}
// 全局MFC应用程序对象
CMyApp theApp;
问题没得到解决,应该跟你的进程启动方式有关,也可能是你查找窗口的代码有点问题,方便的话,把c#工程发出来看一下问题。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ClassLibrary2
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("hello world!");
}
}
}
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
在MFC对话框中嵌入一个C# WinForm窗口,可以使用MFC中的CWinFormsControl类来实现。具体步骤如下:
1、 创建一个MFC对话框应用程序,并添加一个控件用于容纳WinForm窗口。在资源编辑器中创建一个“Picture Control”控件,可以通过“插入ActiveX控件”来添加,然后调整控件的大小和位置,以便容纳WinForm窗口。
2、 在MFC应用程序中添加一个CWinFormsControl类。右键单击项目,选择“添加类”,然后在“添加类向导”中选择“MFC”->“控件类”,输入类名并选择CWinFormsControl作为基类。
3、 在CWinFormsControl类中添加一个C# WinForm窗口。在CWinFormsControl类的头文件中,添加以下代码:
using namespace System::Windows::Forms;
public ref class CMyWinFormsControl : public CWinFormsControl
{
public:
CMyWinFormsControl()
{
// 创建C# WinForm窗口
m_pMyWinForm = gcnew MyWinForm();
m_pMyWinForm->TopLevelControl = this;
m_pMyWinForm->Visible = true;
}
protected:
MyWinForm^ m_pMyWinForm;
};
这里的MyWinForm是一个C# WinForm窗口类,它是在Visual Studio中创建的。
4、 在MFC对话框类中添加一个CWinFormsControl成员变量。在对话框类的头文件中,添加以下代码:
#include "MyWinFormsControl.h"
class CMyDialog : public CDialogEx
{
public:
CMyWinFormsControl m_myWinFormsControl;
};
5、 在OnInitDialog()函数中创建CWinFormsControl对象并将其添加到MFC对话框中。在对话框类的源文件中,添加以下代码:
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 获取控件句柄
CWnd* pWnd = GetDlgItem(IDC_WINFORMS_CONTROL);
// 创建CWinFormsControl对象
RECT rect;
pWnd->GetWindowRect(&rect);
ScreenToClient(&rect);
m_myWinFormsControl.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, rect, this, IDC_WINFORMS_CONTROL);
return TRUE;
}
这里的IDC_WINFORMS_CONTROL是在资源编辑器中创建的控件ID。
6、 在MFC对话框类的OnSize()函数中调整CWinFormsControl对象的大小。在对话框类的源文件中,添加以下代码:
void CMyDialog::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// 调整控件大小
if (m_myWinFormsControl.GetSafeHwnd())
{
CRect rect;
GetDlgItem(IDC_WINFORMS_CONTROL)->GetWindowRect(&rect);
ScreenToClient(&rect);
m_myWinFormsControl.MoveWindow(&rect);
}
}
这样就完成了在MFC对话框中嵌入一个C# WinForm窗口的操作。在运行程序时,你应该能够看到C# WinForm窗口被嵌入到了MFC对话框中,并且可以在MFC应用程序中与其交互。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
引用ChatGPT部分内容参考:
以下是将C# WinForm嵌入MFC对话框的示例代码:
在MFC的对话框资源中添加一个需要使用的ActiveX控件,并将其命名为“axWinForm”。
在你的MFC应用程序的头文件中包含用于嵌入C# WinForm的类:
#import "mscorlib.tlb" raw_interfaces_only, raw_native_types, no_namespace
#import "System.Windows.Forms.tlb" raw_interfaces_only, raw_native_types, no_namespace named_guids
创建一个用于管理C# WinForm窗口的C++封装类:
class CWinForm {
public:
CWinForm(void);
virtual ~CWinForm(void);
BOOL Create(CWnd* pParentWnd, RECT rc);
LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0);
void Show(void);
void Hide(void);
HWND GetSafeHwnd(void) const;
protected:
HWND m_hWnd;
CComPtr<System::Windows::Forms::Form> m_pForm;
CComPtr<System::Windows::Forms::Control> m_pHost;
};
后续操作都可以在CWinForm类中进行。
在CWinForm类的实现文件中添加以下代码:
CWinForm::CWinForm(void) : m_hWnd(NULL)
{
CoInitialize(NULL);
}
CWinForm::~CWinForm(void)
{
if (m_pForm != NULL) {
m_pForm->Close();
m_pForm.Release();
}
CoUninitialize();
}
BOOL CWinForm::Create(CWnd* pParentWnd, RECT rc)
{
m_pHost = GetDlgItem(pParentWnd->GetSafeHwnd(), IDC_WINFORM);
HRESULT hr = ::CoCreateInstance(CLSID_CorRuntimeHost, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pRuntimeHost));
if (FAILED(hr)) {
return FALSE;
}
m_pRuntimeHost->Start();
IUnknownPtr ptr;
hr = m_pRuntimeHost->GetDefaultDomain(&ptr);
if (FAILED(hr)) {
return FALSE;
}
CComBSTR bstrAssembly("MyWinForm");
CComBSTR bstrTypeName("MyWinForm.Form1");
CComPtr<IDispatch> pDispatch;
hr = ptr->CreateInstance(bstrAssembly, bstrTypeName, &pDispatch);
if (FAILED(hr)) {
return FALSE;
}
hr = pDispatch.QueryInterface(&m_pForm);
if (FAILED(hr)) {
return FALSE;
}
m_pHost->GetControlUnknown()->QueryInterface(IID_PPV_ARGS(&m_pOleClientSite));
hr = m_pForm->put_Visible(VARIANT_TRUE);
if (FAILED(hr)) {
return FALSE;
}
hr = m_pForm->QueryInterface(&m_pOleObject);
if (FAILED(hr)) {
return FALSE;
}
m_pOleObject->SetClientSite(m_pOleClientSite);
HWND hWndHost;
m_pHost->GetControlWindow(&hWndHost);
int nLeft = rc.left;
int nTop = rc.top;
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;
::MoveWindow(hWndHost, nLeft, nTop, nWidth, nHeight, TRUE);
return TRUE;
}
LRESULT CWinForm::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
CComQIPtr<IOleInPlaceActiveObject, &IID_IOleInPlaceActiveObject> ipActive(m_pOleInPlaceObject);
if (ipActive) {
ipActive->TranslateAccelerator(&m_msg);
}
LRESULT lResult = 0;
BOOL bHandled = FALSE;
if (m_pForm) {
m_pForm->ProcessKeyPreview(&m_msg, &bHandled);
if (!bHandled) {
lResult = CWnd::DefWindowProc(message, wParam, lParam);
}
}
return lResult;
}
void CWinForm::Show(void)
{
m_pForm->Show();
}
void CWinForm::Hide(void)
{
m_pForm->Hide();
}
HWND CWinForm::GetSafeHwnd(void) const
{
if (m_pForm) {
CComPtr<IWin32Window> pWin32Window;
m_pForm->QueryInterface(&pWin32Window);
HWND hWnd;
pWin32Window->get_Handle((HWND*)hWnd);
return hWnd;
}
return nullptr;
}
在MFC对话框的OnInitDialog()中添加以下代码:
BOOL CMyDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
RECT rc;
GetDlgItem(IDC_WINFORM)->GetWindowRect(&rc);
ScreenToClient(&rc);
m_winform.Create(this, rc);
return TRUE;
}
最后添加以下代码以在需要时调用WinForm窗口的方法:
m_winform.SendMessage(WM_KEYUP, VK_SPACE, 0);
请根据实际需要进行更改和修改。
AutoScaleMode:当屏幕分辨率或字体发生改变时,窗体和控件是如何发生变化的。
- None : 禁用自动缩放。(默认时)
- Font :根据类使用的字体(通常为系统字体)的维度控制缩放。如果希望控件或窗体根据操作系统中字体的大小进行拉伸或缩小,则按 Font 缩放十分有用,如果控件或窗体的绝对大小无关紧要,则应使用这种方式进行缩放。比如:一个按钮的文字,改变了系统的字体大小,按钮也随着变大到能完整显示文字。例子:新建一个winform,字体为 ‘宋体 9pt’,上面还有一个button,用来参考,然后,先改变winform的字体大小,就改为‘宋体 16pt’吧。这时候,连按钮都变大了。
- Dpi : 根据显示分辨率控制缩放。常用分辨率为 96 和 120 DPI。如果要相对于屏幕确定控件或窗体的大小,则按 Dpi 缩放十分有用。例如,对于显示图表或其他图形的控件,可能希望使用每英寸点数 (DPI) 缩放,以便该控件始终占据一定百分比的屏幕
- Inherit : 根据类的父类的缩放模式控制缩放。如果不存在父类,则禁用自动缩放。
AutoScroll:只是当控件内容大于它的可见区域时是否自动显示滚动条。
- TRUE—是
- FALSE—否
AutoSize:指定控件是否自动调整自身的大小以适应其内容的大小。
- TRUE—是
- FALSE—否
AutoSizeMode:指定用户界面元素自动调整自身大小的模式。
- GrowOnly—生成的窗体可以用鼠标调节大小
- GrowAndShrik—生成的窗体不可以用鼠标调节大小
Anchor:定义某个控件绑定到的容器的边缘,当控件锚定到某个边缘时,与指定边缘最接近的控件边缘与指定边缘之间的距离将保持不变。
-Top——表示控件中与父窗体(或父控件)相关的顶部应该保持固定(Anchor相当于是将控件钉在了父控件上,不管父控件怎么放大缩小,它与父控件边缘距离都将保持绝度距离不变)
- Bottom——表示控件中与父窗体(或父控件)相关的底边应该保持固定
- Left——表示控件中与父窗体(或父控件)相关的左边缘应该保持固定
- Right——表示控件中与父窗体(或父控件)相关的右边缘应该保持固定
- None——漂浮
Dock:用于指定控件应停放在窗口的边框上,用户重新设置了窗口的大小,这个控件将继续停放在窗口的边框上,例如,如果指定控件停放在窗口的底部边界上,则无论窗口的大小改变,这个控件都将改变大小,或移动其位置,确保总是位于屏幕的底部。虽然Anchor属性也可以实现这一点,但是dock属性使得你能够在父窗体中让子窗体可以在上方(或旁边)互相“堆叠”。
- Top——迫使控件位于父窗体(或控件)的顶部。如果有同一个父窗体的其它子控件也被设置为停驻在顶部的话,那么控件将在彼此上方相互堆叠。
- Bottom——迫使控件位于父窗体(或控件)的底部。如果有同一个父窗体的其它子控件也被设置为停驻在底部的话,那么控件将在彼此上方相互堆叠。
- Left——迫使控件位于父窗体(或控件)的左边。如果有同一个父窗体的其它子控件也被设置为停驻在左边的话,那么控件将在彼此旁边相互堆叠。
- Right——迫使控件位于父窗体(或控件)的右边。如果有同一个父窗体的其它子控件也被设置为停驻在右边的话,那么控件将在彼此旁边相互堆叠。
- Fill——迫使控件位于父窗体(或控件)的上方。如果有同一个父窗体的其它子控件也被设置为停驻在上方的话,那么控件将在彼此上方相互堆叠。
- None——表示控件将会正常运转。
以下内容引用CHATGPT、有用望采纳:
在MFC对话框中嵌入C# WinForm窗口,可以使用ActiveX控件来实现。
首先,在C# WinForm项目中,将窗口作为ActiveX控件导出。
然后,在MFC项目中,添加ActiveX控件。
最后,在MFC项目中,使用ActiveX控件。
示例代码:
C# WinForm项目中,导出ActiveX控件:
namespace WinFormControlLibrary
{
[ComVisible(true)]
[Guid("D2A8D2A1-6E1F-4A0C-9CDD-4B0B3C9B4E4B")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IWinFormControl))]
public partial class WinFormControl : UserControl, IWinFormControl
{
public WinFormControl()
{
InitializeComponent();
}
public string GetText()
{
return textBox1.Text;
}
public void SetText(string text)
{
textBox1.Text = text;
}
#region IWinFormControl 成员
string IWinFormControl.GetText()
{
return GetText();
}
void IWinFormControl.SetText(string text)
{
SetText(text);
}
#endregion
}
[ComVisible(true)]
[Guid("D1D0C2C0-12D9-4F58-BD5B-5A657F2D9B3F")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IWinFormControl
{
string GetText();
void SetText(string text);
}
}
MFC项目中,使用ActiveX控件:
// 在对话框类中添加成员变量
CWnd m_wndWinFormControl;
// 在OnInitDialog()函数中,创建ActiveX控件
m_wndWinFormControl.Create(_T("WinFormControlLibrary.WinFormControl.1"), NULL, WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, IDC_WINFORMCONTROL);
// 在OnSize()函数中,调整ActiveX控件的大小和位置
CRect rect;
GetDlgItem(IDC_WINFORMCONTROL)->GetWindowRect(&rect);
ScreenToClient(&rect);
m_wndWinFormControl.MoveWindow(rect);
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在MFC对话框中嵌入C# Winform窗口可以使用MFC中的CStatic控件。下面是详细步骤:
在MFC对话框上添加一个CStatic控件,并为其设置唯一的ID,例如 IDC_WINFORM。
在MFC中使用C++/CLI创建一个中间层,并在其中创建C# Winform控件。这里我假设您已经熟悉了C++/CLI和C# Winform开发,并已经有了可添加到控件中的C# Winform窗体。
将中间层窗体声明为MFC中的CStatic控件的变量。在此处定义一个名为m_winform的CStatic变量。
CStatic m_winform;
//在C++/CLI中创建一个名为"WinformWrapper"的中间层窗体
m_winform.Create("", WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, IDC_WINFORM);
HWND hWinformWrapper = (HWND)m_winform.GetSafeHwnd();
//将中间层窗体绑定到m_winform上
WinformWrapper^ pWinformDlg = gcnew WinformWrapper();
pWinformDlg->CreateControl();
IntPtr hWinform = pWinformDlg->Handle;
::SetParent((HWND)hWinform.ToPointer(), hWinformWrapper);
以上代码中,WinformWrapper是在C++/CLI中定义的中间层,其包含了您所编写的C# Winform控件代码。使用Create()方法创建一个可见的m_winform控件,并将其绑定到C++/CLI中间层上的窗口。最后使用SetParent()方法将中间层窗口绑定到CStatic控件上。
CRect rect;
m_winform.GetClientRect(&rect);
m_winform.MoveWindow(20, 20, rect.Width(), rect.Height());
完整的示例代码如下:
MFC对话框的头文件:
#include "WinformWrapper.h"
#include <vcclr.h> //需要包含vcclr.h头文件
//定义一个名为m_winform的CStatic控件
CStatic m_winform;
MFC对话框的实现文件:
BOOL CMFCDlg::OnInitDialog()
{
//省略其他初始化代码
//在C++/CLI中创建一个名为"WinformWrapper"的中间层窗体
m_winform.Create("", WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, IDC_WINFORM);
HWND hWinformWrapper = (HWND)m_winform.GetSafeHwnd();
//将中间层窗体绑定到m_winform上
WinformWrapper^ pWinformDlg = gcnew WinformWrapper();
pWinformDlg->CreateControl();
IntPtr hWinform = pWinformDlg->Handle;
::SetParent((HWND)hWinform.ToPointer(), hWinformWrapper);
//调整m_winform控件的位置和大小
CRect rect;
m_winform.GetClientRect(&rect);
m_winform.MoveWindow(20, 20, rect.Width(), rect.Height());
return TRUE;
}
中间层头文件WinformWrapper.h:
#pragma once
#include <Windows.h>
using namespace System::Windows::Forms;
//定义一个名为WinformWrapper的中间层窗体
public ref class WinformWrapper : public Form
{
public:
//使用CreateControl方法创建控件,定义为public类型
void CreateControl()
{
this->SuspendLayout();
this->TopLevel = false;
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->Dock = DockStyle::Fill;
this->ResumeLayout(false);
}
};
请注意,在Windows Forms中,我们不能显式地调用CreateWindowEx或CreateDialog来创建控件和窗口。相反,我们可以使用CreateControl方法创建控件,并在其中定义其窗口句柄。在中间层中,我们需要使用System::Windows::Forms::Control的SuspendLayout和ResumeLayout方法来禁止和重新启用屏幕布局操作。
如果我的回答解决了您的问题,请采纳!