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

本文关键字:窗口 显示 隐藏 | 更新日期: 2023-09-27 18:12:25

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

  1. 使用COM(AutoCAD(连接到外部应用程序
  2. 向应用程序发送消息以运行某些DLL代码(打开一个窗口(
  3. 隐藏AutoCAD的窗口,但保持DLL的窗口可见

我已经成功地完成了前两个步骤,但第三个步骤给我带来了一些问题。

我不知道是否可以在子窗口的父窗口不可见的情况下使其可见。每当我使子窗口可见或使其成为最顶部的窗口时,AutoCAD也会变为可见。

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

在任何情况下,我都很好奇我试图做的事情是否可能,也许是通过一些Windows API调用或中的某些内容。NET。

附言:我不确定这种窗口关系是否真的是亲子关系。不过,我认为是因为加载了DLL,所以我的窗口属于AutoCAD应用程序实例。

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

编辑: 用于创建窗口的DLL代码

//CommandMethod is an AutoCAD attribute for entering into the DLL.  This code is called
//when the user attempts the command "AUTOCADCOMMANDNAME" or can be done by simulating
//the command programmatically.
[CommandMethod("AUTOCADCOMMANDNAME", CommandFlags.Session)]
public void CommandEntry()
{
    MainWindow mainWin = new MainWindow();
    mainWin.ShowDialog();
}

主要应用程序代码

public static void Main()
{   //Use a utility class to create a connection to AutoCAD via COM
    AcadApplication acadApp = ACUtil.GetAcadInstance(out createdNewInstance);
    acadApp.Visible = false;
    //Irrelevant code omitted...
    acadApp.ActiveDocument.SendCommand("AUTOCADCOMMANDNAME");
    acadApp.Quit(); //Exit AutoCAD application
    //Note: doesn't quit until mainWin closes because of ShowDialog()
}

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

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

最好的选择是使DLL窗口成为顶级窗口(但归AutoCAD窗口所有(。

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

不管别人怎么想,你想要的都可以实现。你只需要用不同的方式来思考这个问题。不要考虑父代和子代Window…而是考虑启动屏幕Window

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

要了解如何在WPF中做到这一点,请参阅我在WPF的MainWindow之前如何像启动屏幕一样打开子窗口?问题,请参阅Stack Overflow。稍微扩展一下这个答案,我应该指出,您不需要使用Timer。你可以这样做:

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=0height=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);