我需要启动一些Windows应用程序才能在表单中运行。我正在使用VS-15 IDE在C#上开发Windows桌面应用程序。
很多年前,这个话题已经解决了。这是我找到的最佳答案:
How can I run another application within a panel of my C# program?
然而,所有示例都涉及启动记事本,它可以正常工作。我确实可以在目标形式的目标面板内启动和运行记事本,并且运行良好。
但我不需要启动记事本,我需要启动其他已安装的应用程序,并且发现了令人沮丧的现实,即无法在目标面板/表单内启动所需的应用程序。它只是在表单之外打开。
甚至找到了OP需要启动IE的帖子,但结果相同,IE在表单之外启动。
阅读和阅读相关主题,我发现它可能是使用名为 EnumWindows 的东西解决的概率。我是C#的新手,我通常会处理Python。我甚至不是Windows的原生,不得不在VM中安装它。
我正在使用Visual Studio 2015.预期输出是Windows 7和8台机器的桌面应用程序,64位。
代码:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace < >
{
public partial class Form1:
{
private void btn_qui_Click(object sender, EventArgs e)
{
var postventa = new appUser("POSTVENTA", "",3);
try
{
frm_3.Show();
Process p = Process.Start("C://QuiterWeb/QuiterWeb.exe");
p.WaitForInputIdle();
SetParent(p.MainWindowHandle, frm_3.panel_3.Handle);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
运行代码时,.exe在表单外打开。但是,如果我把它打开notepad.exe,它会在特定的面板和窗体中打开。这表示目标已很好地映射到方法。
这里有什么问题?如何使.exe在面板和表单内运行?
答案 0 :(得分:2)
这取决于您的具体流程。它闲置时可能没有主窗口处理(它不常见,但可能会发生),或者它可能有几个主窗口#34;。
等待进程拥有第一个MainWindowHandle
的正确方法如下:
Process p = Process.Start("C://QuiterWeb/QuiterWeb.exe");
p.WaitForInputIdle();
while (p.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(100); // Don't hog the CPU
p.Refresh(); // You need this since `MainWindowHandle` is cached
// do additional checks, or add a timeout in case the process is stalled
// or never creates a main window handle, etc.
}
SetParent(p.MainWindowHandle, frm_3.panel_3.Handle);
如果您的流程实际上产生了多个&#34;主窗口&#34;,那么您需要篡改它(等待第二个MainWindowHandle
)
至于你的具体问题,EnumWindows
只列出了进程产生的窗口......如果你的进程有多个窗口而你想在winforms中托管所有窗口,这可能很有用,但它&# 39; d几乎是特定于流程的(您更可能还需要EnumChildWindows
或EnumThreadWindows
并枚举所有流程以使某些内容具有通用性,以及需要特定UI的特定需求如果你需要自己托管窗户。)
答案 1 :(得分:0)
在调用 WaitForInputIdle 方法后尝试添加 sleep 。
样品:
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
static readonly int GWL_STYLE = -16;
static readonly int WS_VISIBLE = 0x10000000;
private void button1_Click(object sender, EventArgs e)
{
Process p = Process.Start(@"C:\test\SampleWinForm2.exe");
p.WaitForInputIdle();
Thread.Sleep(3000); //sleep for 3 seconds
SetParent(p.MainWindowHandle, panel1.Handle);
SetWindowLong(p.MainWindowHandle, GWL_STYLE, WS_VISIBLE);
MoveWindow(p.MainWindowHandle, 0, 0, panel1.Width, panel1.Height, true);
}
答案 2 :(得分:0)
private void button1_Click(object sender, EventArgs e)
{
Process p = Process.Start("<your exe name>");
p.WaitForInputIdle();
while (p.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(100); // Don't hog the CPU
p.Refresh(); // You need this since `MainWindowHandle` is cached
}
SetParent(p.MainWindowHandle, Panel_1.Handle);
}