在WPF的程序中,嵌入其他进程的窗体
作者:互联网
我最近遇到了这样一个问题,就是我的WPF程序中,需要用到32位的COM组件。所以我的WPF程序也是要32位的。但是32的程序的逻辑内存最多只有2G,因此,当这个COM组件比较吃内存的时候,程序就会出现内存不够的情况,就会出现异常。因此,我的解决方案是使用winform来调用这个COM组件。然后WPF程序再调用winform。这样,就把内存分配到了多个进程当中,就不会出现一个进程使用太多内存的情况。
下面是WPF实现此功能的简单代码
窗体XAML代码
<Window x:Class="WPF_Open_Exe.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Open_Exe"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="Window1" Height="450" Width="800">
<Grid>
<WindowsFormsHost x:Name="WindowsFormsHost1" Background="Red" VerticalAlignment="Top" HorizontalAlignment="Left" Height="450" Width="800">
</WindowsFormsHost>
</Grid>
</Window>
页面的逻辑代码:
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll", SetLastError = true)]
public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
Process _process;
System.Windows.Forms.Panel _hostPanel;
public bool StartAndEmbedProcess(string processPath)
{
bool isStartAndEmbedSuccess = false;
if (WindowsFormsHost1 != null)
{
_hostPanel = new System.Windows.Forms.Panel();
WindowsFormsHost1.Child = _hostPanel;
}
_process = System.Diagnostics.Process.Start(processPath);
//确保可获取到句柄
Thread thread = new Thread(new ThreadStart(() =>
{
while (true)
{
if (_process.MainWindowHandle != (IntPtr)0)
{
break;
}
Thread.Sleep(10);
}
}));
thread.Start();
Thread.Sleep(1000);
isStartAndEmbedSuccess = EmbedApp(_process);
if (!isStartAndEmbedSuccess)
{
CloseApp(_process);
}
return isStartAndEmbedSuccess;
}
public bool EmbedExistProcess(Process process)
{
_process = process;
return EmbedApp(process);
}
/// <summary>
/// 将外进程嵌入到当前程序
/// </summary>
/// <param name="process"></param>
private bool EmbedApp(Process process)
{
//是否嵌入成功标志,用作返回值
bool isEmbedSuccess = false;
//外进程句柄
IntPtr processHwnd = process.MainWindowHandle;
//容器句柄
IntPtr panelHwnd = _hostPanel.Handle;
if (processHwnd != (IntPtr)0 && panelHwnd != (IntPtr)0)
{
//把本窗口句柄与目标窗口句柄关联起来
int setTime = 0;
while (!isEmbedSuccess && setTime < 10)
{
isEmbedSuccess = (SetParent(processHwnd, panelHwnd) != 0);
Thread.Sleep(100);
setTime++;
}
//设置初始尺寸和位置
MoveWindow(_process.MainWindowHandle, 0, 0, (int)ActualWidth, (int)ActualHeight, true);
}
if (isEmbedSuccess)
{
//_embededWindowHandle = _process.MainWindowHandle;
}
return isEmbedSuccess;
}
protected override void OnRender(DrawingContext drawingContext)
{
if (_process != null)
{
MoveWindow(_process.MainWindowHandle, 0, 0, (int)ActualWidth, (int)ActualHeight, true);
}
base.OnRender(drawingContext);
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
if (_hostPanel != null)
{
_hostPanel.Width = (int)this.Width;
_hostPanel.Height = (int)this.Height;
WindowsFormsHost1.Width = (int)this.Width;
WindowsFormsHost1.Height = (int)this.Height;
}
this.InvalidateVisual();
base.OnRenderSizeChanged(sizeInfo);
}
/// <summary>
/// 关闭进程
/// </summary>
/// <param name="process"></param>
private void CloseApp(Process process)
{
if (process != null && !process.HasExited)
{
process.Kill();
}
}
public void CloseProcess()
{
CloseApp(_process);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
StartAndEmbedProcess(@"C:\Windows\system32\mspaint.exe");
}
}
运行后的效果图,这里是把系统的画图程序调进来了,调用其他的程序也是可以的,亲测有效。
代码链接:链接:https://pan.baidu.com/s/1BO7DLC0uy6pka8cjsaTUDA
提取码:zxhe
--来自百度网盘超级会员V3的分享
标签:IntPtr,嵌入,process,hostPanel,int,窗体,bool,WPF,public 来源: https://blog.csdn.net/qq_34090937/article/details/122525006