WPF 中的 WindowsFormsHost 不显示托管应用程序
WindowsFormsHost in WPF Not Displaying Hosted Application
在我的 WPF 中,我有一个包含 WindowsFormsHost 的网格,它将承载一个 .exe。
我的 .xaml 代码是:
<Window x:Class="PracticeWPF.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:PracticeWPF"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1300">
<Grid x:Name="grid">
<Button x:Name="BtnRun" Content="Run"
HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" Click="BtnRun_Click"/>
<WindowsFormsHost x:Name="formshost" Margin="0,39,0,0"
Height="720" Width="1280"/>
</Grid>
</Window>
还有我的cs:
namespace PracticeWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll")]
public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void BtnRun_Click(object sender, EventArgs e)
{
Process proc = Process.Start("notepad.exe");
proc.WaitForInputIdle();
while (proc.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(100);
proc.Refresh();
}
SetParent(proc.MainWindowHandle, formshost.Handle);
}
}
}
当我使用 WinForm 时一切正常,但是当我在 WPF 中使用 WindowsFormsHosting 时,.exe 不可见。
任何帮助将不胜感激。
谢谢。
恐怕 WindowsFormsHost 无法在另一个应用程序中托管整个 Windows Forms 应用程序。
它用于在 WPF 视图中托管一个单独的 Windows 表单 控件。
如果您想获取 WPF window 的句柄,请尝试:
new System.Windows.Interop.WindowInteropHelper(this).Handle
您想使用此句柄而不是 formshost.Handle
。
在此linkDocking Window inside another Window我想你的答案。我把它和你的代码匹配了
xaml
<Window x:Class="PracticeWPF.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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:PracticeWPF"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1300">
<Grid x:Name="grid">
<Button x:Name="BtnRun" Content="Run"
HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" Click="BtnRun_Click"/>
<WindowsFormsHost x:Name="formshost" Margin="0,39,0,0"
Height="720" Width="1280">
<wf:Button Text="by button" Visible="False"></wf:Button>
</WindowsFormsHost>
</Grid>
</Window>
和mainwindow.cs
namespace PracticeWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnRun_Click(object sender, EventArgs e)
{
//Process proc = Process.Start("notepad.exe");
//proc.WaitForInputIdle();
//while (proc.MainWindowHandle == IntPtr.Zero)
//{
// Thread.Sleep(100);
// proc.Refresh();
//}
this.Width = formshost.Width;
this.Height = formshost.Height;
dockIt();
}
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private Process pDocked;
private IntPtr hWndOriginalParent;
private IntPtr hWndDocked;
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
private void dockIt()
{
if (hWndDocked != IntPtr.Zero) //don't do anything if there's already a window docked.
return;
IntPtr hWndParent = IntPtr.Zero;
pDocked = Process.Start(@"notepad");
while (hWndDocked == IntPtr.Zero)
{
pDocked.WaitForInputIdle(1000); //wait for the window to be ready for input;
pDocked.Refresh(); //update process info
if (pDocked.HasExited)
{
return; //abort if the process finished before we got a handle.
}
hWndDocked = pDocked.MainWindowHandle; //cache the window handle
}
//Windows API call to change the parent of the target window.
//It returns the hWnd of the window's parent prior to this call.
hWndOriginalParent = SetParent(hWndDocked, formshost.Handle);
//Wire up the event to keep the window sized to match the control
formshost.SizeChanged += new SizeChangedEventHandler(Panel1_Resize);
//Perform an initial call to set the size.
Panel1_Resize(new Object(), new EventArgs());
}
private void undockIt()
{
//Restores the application to it's original parent.
SetParent(hWndDocked, hWndOriginalParent);
}
private void Panel1_Resize(object sender, EventArgs e)
{
//Change the docked windows size to match its parent's size.
MoveWindow(hWndDocked, 0, 0, (int)formshost.Width, (int)formshost.Height, true);
}
}
}
在我的 WPF 中,我有一个包含 WindowsFormsHost 的网格,它将承载一个 .exe。 我的 .xaml 代码是:
<Window x:Class="PracticeWPF.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:PracticeWPF"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1300">
<Grid x:Name="grid">
<Button x:Name="BtnRun" Content="Run"
HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" Click="BtnRun_Click"/>
<WindowsFormsHost x:Name="formshost" Margin="0,39,0,0"
Height="720" Width="1280"/>
</Grid>
</Window>
还有我的cs:
namespace PracticeWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll")]
public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void BtnRun_Click(object sender, EventArgs e)
{
Process proc = Process.Start("notepad.exe");
proc.WaitForInputIdle();
while (proc.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(100);
proc.Refresh();
}
SetParent(proc.MainWindowHandle, formshost.Handle);
}
}
}
当我使用 WinForm 时一切正常,但是当我在 WPF 中使用 WindowsFormsHosting 时,.exe 不可见。 任何帮助将不胜感激。 谢谢。
恐怕 WindowsFormsHost 无法在另一个应用程序中托管整个 Windows Forms 应用程序。
它用于在 WPF 视图中托管一个单独的 Windows 表单 控件。
如果您想获取 WPF window 的句柄,请尝试:
new System.Windows.Interop.WindowInteropHelper(this).Handle
您想使用此句柄而不是 formshost.Handle
。
在此linkDocking Window inside another Window我想你的答案。我把它和你的代码匹配了
xaml
<Window x:Class="PracticeWPF.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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:PracticeWPF"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1300">
<Grid x:Name="grid">
<Button x:Name="BtnRun" Content="Run"
HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" Click="BtnRun_Click"/>
<WindowsFormsHost x:Name="formshost" Margin="0,39,0,0"
Height="720" Width="1280">
<wf:Button Text="by button" Visible="False"></wf:Button>
</WindowsFormsHost>
</Grid>
</Window>
和mainwindow.cs
namespace PracticeWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnRun_Click(object sender, EventArgs e)
{
//Process proc = Process.Start("notepad.exe");
//proc.WaitForInputIdle();
//while (proc.MainWindowHandle == IntPtr.Zero)
//{
// Thread.Sleep(100);
// proc.Refresh();
//}
this.Width = formshost.Width;
this.Height = formshost.Height;
dockIt();
}
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private Process pDocked;
private IntPtr hWndOriginalParent;
private IntPtr hWndDocked;
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
private void dockIt()
{
if (hWndDocked != IntPtr.Zero) //don't do anything if there's already a window docked.
return;
IntPtr hWndParent = IntPtr.Zero;
pDocked = Process.Start(@"notepad");
while (hWndDocked == IntPtr.Zero)
{
pDocked.WaitForInputIdle(1000); //wait for the window to be ready for input;
pDocked.Refresh(); //update process info
if (pDocked.HasExited)
{
return; //abort if the process finished before we got a handle.
}
hWndDocked = pDocked.MainWindowHandle; //cache the window handle
}
//Windows API call to change the parent of the target window.
//It returns the hWnd of the window's parent prior to this call.
hWndOriginalParent = SetParent(hWndDocked, formshost.Handle);
//Wire up the event to keep the window sized to match the control
formshost.SizeChanged += new SizeChangedEventHandler(Panel1_Resize);
//Perform an initial call to set the size.
Panel1_Resize(new Object(), new EventArgs());
}
private void undockIt()
{
//Restores the application to it's original parent.
SetParent(hWndDocked, hWndOriginalParent);
}
private void Panel1_Resize(object sender, EventArgs e)
{
//Change the docked windows size to match its parent's size.
MoveWindow(hWndDocked, 0, 0, (int)formshost.Width, (int)formshost.Height, true);
}
}
}