2014-07-10 143 views
0

我的工作应该做在启动以下应用:隐藏父窗口,但显示的子窗口

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

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

我不知道是否有可能让子窗口可见而父窗口不可见。每当我让孩子看到或使其成为最顶层窗口时,AutoCAD也会变得可见。

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

在任何情况下,我很好奇我是否有可能通过一些Windows API调用或.NET中的某些东西来实现。 PS:我不确定这个窗口关系是否真的是父母 - 孩子之间的关系。我假设它是因为我的窗口属于AutoCAD应用程序实例,由于DLL加载。

任何帮助,非常感谢。谢谢! :)

编辑: 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() 
} 
+0

你需要证明创建DLL中的窗口中的代码。 –

+0

完成,虽然窗口没有以任何奇特的方式初始化:P –

回答

1

哈哈!我找到了!

因此,我最终调用了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... 
} 

基本上我通过直接修改HWND来告诉AutoCAD窗口隐藏。我还将尺寸设置为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); 
2

不能完成。父窗口控制子窗口可见性。

您的最佳选择是使DLL窗口成为顶层窗口(但归AutoCAD窗口所有)。

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

+0

感谢您的快速回复。显然,我的窗户已经是顶层,而不是小孩。根据这里的链接: http://forums.codeguru.com/showthread.php?491610-Windows-SDK-What-is-a-top-level-window http://forums.codeguru.com/showthread .php?491604-Windows-SDK-What-is-a-child-window 孩子们被绑定到父母的客户区,但是顶级窗口不是。 –

+0

@Eric当你展示一个拥有的窗口时,它也是拥有者。我认为。 –

2

你想要什么可以尽管其他人可能会想到。你只需要以不同的方式思考问题。不要考虑父母和孩子Window s ...相反,想想一个启动画面Window

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

要了解如何在WPF中执行此操作,请参阅How to open a child Window like a splash screen before MainWindow in WPF?问题的答案,这里是堆栈溢出。稍微扩展这个答案,我应该指出,你不需要使用Timer。代替链接页面的代码,你可以这样做:

private void OpenMainWindow() 
{ 
    autoCadWindow.Visiblity = Visibility.Collapsed; 
    MainWindow mainWindow = new MainWindow(); 
    mainWindow.Show(); 
} 
+0

我正在处理的AutoCAD窗口类型是'System.Windows.Forms.IWin32Window'。你是否可以折叠这种类型的窗口而不是WPF窗口? –

+0

查看MSDN上的[如何:启动Windows窗体不可见](http://msdn.microsoft.com/en-us/library/754w18dd(v = vs.110).aspx)页面。另外,如果你只是初始化'AutoCAD窗口',但不显示它呢? – Sheridan

+0

不幸的是,我不相信在使用AutoCAD时我有这种控制。为了实例化,我需要使用COM interop,它可以在单独的进程中启动AutoCAD应用程序。这意味着我无法控制最初显示窗口的方式。在创建过程并通过获取COM对象(AcadApplication)建立与它的连接后,我可以修改该应用程序。 'AcadApplication app =(AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(“AutoCAD.Application.18”,true));' –