DockPanel.FocusManager.cs
上传用户:szlfmled
上传日期:2020-11-22
资源大小:978k
文件大小:20k
源码类别:

C#编程

开发平台:

C#

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.ComponentModel;
  5. using System.Runtime.InteropServices;
  6. using System.Windows.Forms;
  7. using System.Diagnostics.CodeAnalysis;
  8. namespace WeifenLuo.WinFormsUI.Docking
  9. {
  10.     internal interface IContentFocusManager
  11.     {
  12.         void Activate(IDockContent content);
  13.         void GiveUpFocus(IDockContent content);
  14.         void AddToList(IDockContent content);
  15.         void RemoveFromList(IDockContent content);
  16.     }
  17.     partial class DockPanel
  18.     {
  19.         private interface IFocusManager
  20.         {
  21.             void SuspendFocusTracking();
  22.             void ResumeFocusTracking();
  23.             bool IsFocusTrackingSuspended { get; }
  24.             IDockContent ActiveContent { get; }
  25.             DockPane ActivePane { get; }
  26.             IDockContent ActiveDocument { get; }
  27.             DockPane ActiveDocumentPane { get; }
  28.         }
  29.         private class FocusManagerImpl : Component, IContentFocusManager, IFocusManager
  30.         {
  31.             private class HookEventArgs : EventArgs
  32.             {
  33.                 [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  34.                 public int HookCode;
  35.                 [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  36.                 public IntPtr wParam;
  37.                 public IntPtr lParam;
  38.             }
  39.             private class LocalWindowsHook : IDisposable
  40.             {
  41.                 // Internal properties
  42.                 private IntPtr m_hHook = IntPtr.Zero;
  43.                 private NativeMethods.HookProc m_filterFunc = null;
  44.                 private Win32.HookType m_hookType;
  45.                 // Event delegate
  46.                 public delegate void HookEventHandler(object sender, HookEventArgs e);
  47.                 // Event: HookInvoked 
  48.                 public event HookEventHandler HookInvoked;
  49.                 protected void OnHookInvoked(HookEventArgs e)
  50.                 {
  51.                     if (HookInvoked != null)
  52.                         HookInvoked(this, e);
  53.                 }
  54.                 public LocalWindowsHook(Win32.HookType hook)
  55.                 {
  56.                     m_hookType = hook;
  57.                     m_filterFunc = new NativeMethods.HookProc(this.CoreHookProc);
  58.                 }
  59.                 // Default filter function
  60.                 public IntPtr CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
  61.                 {
  62.                     if (code < 0)
  63.                         return NativeMethods.CallNextHookEx(m_hHook, code, wParam, lParam);
  64.                     // Let clients determine what to do
  65.                     HookEventArgs e = new HookEventArgs();
  66.                     e.HookCode = code;
  67.                     e.wParam = wParam;
  68.                     e.lParam = lParam;
  69.                     OnHookInvoked(e);
  70.                     // Yield to the next hook in the chain
  71.                     return NativeMethods.CallNextHookEx(m_hHook, code, wParam, lParam);
  72.                 }
  73.                 // Install the hook
  74.                 public void Install()
  75.                 {
  76.                     if (m_hHook != IntPtr.Zero)
  77.                         Uninstall();
  78.                     int threadId = NativeMethods.GetCurrentThreadId();
  79.                     m_hHook = NativeMethods.SetWindowsHookEx(m_hookType, m_filterFunc, IntPtr.Zero, threadId);
  80.                 }
  81.                 // Uninstall the hook
  82.                 public void Uninstall()
  83.                 {
  84.                     if (m_hHook != IntPtr.Zero)
  85.                     {
  86.                         NativeMethods.UnhookWindowsHookEx(m_hHook);
  87.                         m_hHook = IntPtr.Zero;
  88.                     }
  89.                 }
  90.                 ~LocalWindowsHook()
  91.                 {
  92.                     Dispose(false);
  93.                 }
  94.                 public void Dispose()
  95.                 {
  96.                     Dispose(true);
  97.                     GC.SuppressFinalize(this);
  98.                 }
  99.                 protected virtual void Dispose(bool disposing)
  100.                 {
  101.                     Uninstall();
  102.                 }
  103.             }
  104.             private LocalWindowsHook m_localWindowsHook;
  105.             private LocalWindowsHook.HookEventHandler m_hookEventHandler;
  106.             public FocusManagerImpl(DockPanel dockPanel)
  107.             {
  108.                 m_dockPanel = dockPanel;
  109.                 m_localWindowsHook = new LocalWindowsHook(Win32.HookType.WH_CALLWNDPROCRET);
  110.                 m_hookEventHandler = new LocalWindowsHook.HookEventHandler(HookEventHandler);
  111.                 m_localWindowsHook.HookInvoked += m_hookEventHandler;
  112.                 m_localWindowsHook.Install();
  113.             }
  114.             private DockPanel m_dockPanel;
  115.             public DockPanel DockPanel
  116.             {
  117.                 get { return m_dockPanel; }
  118.             }
  119.             private bool m_disposed = false;
  120.             protected override void Dispose(bool disposing)
  121.             {
  122.                 lock (this)
  123.                 {
  124.                     if (!m_disposed && disposing)
  125.                     {
  126.                         m_localWindowsHook.Dispose();
  127.                         m_disposed = true;
  128.                     }
  129.                     base.Dispose(disposing);
  130.                 }
  131.             }
  132.             private IDockContent m_contentActivating = null;
  133.             private IDockContent ContentActivating
  134.             {
  135.                 get { return m_contentActivating; }
  136.                 set { m_contentActivating = value; }
  137.             }
  138.             public void Activate(IDockContent content)
  139.             {
  140.                 if (IsFocusTrackingSuspended)
  141.                 {
  142.                     ContentActivating = content;
  143.                     return;
  144.                 }
  145.                 if (content == null)
  146.                     return;
  147.                 DockContentHandler handler = content.DockHandler;
  148.                 if (handler.Form.IsDisposed)
  149.                     return; // Should not reach here, but better than throwing an exception
  150.                 if (ContentContains(content, handler.ActiveWindowHandle))
  151.                     NativeMethods.SetFocus(handler.ActiveWindowHandle);
  152.                 if (!handler.Form.ContainsFocus)
  153.                 {
  154.                     if (!handler.Form.SelectNextControl(handler.Form.ActiveControl, true, true, true, true))
  155.                         // Since DockContent Form is not selectalbe, use Win32 SetFocus instead
  156.                         NativeMethods.SetFocus(handler.Form.Handle);
  157.                 }
  158.             }
  159.             private List<IDockContent> m_listContent = new List<IDockContent>();
  160.             private List<IDockContent> ListContent
  161.             {
  162.                 get { return m_listContent; }
  163.             }
  164.             public void AddToList(IDockContent content)
  165.             {
  166.                 if (ListContent.Contains(content) || IsInActiveList(content))
  167.                     return;
  168.                 ListContent.Add(content);
  169.             }
  170.             public void RemoveFromList(IDockContent content)
  171.             {
  172.                 if (IsInActiveList(content))
  173.                     RemoveFromActiveList(content);
  174.                 if (ListContent.Contains(content))
  175.                     ListContent.Remove(content);
  176.             }
  177.             private IDockContent m_lastActiveContent = null;
  178.             private IDockContent LastActiveContent
  179.             {
  180.                 get { return m_lastActiveContent; }
  181.                 set { m_lastActiveContent = value; }
  182.             }
  183.             private bool IsInActiveList(IDockContent content)
  184.             {
  185.                 return !(content.DockHandler.NextActive == null && LastActiveContent != content);
  186.             }
  187.             private void AddLastToActiveList(IDockContent content)
  188.             {
  189.                 IDockContent last = LastActiveContent;
  190.                 if (last == content)
  191.                     return;
  192.                 DockContentHandler handler = content.DockHandler;
  193.                 if (IsInActiveList(content))
  194.                     RemoveFromActiveList(content);
  195.                 handler.PreviousActive = last;
  196.                 handler.NextActive = null;
  197.                 LastActiveContent = content;
  198.                 if (last != null)
  199.                     last.DockHandler.NextActive = LastActiveContent;
  200.             }
  201.             private void RemoveFromActiveList(IDockContent content)
  202.             {
  203.                 if (LastActiveContent == content)
  204.                     LastActiveContent = content.DockHandler.PreviousActive;
  205.                 IDockContent prev = content.DockHandler.PreviousActive;
  206.                 IDockContent next = content.DockHandler.NextActive;
  207.                 if (prev != null)
  208.                     prev.DockHandler.NextActive = next;
  209.                 if (next != null)
  210.                     next.DockHandler.PreviousActive = prev;
  211.                 content.DockHandler.PreviousActive = null;
  212.                 content.DockHandler.NextActive = null;
  213.             }
  214.             public void GiveUpFocus(IDockContent content)
  215.             {
  216.                 DockContentHandler handler = content.DockHandler;
  217.                 if (!handler.Form.ContainsFocus)
  218.                     return;
  219.                 if (IsFocusTrackingSuspended)
  220.                     DockPanel.DummyControl.Focus();
  221.                 if (LastActiveContent == content)
  222.                 {
  223.                     IDockContent prev = handler.PreviousActive;
  224.                     if (prev != null)
  225.                         Activate(prev);
  226.                     else if (ListContent.Count > 0)
  227.                         Activate(ListContent[ListContent.Count - 1]);
  228.                 }
  229.                 else if (LastActiveContent != null)
  230.                     Activate(LastActiveContent);
  231.                 else if (ListContent.Count > 0)
  232.                     Activate(ListContent[ListContent.Count - 1]);
  233.             }
  234.             private static bool ContentContains(IDockContent content, IntPtr hWnd)
  235.             {
  236.                 Control control = Control.FromChildHandle(hWnd);
  237.                 for (Control parent = control; parent != null; parent = parent.Parent)
  238.                     if (parent == content.DockHandler.Form)
  239.                         return true;
  240.                 return false;
  241.             }
  242.             private int m_countSuspendFocusTracking = 0;
  243.             public void SuspendFocusTracking()
  244.             {
  245.                 m_countSuspendFocusTracking++;
  246.                 m_localWindowsHook.HookInvoked -= m_hookEventHandler;
  247.             }
  248.             public void ResumeFocusTracking()
  249.             {
  250.                 if (m_countSuspendFocusTracking > 0)
  251.                     m_countSuspendFocusTracking--;
  252.                 if (m_countSuspendFocusTracking == 0)
  253.                 {
  254.                     if (ContentActivating != null)
  255.                     {
  256.                         Activate(ContentActivating);
  257.                         ContentActivating = null;
  258.                     }
  259.                     m_localWindowsHook.HookInvoked += m_hookEventHandler;
  260.                     if (!InRefreshActiveWindow)
  261.                         RefreshActiveWindow();
  262.                 }
  263.             }
  264.             public bool IsFocusTrackingSuspended
  265.             {
  266.                 get { return m_countSuspendFocusTracking != 0; }
  267.             }
  268.             // Windows hook event handler
  269.             private void HookEventHandler(object sender, HookEventArgs e)
  270.             {
  271.                 Win32.Msgs msg = (Win32.Msgs)Marshal.ReadInt32(e.lParam, IntPtr.Size * 3);
  272.                 if (msg == Win32.Msgs.WM_KILLFOCUS)
  273.                 {
  274.                     IntPtr wParam = Marshal.ReadIntPtr(e.lParam, IntPtr.Size * 2);
  275.                     DockPane pane = GetPaneFromHandle(wParam);
  276.                     if (pane == null)
  277.                         RefreshActiveWindow();
  278.                 }
  279.                 else if (msg == Win32.Msgs.WM_SETFOCUS)
  280.                     RefreshActiveWindow();
  281.             }
  282.             private DockPane GetPaneFromHandle(IntPtr hWnd)
  283.             {
  284.                 Control control = Control.FromChildHandle(hWnd);
  285.                 IDockContent content = null;
  286.                 DockPane pane = null;
  287.                 for (; control != null; control = control.Parent)
  288.                 {
  289.                     content = control as IDockContent;
  290.                     if (content != null)
  291.                         content.DockHandler.ActiveWindowHandle = hWnd;
  292.                     if (content != null && content.DockHandler.DockPanel == DockPanel)
  293.                         return content.DockHandler.Pane;
  294.                     pane = control as DockPane;
  295.                     if (pane != null && pane.DockPanel == DockPanel)
  296.                         break;
  297.                 }
  298.                 return pane;
  299.             }
  300.             private bool m_inRefreshActiveWindow = false;
  301.             private bool InRefreshActiveWindow
  302.             {
  303.                 get { return m_inRefreshActiveWindow; }
  304.             }
  305.             private void RefreshActiveWindow()
  306.             {
  307.                 SuspendFocusTracking();
  308.                 m_inRefreshActiveWindow = true;
  309.                 DockPane oldActivePane = ActivePane;
  310.                 IDockContent oldActiveContent = ActiveContent;
  311.                 IDockContent oldActiveDocument = ActiveDocument;
  312.                 SetActivePane();
  313.                 SetActiveContent();
  314.                 SetActiveDocumentPane();
  315.                 SetActiveDocument();
  316.                 DockPanel.AutoHideWindow.RefreshActivePane();
  317.                 ResumeFocusTracking();
  318.                 m_inRefreshActiveWindow = false;
  319.                 if (oldActiveContent != ActiveContent)
  320.                     DockPanel.OnActiveContentChanged(EventArgs.Empty);
  321.                 if (oldActiveDocument != ActiveDocument)
  322.                     DockPanel.OnActiveDocumentChanged(EventArgs.Empty);
  323.                 if (oldActivePane != ActivePane)
  324.                     DockPanel.OnActivePaneChanged(EventArgs.Empty);
  325.             }
  326.             private DockPane m_activePane = null;
  327.             public DockPane ActivePane
  328.             {
  329.                 get { return m_activePane; }
  330.             }
  331.             private void SetActivePane()
  332.             {
  333.                 DockPane value = GetPaneFromHandle(NativeMethods.GetFocus());
  334.                 if (m_activePane == value)
  335.                     return;
  336.                 if (m_activePane != null)
  337.                     m_activePane.SetIsActivated(false);
  338.                 m_activePane = value;
  339.                 if (m_activePane != null)
  340.                     m_activePane.SetIsActivated(true);
  341.             }
  342.             private IDockContent m_activeContent = null;
  343.             public IDockContent ActiveContent
  344.             {
  345.                 get { return m_activeContent; }
  346.             }
  347.             internal void SetActiveContent()
  348.             {
  349.                 IDockContent value = ActivePane == null ? null : ActivePane.ActiveContent;
  350.                 if (m_activeContent == value)
  351.                     return;
  352.                 if (m_activeContent != null)
  353.                     m_activeContent.DockHandler.IsActivated = false;
  354.                 m_activeContent = value;
  355.                 if (m_activeContent != null)
  356.                 {
  357.                     m_activeContent.DockHandler.IsActivated = true;
  358.                     if (!DockHelper.IsDockStateAutoHide((m_activeContent.DockHandler.DockState)))
  359.                         AddLastToActiveList(m_activeContent);
  360.                 }
  361.             }
  362.             private DockPane m_activeDocumentPane = null;
  363.             public DockPane ActiveDocumentPane
  364.             {
  365.                 get { return m_activeDocumentPane; }
  366.             }
  367.             private void SetActiveDocumentPane()
  368.             {
  369.                 DockPane value = null;
  370.                 if (ActivePane != null && ActivePane.DockState == DockState.Document)
  371.                     value = ActivePane;
  372.                 if (value == null && DockPanel.DockWindows != null)
  373.                 {
  374.                     if (ActiveDocumentPane == null)
  375.                         value = DockPanel.DockWindows[DockState.Document].DefaultPane;
  376.                     else if (ActiveDocumentPane.DockPanel != DockPanel || ActiveDocumentPane.DockState != DockState.Document)
  377.                         value = DockPanel.DockWindows[DockState.Document].DefaultPane;
  378.                     else
  379.                         value = ActiveDocumentPane;
  380.                 }
  381.                 if (m_activeDocumentPane == value)
  382.                     return;
  383.                 if (m_activeDocumentPane != null)
  384.                     m_activeDocumentPane.SetIsActiveDocumentPane(false);
  385.                 m_activeDocumentPane = value;
  386.                 if (m_activeDocumentPane != null)
  387.                     m_activeDocumentPane.SetIsActiveDocumentPane(true);
  388.             }
  389.             private IDockContent m_activeDocument = null;
  390.             public IDockContent ActiveDocument
  391.             {
  392.                 get { return m_activeDocument; }
  393.             }
  394.             private void SetActiveDocument()
  395.             {
  396.                 IDockContent value = ActiveDocumentPane == null ? null : ActiveDocumentPane.ActiveContent;
  397.                 if (m_activeDocument == value)
  398.                     return;
  399.                 m_activeDocument = value;
  400.             }
  401.         }
  402.         private IFocusManager FocusManager
  403.         {
  404.             get { return m_focusManager; }
  405.         }
  406.         internal IContentFocusManager ContentFocusManager
  407.         {
  408.             get { return m_focusManager; }
  409.         }
  410.         internal void SaveFocus()
  411.         {
  412.             DummyControl.Focus();
  413.         }
  414.         [Browsable(false)]
  415.         public IDockContent ActiveContent
  416.         {
  417.             get { return FocusManager.ActiveContent; }
  418.         }
  419.         [Browsable(false)]
  420.         public DockPane ActivePane
  421.         {
  422.             get { return FocusManager.ActivePane; }
  423.         }
  424.         [Browsable(false)]
  425.         public IDockContent ActiveDocument
  426.         {
  427.             get { return FocusManager.ActiveDocument; }
  428.         }
  429.         [Browsable(false)]
  430.         public DockPane ActiveDocumentPane
  431.         {
  432.             get { return FocusManager.ActiveDocumentPane; }
  433.         }
  434.         private static readonly object ActiveDocumentChangedEvent = new object();
  435.         [LocalizedCategory("Category_PropertyChanged")]
  436.         [LocalizedDescription("DockPanel_ActiveDocumentChanged_Description")]
  437.         public event EventHandler ActiveDocumentChanged
  438.         {
  439.             add { Events.AddHandler(ActiveDocumentChangedEvent, value); }
  440.             remove { Events.RemoveHandler(ActiveDocumentChangedEvent, value); }
  441.         }
  442.         protected virtual void OnActiveDocumentChanged(EventArgs e)
  443.         {
  444.             EventHandler handler = (EventHandler)Events[ActiveDocumentChangedEvent];
  445.             if (handler != null)
  446.                 handler(this, e);
  447.         }
  448.         private static readonly object ActiveContentChangedEvent = new object();
  449.         [LocalizedCategory("Category_PropertyChanged")]
  450.         [LocalizedDescription("DockPanel_ActiveContentChanged_Description")]
  451.         public event EventHandler ActiveContentChanged
  452.         {
  453.             add { Events.AddHandler(ActiveContentChangedEvent, value); }
  454.             remove { Events.RemoveHandler(ActiveContentChangedEvent, value); }
  455.         }
  456.         protected void OnActiveContentChanged(EventArgs e)
  457.         {
  458.             EventHandler handler = (EventHandler)Events[ActiveContentChangedEvent];
  459.             if (handler != null)
  460.                 handler(this, e);
  461.         }
  462.         private static readonly object ActivePaneChangedEvent = new object();
  463.         [LocalizedCategory("Category_PropertyChanged")]
  464.         [LocalizedDescription("DockPanel_ActivePaneChanged_Description")]
  465.         public event EventHandler ActivePaneChanged
  466.         {
  467.             add { Events.AddHandler(ActivePaneChangedEvent, value); }
  468.             remove { Events.RemoveHandler(ActivePaneChangedEvent, value); }
  469.         }
  470.         protected virtual void OnActivePaneChanged(EventArgs e)
  471.         {
  472.             EventHandler handler = (EventHandler)Events[ActivePaneChangedEvent];
  473.             if (handler != null)
  474.                 handler(this, e);
  475.         }
  476.     }
  477. }