如何在我的C#程序面板中运行另一个应用程序?

Ale*_*lex 68 .net c# windows exe winforms

我一直在阅读很多关于如何从C#程序(Process.Start())中触发应用程序的内容,但是我还没有找到有关如何在我的C#程序面板中运行这个新应用程序的任何信息.例如,我想点击一下按钮,在我的应用程序中打开notepad.exe,而不是外部打开.

Luk*_*ane 101

使用win32 API可以"吃掉"另一个应用程序.基本上,您可以获得该应用程序的顶部窗口,并将其父级设置为要放置的面板的句柄.如果您不想要MDI样式效果,则还必须调整窗口样式以使其最大化并且删除标题栏.

这是一些简单的示例代码,其中我有一个带有按钮和面板的表单:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process p = Process.Start("notepad.exe");
            Thread.Sleep(500); // Allow the process to open it's window
            SetParent(p.MainWindowHandle, panel1.Handle);
        }

        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    }
}
Run Code Online (Sandbox Code Playgroud)

我刚看到另一个例子,他们调用WaitForInputIdle而不是sleep.所以代码是这样的:

Process p = Process.Start("notepad.exe");
p.WaitForInputIdle();
SetParent(p.MainWindowHandle, panel1.Handle);
Run Code Online (Sandbox Code Playgroud)

代码项目在整个过程中有一篇很好的文章:在WinForm项目中托管EXE应用程序

  • 超级有用!该链接没有显示其函数的dll导入,所以我认为id在这里共享它们[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); (15认同)
  • 是的,有经验的 Windows 程序员使用 WaitForInputIdle。Windows 程序员应始终查看使用 Sleep 的代码两次或更多次。 (2认同)

And*_*ite 15

我不知道这是否仍然是推荐使用的东西,但"对象链接和嵌入"框架允许您将某些对象/控件直接嵌入到您的应用程序中.这可能只适用于某些应用程序,我不确定Notepad是否是其中之一.对于像记事本这样非常简单的事情,你可能会更容易使用你正在使用的任何媒体提供的文本框控件(例如WinForms).

这是一个启动OLE信息的链接:

http://en.wikipedia.org/wiki/Object_Linking_and_Embedding


Sau*_*oot 6

  • 在答案中添加一些解决方案..**

这段代码帮助我以 Windows 形式停靠了一些可执行文件。像记事本、Excel、word、Acrobat 阅读器等等……

但它不适用于某些应用程序。有时当您启动某个应用程序的进程时....等待空闲时间...并尝试获取其 mainWindowHandle.... 直到主窗口句柄变为空.....

所以我做了一个技巧来解决这个问题

如果您将主窗口句柄设为空...然后在系统上搜索所有正在运行的进程并找到您的进程...然后获取进程的主窗口并将设置面板作为其父进程。

        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "xxxxxxxxxxxx.exe";
        info.Arguments = "yyyyyyyyyy";
        info.UseShellExecute = true;
        info.CreateNoWindow = true;
        info.WindowStyle = ProcessWindowStyle.Maximized;
        info.RedirectStandardInput = false;
        info.RedirectStandardOutput = false;
        info.RedirectStandardError = false;

        System.Diagnostics.Process p = System.Diagnostics.Process.Start(info); 

        p.WaitForInputIdle();
        Thread.Sleep(3000);

        Process[] p1 ;
    if(p.MainWindowHandle == null)
    {
        List<String> arrString = new List<String>();
        foreach (Process p1 in Process.GetProcesses())
        {
            // Console.WriteLine(p1.MainWindowHandle);
            arrString.Add(Convert.ToString(p1.ProcessName));
        }
        p1 = Process.GetProcessesByName("xxxxxxxxxxxx");
        //p.WaitForInputIdle();
        Thread.Sleep(5000);
      SetParent(p1[0].MainWindowHandle, this.panel2.Handle);

    }
    else
    {
     SetParent(p.MainWindowHandle, this.panel2.Handle);
     }
Run Code Online (Sandbox Code Playgroud)


dan*_*004 5

以下是另一个使用WinForm容器吸引外部应用程序的有趣解决方案:

[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);


private void Form1_Load(object sender, EventArgs e)
{
    ProcessStartInfo psi = new ProcessStartInfo("notepad.exe");
    psi.WindowStyle = ProcessWindowStyle.Minimized;
    Process p = Process.Start(psi);
    Thread.Sleep(500);
    SetParent(p.MainWindowHandle, panel1.Handle);
    CenterToScreen();
    psi.WindowStyle = ProcessWindowStyle.Normal;
}
Run Code Online (Sandbox Code Playgroud)

ProcessWindowStyle.Minimized从ProcessWindowStyle.Normal 到的步骤 消除了烦人的延迟。

在此处输入图片说明