zoukankan      html  css  js  c++  java
  • 让子窗口和父窗口同时处于激活状态

                                        让子窗口和父窗口同时处于激活状态
                                                 周银辉

    一般情况下,激活父窗口的时候,子窗口会失去焦点,同理,激活子窗口的时候,父窗口也会失去焦点,这在某些时候不太好看,比如子窗口作为ToolWindow漂浮在父窗口上面时。Visual Studio好像也有这个问题,当激活其中某个处于浮动状态的DockingPanel时,Visual Studio主窗口会失去焦点。
    上两幅图,更明白点,
    一般效果如下:

    我们现在追求的效果如下:

    恩,这里有个简单的包装,呵呵,复制下代码就可以直接使用了(Framework版本需要3.5):

    using System;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Interop;

    namespace YourNamespace
    {
        
    public static class WindowActiveService
        {
            
    internal class WindowActiveHelper
            {
                [DllImport(
    "user32", CharSet = CharSet.Auto)]
                
    private extern static int SendMessage(
                   IntPtr handle, 
    int msg, int wParam, IntPtr lParam);

                [DllImport(
    "user32.dll")]
                
    private static extern IntPtr GetForegroundWindow();

    // ReSharper disable InconsistentNaming
                private const int WM_NCACTIVATE = 0x086;
    // ReSharper restore InconsistentNaming
                private IntPtr ownerHwnd = IntPtr.Zero;
                
    private IntPtr childHwnd = IntPtr.Zero;
                
    private HwndSource ownerHwndSource;
                
    private HwndSource childHwndSource;
                
    private HwndSourceHook ownerHook;
                
    private HwndSourceHook childHook;
                
    private bool childActive;
                
    private bool ownerActive;

                
    private static IntPtr GetWindowHwnd(Window window)
                {
                    var helper 
    = new WindowInteropHelper(window);
                    
    return helper.Handle;
                }

                
    private IntPtr FilterChildMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
                {
                    
    if (msg == WM_NCACTIVATE)
                    {
                        
    if (((int)wParam) == 0)
                        {
                            IntPtr handle 
    = GetForegroundWindow();
                            
    if (handle == childHwnd || handle == ownerHwnd)
                            {
                                
    if (childActive == false)
                                {
                                    childActive 
    = true;
                                    SendMessage(childHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                                }
                                
    if (ownerActive == false)
                                {
                                    ownerActive 
    = true;
                                    SendMessage(ownerHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                                }
                            }
                            
    else
                            {
                                
    if (childActive)
                                {
                                    childActive 
    = false;
                                    SendMessage(childHwnd, WM_NCACTIVATE, 
    0, IntPtr.Zero);
                                }
                                
    if (ownerActive)
                                {
                                    ownerActive 
    = false;
                                    SendMessage(ownerHwnd, WM_NCACTIVATE, 
    0, IntPtr.Zero);
                                }
                            }
                        }
                        
    if (((int)wParam) == 1)
                        {
                            
    if (childActive == false)
                            {
                                childActive 
    = true;
                                SendMessage(childHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                            }
                            
    if (ownerActive == false)
                            {
                                ownerActive 
    = true;
                                SendMessage(ownerHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                            }
                        }

                    }

                    
    return IntPtr.Zero;
                }

                
    private IntPtr FilterOwnerMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
                {
                    
    if (msg == WM_NCACTIVATE)
                    {
                        
    if (((int)wParam) == 0)
                        {
                            IntPtr handle 
    = GetForegroundWindow();
                            
    try
                            {
                                
    if (handle == ownerHwnd || handle == childHwnd)
                                {
                                    
    if (ownerActive == false)
                                    {
                                        ownerActive 
    = true;
                                        SendMessage(ownerHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                                    }
                                    
    if (childActive == false)
                                    {
                                        childActive 
    = true;
                                        SendMessage(childHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                                    }
                                }
                                
    else
                                {
                                    
    if (ownerActive)
                                    {
                                        ownerActive 
    = false;
                                        SendMessage(ownerHwnd, WM_NCACTIVATE, 
    0, IntPtr.Zero);
                                    }
                                    
    if (childActive)
                                    {
                                        childActive 
    = false;
                                        SendMessage(childHwnd, WM_NCACTIVATE, 
    0, IntPtr.Zero);
                                    }
                                }
                            }
    // ReSharper disable EmptyGeneralCatchClause
                            catch (Exception)
    // ReSharper restore EmptyGeneralCatchClause
                            {
                            }
                        }
                        
    if (((int)wParam) == 1)
                        {
                            
    if (ownerActive == false)
                            {
                                ownerActive 
    = true;
                                SendMessage(ownerHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                            }
                            
    if (childActive == false)
                            {
                                childActive 
    = true;
                                SendMessage(childHwnd, WM_NCACTIVATE, 
    1, IntPtr.Zero);
                            }
                        }


                    }

                    
    return IntPtr.Zero;
                }


                
    private void RemoveChildHook()
                {
                    
    if (childHwndSource != null && childHook != null)
                    {
                        childHwndSource.RemoveHook(childHook);
                    }
                }


                
    private void RemoveOwnerHook()
                {
                    
    if (ownerHwndSource != null && ownerHook != null)
                    {
                        ownerHwndSource.RemoveHook(ownerHook);
                    }
                }

                
    public void RegisterFloatingToolWindow(Window childWindow, Window ownerWindow)
                {
                    childWindow.Owner 
    = ownerWindow;


                    childWindow.Unloaded 
    += ((sender, args) => RemoveChildHook());
                    ownerWindow.Unloaded 
    += ((sender, args) => RemoveOwnerHook());

                    childWindow.Activated 
    += ((sender, args) => childActive = true);
                    ownerWindow.Activated 
    += ((sender, args) => ownerActive = true);

                    childWindow.Deactivated 
    += ((sender, args) => childActive = false);
                    ownerWindow.Deactivated 
    += ((sender, args) => ownerActive = false);


                    childHwnd 
    = GetWindowHwnd(childWindow);
                    ownerHwnd 
    = GetWindowHwnd(ownerWindow);
                    childHwndSource 
    = HwndSource.FromHwnd(childHwnd);
                    ownerHwndSource 
    = HwndSource.FromHwnd(ownerHwnd);
                    childHook 
    = new HwndSourceHook(FilterChildMessage);
                    ownerHook 
    = new HwndSourceHook(FilterOwnerMessage);

                    
    if (childHwndSource != null)
                    {
                        childHwndSource.AddHook(childHook);
                    }

                    
    if (ownerHwndSource != null)
                    {
                        ownerHwndSource.AddHook(ownerHook);
                    }
                }
            }

            
    /// <summary>
            
    /// (notes: call this before loading)
            
    /// </summary>
            public static void RegisterAsActivePreemptionDisabledWindow(this Window window, Window owner)
            {
                var helper 
    = new WindowActiveHelper();
                window.Loaded 
    += delegate
                {
                    helper.RegisterFloatingToolWindow(window, owner);
                    owner.Activate();
                };
            }
        }
    }

    如何使用上面的代码:
    在子窗口Show之前,调用RegisterAsActivePreemptionDisabledWindow()方法。比如上图中,点击主窗口的Button,然后:

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                var child = 
    new ChildWindow {Owner = this};
                
                child.RegisterAsActivePreemptionDisabledWindow(this);

                child.Show();
            }
  • 相关阅读:
    贝尔级数
    NOIP2018 退役记
    Codeforces1106F 【BSGS】【矩阵快速幂】【exgcd】
    codeforces1111 简单题【DE】简要题解
    BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】
    BZOJ3771: Triple【生成函数】
    Codeforces 1096G. Lucky Tickets【生成函数】
    Codeforces1099F. Cookies【DP】【线段树】【贪心】【博弈】【沙比提(这是啥算法)】
    Codeforces gym101955 A【树形dp】
    BZOJ3551: [ONTAK2010]Peaks加强版【Kruskal重构树】【主席树】
  • 原文地址:https://www.cnblogs.com/zhouyinhui/p/1623936.html
Copyright © 2011-2022 走看看