将两个不同进程的窗口设置为父子关系

原文: 将两个不同进程的窗口设置为父子关系

今天用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不行,既然微软自己都在用,暂且先用着,后续发现有问题再补充说明。

猜你喜欢

转载自www.cnblogs.com/lonelyxmas/p/10249362.html