2014-07-10 179 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));' –