winforms 是否可以在启动进程之前设置外部应用程序的父表单?

oyjwcjzk  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(113)

我有一个winforms应用程序(.net 5.0),它包含两个表单-一个供操作员使用(设置不同的选项/输入数据、管理职责),另一个供用户交互(玩游戏、遵循指令等)。每个表单都显示在单独的监视器上,在应用程序运行时都是可见的/可用的。
应用程序的一个要求是在用户表单中运行外部应用程序(游戏)。用户表单包含一个面板(作为页眉)和几个自定义用户控件。其中一个用户控件将成为外部应用程序的父控件。
使用下面的代码,我可以在用户窗体内运行外部应用程序。但是,在使用SetParent(...)将应用程序移动到用户窗体内之前,这些应用程序都是在窗体外启动的(如“闪屏”所示)。
我想实现的是在将外部应用程序移动到用户控件之前不出现“闪屏”。我理解原因/解决方案可能因应用程序而异,因此欢迎使用指导代替解决方案。
下面的大部分代码都来自SO和Google,但是我无法找到关于“闪屏”问题的参考。

public static int GWL_STYLE = -16;
public static int WS_BORDER = 0x00800000; //window with border
public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar
public const uint WS_SIZEBOX = 0x00040000;

...

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

[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);

[DllImport("user32.dll")]
static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);

public static void HideWindowBorders(IntPtr hWnd)
{
    var style = GetWindowLong(hWnd, GWL_STYLE); //gets current style
    SetWindowLong(hWnd, GWL_STYLE, (uint)(style & ~(WS_CAPTION | WS_SIZEBOX))); //removes caption and the sizebox from current style
}

...

// Button click in the operator form starts the external application
private void playSuperTuxBtn_Click(object sender, EventArgs e)
{
   Process superTux = new Process();

   superTux.StartInfo.FileName = @"C:\Program Files\SuperTux\bin\supertux2.exe"; // 0.6.3
   superTux.StartInfo.UseShellExecute = false;
   superTux.StartInfo.CreateNoWindow = false;
   superTux.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

   superTux.Start();

   superTux.WaitForInputIdle();

   while (superTux.MainWindowHandle == IntPtr.Zero)
   {
       Thread.Sleep(100);
       superTux.Refresh();
   }

   RemoveMenuBar(superTux.MainWindowHandle);
   HideWindowBorders(superTux.MainWindowHandle);
   SetParent(superTux.MainWindowHandle, RebotControlForm.uiForm.conUIGamePlay.Handle);
   MoveWindow(superTux.MainWindowHandle, 0, 0, RebotControlForm.uiForm.conUIGamePlay.Width, RebotControlForm.uiForm.conUIGamePlay.Height, true);
}
3htmauhk

3htmauhk1#

MainWindowHandle在Windows中不是一个真实的东西,它是由. NET伪造的。
要捕获所有窗口,您必须使用某种挂钩,SetWinEventHook或CBT挂钩。

相关问题