隐藏父窗口,但显示子窗口
本文关键字:窗口 显示 隐藏 | 更新日期: 2023-09-27 18:12:25
我正在开发一个应用程序,该应用程序在启动时应执行以下操作:
- 使用COM(AutoCAD(连接到外部应用程序
- 向应用程序发送消息以运行某些DLL代码(打开一个窗口(
- 隐藏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=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);