You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断进程主窗口加载完成,将Stellarium正确嵌入WinForm的Panel控件

根因分析

Stellarium启动时会先加载启动屏窗口,此时你读取到的Process.MainWindowHandle实际是启动屏的句柄,将启动屏嵌入Panel后,启动屏销毁时不会自动把后续生成的主窗口挂载到Panel下,就会出现主窗口在Panel外打开的问题。固定时长等待的方案兼容性极差,不同性能设备的启动速度差异很大,无法适配所有场景。

解决方案

核心思路是异步循环检测进程的主窗口句柄,匹配到主窗口后再执行嵌入操作,不会阻塞UI线程,也不需要固定等待时长。

第一步:声明所需Windows API

using System.Text;
using System.Runtime.InteropServices;

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

[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", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll")]
private static extern bool IsWindow(IntPtr hWnd);

第二步:修改按钮点击逻辑

private async void Notepad_Button_Click(object sender, EventArgs e)
{
    var psi = new ProcessStartInfo(@"C:\Program Files\Stellarium\stellarium.exe") 
    { 
        WindowStyle = ProcessWindowStyle.Minimized 
    };

    using (var p = Process.Start(psi))
    {
        IntPtr stellariumMainHandle = IntPtr.Zero;
        // 最多等待30秒,避免进程异常时无限循环
        for (int retryCount = 0; retryCount < 300; retryCount++)
        {
            // 刷新进程缓存属性,否则MainWindowHandle不会更新
            p.Refresh();
            IntPtr currentHandle = p.MainWindowHandle;
            
            if (currentHandle != IntPtr.Zero && IsWindow(currentHandle))
            {
                StringBuilder windowTitle = new StringBuilder(256);
                GetWindowText(currentHandle, windowTitle, 256);
                // 匹配Stellarium主窗口标题,可根据实际版本调整匹配规则
                if (windowTitle.ToString().Contains("Stellarium"))
                {
                    stellariumMainHandle = currentHandle;
                    break;
                }
            }
            // 每100ms检测一次,不阻塞UI线程
            await Task.Delay(100);
        }

        if (stellariumMainHandle != IntPtr.Zero)
        {
            SetParent(stellariumMainHandle, panel1.Handle);
            MoveWindow(stellariumMainHandle, 0, 0, panel1.Width, panel1.Height, true);
        }
        else
        {
            MessageBox.Show("Stellarium主窗口加载超时,请检查程序是否正常启动");
        }
    }
}

额外优化建议

如果后续Stellarium版本更新修改了主窗口标题,你可以替换为GetClassNameAPI检测窗口类名做匹配,判断准确率更高。

内容的提问来源于stack exchange,提问作者Selim Boz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 03:36:00