1. 程式人生 > >將兩個不同程序的視窗設定為父子關係

將兩個不同程序的視窗設定為父子關係

原文: 將兩個不同程序的視窗設定為父子關係

今天用WPF程式給一個第三方程式做外掛,該程式支援通過選單擴充套件的方式整合第三方程式,看起來像是彈出一個對話方塊。

但是,由於新寫的WPF程式和原程式是沒有任何關係的,一旦原程式重新獲取焦點時,新彈出的WPF程式視窗就會切換到後臺,看起來就不像子視窗了。看了一下之前的人們的做法,大多是將新蹦出來的視窗設定為TopMost,但這樣就又引入了改視窗不能切換到後臺隱藏的問題。

在網上搜了一下,找到了如下解決方法:http://stackoverflow.com/questions/2599053/how-to-set-win32-window-as-owner-of-wpf-window

。具體就是通過WindowInteropHelper將外部視窗設定為Owner。

    var helper = new WindowInteropHelper(myWpfChildWindow);
    helper->Owner = mainWindowHWND;

這樣做確實解決問題了,但反過來一想,如果要讓外部視窗作為WPF的子視窗,就無法用這個方法了。由於WPF程式本身就是呼叫的WindowsAPI,肯定WindowsAPI是支援兩個不相干的視窗的父子關係設定的,便在referencesource

上看了一下其原始碼,用的是如下程式碼:

UnsafeNativeMethods.SetWindowLong(new HandleRef(null, CriticalHandle),
                NativeMethods.GWL_HWNDPARENT,    
                _ownerHandle

);

也就是說,它呼叫的是API SetWindowLong

    LONG WINAPI SetWindowLong(
     _In_ HWND hWnd,
     _In_ int nIndex,
     _In_ LONG dwNewLong
    );

它有三個引數,第一個引數傳入子視窗Handle, 第二個引數傳入GWL_HWNDPARENT,第三個傳入父視窗Handle。不過,MSDN上同時寫著不建議使用這種方式設定父子關係,而需要用SetParent。我試了一下,用這種方式可以,反而用SetParent不行,既然微軟自己都在用,暫且先用著,後續發現有問題再補充說明。