C# 隐藏父窗口,但显示子窗口

C# 隐藏父窗口,但显示子窗口,c#,wpf,winapi,dll,autocad-plugin,C#,Wpf,Winapi,Dll,Autocad Plugin,我正在开发一个应用程序,该应用程序在启动时应执行以下操作: 使用COM(AutoCAD)连接到外部应用程序 向应用程序发送消息以运行某些DLL代码(打开一个窗口) 隐藏AutoCAD的窗口,但保持DLL的窗口可见 我已经成功地完成了前两个步骤,但第三个步骤给了我一些问题 我不知道当父窗口不可见时,是否可以使子窗口可见。每次我使子窗口可见或使其成为最顶部的窗口时,AutoCAD也将可见 我的目标是运行DLL代码,但让AutoCAD在后台运行,对我的用户完全不可见。DLL必须通过AutoCAD加载,

我正在开发一个应用程序,该应用程序在启动时应执行以下操作:

  • 使用COM(AutoCAD)连接到外部应用程序
  • 向应用程序发送消息以运行某些DLL代码(打开一个窗口)
  • 隐藏AutoCAD的窗口,但保持DLL的窗口可见
  • 我已经成功地完成了前两个步骤,但第三个步骤给了我一些问题

    我不知道当父窗口不可见时,是否可以使子窗口可见。每次我使子窗口可见或使其成为最顶部的窗口时,AutoCAD也将可见

    我的目标是运行DLL代码,但让AutoCAD在后台运行,对我的用户完全不可见。DLL必须通过AutoCAD加载,因为它允许我使用AutoCAD的.NET接口而不是COM

    在任何情况下,我都很好奇我试图做的事情是否可行,也许是通过一些Windows API调用,或者是.NET中的某些东西

    PS:我不确定这个窗口关系是否真的是父子关系。我假设这是因为我的窗口由于DLL加载而属于AutoCAD应用程序实例

    非常感谢您的帮助。谢谢!:)

    编辑: 创建窗口的DLL代码

    主要应用程序代码


    不行。父窗口控制子窗口的可见性

    最好的替代方法是使DLL窗口成为顶级窗口(但归AutoCAD窗口所有)


    请注意,DLL窗口仍将是AutoCAD线程的一部分。

    无法完成。父窗口控制子窗口的可见性

    最好的替代方法是使DLL窗口成为顶级窗口(但归AutoCAD窗口所有)

    请注意,DLL窗口仍将是AutoCAD线程的一部分。

    不管其他人怎么想,您想要的都可以实现。你只需要用另一种方式思考这个问题。不要考虑父项和子项
    Window
    s。。。相反,考虑一个启动屏幕
    窗口

    通常,启动屏幕出现在主应用程序
    窗口
    之前,但这是否使它们成为父窗口?不,没有。通常,它们会在主
    窗口
    打开后关闭,但是没有理由不能隐藏它而不是关闭它

    要了解如何在WPF中实现这一点,请参考我的问题答案,这里是关于堆栈溢出的。稍微扩展一下这个答案,我应该指出,您不需要使用
    计时器。您可以执行以下操作,而不是链接页面中的代码:

    private void OpenMainWindow()
    {
        autoCadWindow.Visiblity = Visibility.Collapsed;
        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
    }
    
    不管别人怎么想,你想要的是可以实现的。你只需要用另一种方式思考这个问题。不要考虑父项和子项
    Window
    s。。。相反,考虑一个启动屏幕
    窗口

    通常,启动屏幕出现在主应用程序
    窗口
    之前,但这是否使它们成为父窗口?不,没有。通常,它们会在主
    窗口
    打开后关闭,但是没有理由不能隐藏它而不是关闭它

    要了解如何在WPF中实现这一点,请参考我的问题答案,这里是关于堆栈溢出的。稍微扩展一下这个答案,我应该指出,您不需要使用
    计时器。您可以执行以下操作,而不是链接页面中的代码:

    private void OpenMainWindow()
    {
        autoCadWindow.Visiblity = Visibility.Collapsed;
        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
    }
    
    哈哈!我找到了

    因此,我最终在Windows API中调用了
    SetWindowPos
    函数,并为AutoCAD窗口提供了句柄。我在我的主应用程序中这样做:

    [DllImport("User32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int w, int h, uint flags);
    public const int SWP_HIDEWINDOW = 0x0080;
    
    public static void Main()
    {
        //...Setup AutoCAD...
    
        //Change window size and hide it before calling to open mainWin inside the DLL.
        SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
        //Display mainWin by entering the DLL.
        acadApp.ActiveDocument.SendCommand("AUTOCADCOMMANDNAME");
    
        //Terminate application as before...
    }
    
    基本上,我告诉AutoCAD窗口通过直接修改HWND来隐藏。我还将尺寸设置为
    width=0
    height=0
    ,这会使窗口占据尽可能小的尺寸。不幸的是,窗口将闪烁一次,但就我而言,这是可以忽略不计的如果有人能找到消除闪烁的方法,那就太好了:)


    编辑:当使用
    SetWindowPos
    时,Windows会记住下次显示应用程序窗口时输入的值。这意味着,如果未正确恢复,则用户下次手动打开AutoCAD时,其坐标将为0,0和最小宽度/高度

    要更改该行为,必须获取窗口信息。对于我的程序,我使用
    GetWindowRect
    获取原始设置。在关闭程序之前,我使用
    SetWindowPos
    恢复了这些设置。有关详细信息,请参见下面的代码:

    首先,导入必要的WINAPI函数和结构:

    [DllImport("User32.dll")]
        static extern bool GetWindowRect(IntPtr hwnd, out RECT rect);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    
    RECT originalRect;
    GetWindowRect(new IntPtr(acadApp.HWND), out originalRect);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 
        originalRect.Left, 
        originalRect.Top, 
        originalRect.Right - originalRect.Left,
        originalRect.Bottom - originalRect.Top, 0);
    
    在修改窗口之前获取原始设置:

    [DllImport("User32.dll")]
        static extern bool GetWindowRect(IntPtr hwnd, out RECT rect);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    
    RECT originalRect;
    GetWindowRect(new IntPtr(acadApp.HWND), out originalRect);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 
        originalRect.Left, 
        originalRect.Top, 
        originalRect.Right - originalRect.Left,
        originalRect.Bottom - originalRect.Top, 0);
    
    修改窗口以隐藏(并调整大小):

    [DllImport("User32.dll")]
        static extern bool GetWindowRect(IntPtr hwnd, out RECT rect);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    
    RECT originalRect;
    GetWindowRect(new IntPtr(acadApp.HWND), out originalRect);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 
        originalRect.Left, 
        originalRect.Top, 
        originalRect.Right - originalRect.Left,
        originalRect.Bottom - originalRect.Top, 0);
    
    退出前恢复原始设置:

    [DllImport("User32.dll")]
        static extern bool GetWindowRect(IntPtr hwnd, out RECT rect);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    
    RECT originalRect;
    GetWindowRect(new IntPtr(acadApp.HWND), out originalRect);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
    SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 
        originalRect.Left, 
        originalRect.Top, 
        originalRect.Right - originalRect.Left,
        originalRect.Bottom - originalRect.Top, 0);
    
    哈哈!我找到了

    因此,我最终在Windows API中调用了
    SetWindowPos
    函数,并为AutoCAD窗口提供了句柄。我在我的主应用程序中这样做:

    [DllImport("User32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int w, int h, uint flags);
    public const int SWP_HIDEWINDOW = 0x0080;
    
    public static void Main()
    {
        //...Setup AutoCAD...
    
        //Change window size and hide it before calling to open mainWin inside the DLL.
        SetWindowPos(new IntPtr(acadApp.HWND), new IntPtr(1), 0, 0, 0, 0, SWP_HIDEWINDOW);
    
        //Display mainWin by entering the DLL.
        acadApp.ActiveDocument.SendCommand("AUTOCADCOMMANDNAME");
    
        //Terminate application as before...
    }
    
    基本上,我告诉AutoCAD窗口通过直接修改HWND来隐藏。我还将尺寸设置为
    width=0
    height=0
    ,这会使窗口占据尽可能小的尺寸。不幸的是,窗口将闪烁一次,但就我而言,这是可以忽略不计的如果有人能找到消除闪烁的方法,那就太好了:)


    编辑:当使用
    SetWindowPos
    时,Windows会记住下次显示应用程序窗口时输入的值。这意味着,如果未正确恢复,则用户下次手动打开AutoCAD时,其坐标将为0,0和最小宽度/高度

    要改变这种行为,必须获得