將兩個不同程序的視窗設定為父子關係
今天用WPF程式給一個第三方程式做外掛,該程式支援通過選單擴充套件的方式整合第三方程式,看起來像是彈出一個對話方塊。
但是,由於新寫的WPF程式和原程式是沒有任何關係的,一旦原程式重新獲取焦點時,新彈出的WPF程式視窗就會切換到後臺,看起來就不像子視窗了。看了一下之前的人們的做法,大多是將新蹦出來的視窗設定為TopMost,但這樣就又引入了改視窗不能切換到後臺隱藏的問題。
在網上搜了一下,找到了如下解決方法:http://stackoverflow.com/questions/2599053/how-to-set-win32-window-as-owner-of-wpf-window
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不行,既然微軟自己都在用,暫且先用著,後續發現有問題再補充說明。