Winform 在 PictureBox 中显示另一个应用程序

Winform showing another application inside a PictureBox

首先,我想声明我知道我的问题类似于 Running another application inside a picturebox,但是我的应用程序 运行s .exe 很好,它不会总是将它嵌套在图片框.

在我的 c# winforms 应用程序中,我试图 运行 PictureBox 中的 calc.exe,但是大约 75% 的时间我的应用程序只是 运行s calc.exe 作为它自己的 window.

我的代码如下。

enter code hereprivate void Preview_Button_Click(object sender, EventArgs e)
    {
        if (ActiveWindows_ListBox.SelectedItem == null)
        {
            MessageBox.Show("There is no Window selected to take a picture of.", "Insufficient Data");
            return;
        }
        Process p = Process.Start("calc.exe");
        Thread.Sleep(500);
        p.WaitForInputIdle();
        SetParent(p.MainWindowHandle, ViewingScreen_PictureBox.Handle);
    }

根据我对我正在尝试做的事情的理解,我正在启动 windows 原生的 calc.exe 应用程序,然后告诉我的应用程序等待计算器自我初始化然后告诉计算器,图片框是计算器的父级。

这就留下了我的问题,是不是我遗漏了一些东西,以至于我的应用程序不会在 100% 的时间内将计算器设置在图片框内?

提前感谢您的帮助。

P.S。我已尝试调整 Thread.Sleep 以在不改变行为的情况下为我的应用程序提供比现在更多或更少的时间。

    public Process p = new Process();

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

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

    private void Preview_Button_Click(object sender, EventArgs e)
    {
        p = Process.Start("calc.exe");
        Thread.Sleep(500);
        p.WaitForInputIdle();
        SetParent(p.MainWindowHandle, ViewingScreen_PictureBox.Handle);
        MoveWindow(p.MainWindowHandle, 0, 0, 230, 320, true);
    }

您的代码中有几个注意事项:

  1. 您对 WaitForInputIdle 的调用应检查 return 值。仅当调用 return 为真(参见 MSDN)时才达到空闲状态。

  2. 即使达到空闲状态,p.MainWindowHandle也可能return为零。忙等待循环可以等待句柄变为非零。不好,但足以说明原理。诊断计数器 ctr 显示访问循环的频率。

  3. 以下代码应该将计算器可靠地绑定到图片框,另外,picBox 的大小会调整为计算器的大小,这样无论 picBox 的初始大小如何,整个计算器始终可见。

    [DllImport("user32.dll")]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPthWndNewParent);
    [DllImport("user32.dll")]
    private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
    

static int ctr = 0;

private void button2_Click(object sender, EventArgs e)
{
    Process p = Process.Start("calc.exe");
    IntPtr h = IntPtr.Zero;

    //Wait for calc.exe to establish
    while ((h = p.MainWindowHandle) == IntPtr.Zero)
        ctr++;

    //Get size of calculator
    RECT r;
    GetWindowRect(h, out r);

    //width and height of the calculator
    int calcWidth = r.Right - r.Left;
    int calcHeight = r.Bottom - r.Top;

    //bind calculator to pictureBox
    SetParent(h, pictureBox1.Handle);

    //move calcusator to upper left corner of picturebox
    MoveWindow(h, 0, 0, calcWidth, calcHeight, true);

    //resize pictureBox to Calculator size
    Size newPicBoxSize = new Size(calcWidth, calcHeight);
    pictureBox1.Size = newPicBoxSize;
}