Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Scheduling/HeuristicLab.ExtLibs/HeuristicLab.WinFormsUI/2.3.1/WinFormsUI-2.3.1/Docking/DockPanel.FocusManager.cs @ 6274

Last change on this file since 6274 was 4068, checked in by swagner, 14 years ago

Sorted usings and removed unused usings in entire solution (#1094)

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