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

C#编程

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. using System.Drawing;
  4. using System.Windows.Forms;
  5. using System.Runtime.InteropServices;
  6. using System.Security.Permissions;
  7. using System.Diagnostics.CodeAnalysis;
  8. namespace WeifenLuo.WinFormsUI.Docking
  9. {
  10. public class FloatWindow : Form, INestedPanesContainer, IDockDragSource
  11. {
  12. private NestedPaneCollection m_nestedPanes;
  13. internal const int WM_CHECKDISPOSE = (int)(Win32.Msgs.WM_USER + 1);
  14. internal protected FloatWindow(DockPanel dockPanel, DockPane pane)
  15. {
  16. InternalConstruct(dockPanel, pane, false, Rectangle.Empty);
  17. }
  18. internal protected FloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
  19. {
  20. InternalConstruct(dockPanel, pane, true, bounds);
  21. }
  22. private void InternalConstruct(DockPanel dockPanel, DockPane pane, bool boundsSpecified, Rectangle bounds)
  23. {
  24. if (dockPanel == null)
  25. throw(new ArgumentNullException(Strings.FloatWindow_Constructor_NullDockPanel));
  26. m_nestedPanes = new NestedPaneCollection(this);
  27. FormBorderStyle = FormBorderStyle.SizableToolWindow;
  28. ShowInTaskbar = false;
  29.             if (dockPanel.RightToLeft != RightToLeft)
  30.                 RightToLeft = dockPanel.RightToLeft;
  31.             if (RightToLeftLayout != dockPanel.RightToLeftLayout)
  32.                 RightToLeftLayout = dockPanel.RightToLeftLayout;
  33. SuspendLayout();
  34.             if (boundsSpecified)
  35.             {
  36.                 Bounds = bounds;
  37.                 StartPosition = FormStartPosition.Manual;
  38.             }
  39.             else
  40.             {
  41.                 StartPosition = FormStartPosition.WindowsDefaultLocation;
  42.                 Size = dockPanel.DefaultFloatWindowSize;
  43.             }
  44. m_dockPanel = dockPanel;
  45. Owner = DockPanel.FindForm();
  46. DockPanel.AddFloatWindow(this);
  47. if (pane != null)
  48. pane.FloatWindow = this;
  49. ResumeLayout();
  50. }
  51. protected override void Dispose(bool disposing)
  52. {
  53. if (disposing)
  54. {
  55. if (DockPanel != null)
  56. DockPanel.RemoveFloatWindow(this);
  57. m_dockPanel = null;
  58. }
  59. base.Dispose(disposing);
  60. }
  61. private bool m_allowEndUserDocking = true;
  62. public bool AllowEndUserDocking
  63. {
  64. get { return m_allowEndUserDocking; }
  65. set { m_allowEndUserDocking = value; }
  66. }
  67. public NestedPaneCollection NestedPanes
  68. {
  69. get { return m_nestedPanes; }
  70. }
  71. public VisibleNestedPaneCollection VisibleNestedPanes
  72. {
  73. get { return NestedPanes.VisibleNestedPanes; }
  74. }
  75. private DockPanel m_dockPanel;
  76. public DockPanel DockPanel
  77. {
  78. get { return m_dockPanel; }
  79. }
  80. public DockState DockState
  81. {
  82. get { return DockState.Float; }
  83. }
  84. public bool IsFloat
  85. {
  86. get { return DockState == DockState.Float; }
  87. }
  88. internal bool IsDockStateValid(DockState dockState)
  89. {
  90. foreach (DockPane pane in NestedPanes)
  91. foreach (IDockContent content in pane.Contents)
  92. if (!DockHelper.IsDockStateValid(dockState, content.DockHandler.DockAreas))
  93. return false;
  94. return true;
  95. }
  96. protected override void OnActivated(EventArgs e)
  97. {
  98. DockPanel.FloatWindows.BringWindowToFront(this);
  99. base.OnActivated (e);
  100. // Propagate the Activated event to the visible panes content objects
  101. foreach (DockPane pane in VisibleNestedPanes)
  102. foreach (IDockContent content in pane.Contents)
  103. content.OnActivated(e);
  104. }
  105. protected override void OnDeactivate(EventArgs e)
  106. {
  107. base.OnDeactivate(e);
  108. // Propagate the Deactivate event to the visible panes content objects
  109. foreach (DockPane pane in VisibleNestedPanes)
  110. foreach (IDockContent content in pane.Contents)
  111. content.OnDeactivate(e);
  112. }
  113. protected override void OnLayout(LayoutEventArgs levent)
  114. {
  115. VisibleNestedPanes.Refresh();
  116. RefreshChanges();
  117.             Visible = (VisibleNestedPanes.Count > 0);
  118.             SetText();
  119. base.OnLayout(levent);
  120. }
  121.         [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.Windows.Forms.Control.set_Text(System.String)")]
  122.         internal void SetText()
  123. {
  124. DockPane theOnlyPane = (VisibleNestedPanes.Count == 1) ? VisibleNestedPanes[0] : null;
  125. if (theOnlyPane == null)
  126. Text = " "; // use " " instead of string.Empty because the whole title bar will disappear when ControlBox is set to false.
  127. else if (theOnlyPane.ActiveContent == null)
  128. Text = " ";
  129. else
  130. Text = theOnlyPane.ActiveContent.DockHandler.TabText;
  131. }
  132. protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
  133. {
  134. Rectangle rectWorkArea = SystemInformation.VirtualScreen;
  135. if (y + height > rectWorkArea.Bottom)
  136. y -= (y + height) - rectWorkArea.Bottom;
  137. if (y < rectWorkArea.Top)
  138. y += rectWorkArea.Top - y;
  139. base.SetBoundsCore (x, y, width, height, specified);
  140. }
  141.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  142. protected override void WndProc(ref Message m)
  143. {
  144. if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDOWN)
  145. {
  146. if (IsDisposed)
  147. return;
  148. uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
  149. if (result == 2 && DockPanel.AllowEndUserDocking && this.AllowEndUserDocking) // HITTEST_CAPTION
  150. {
  151. Activate();
  152. m_dockPanel.BeginDrag(this);
  153. }
  154. else
  155. base.WndProc(ref m);
  156. return;
  157. }
  158.             else if (m.Msg == (int)Win32.Msgs.WM_NCRBUTTONDOWN)
  159.             {
  160.                 uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
  161.                 if (result == 2) // HITTEST_CAPTION
  162.                 {
  163.                     DockPane theOnlyPane = (VisibleNestedPanes.Count == 1) ? VisibleNestedPanes[0] : null;
  164.                     if (theOnlyPane != null && theOnlyPane.ActiveContent != null)
  165.                     {
  166.                         theOnlyPane.ShowTabPageContextMenu(this, PointToClient(Control.MousePosition));
  167.                         return;
  168.                     }
  169.                 }
  170.                 base.WndProc(ref m);
  171.                 return;
  172.             }
  173.             else if (m.Msg == (int)Win32.Msgs.WM_CLOSE)
  174.             {
  175.                 if (NestedPanes.Count == 0)
  176.                 {
  177.                     base.WndProc(ref m);
  178.                     return;
  179.                 }
  180.                 for (int i = NestedPanes.Count - 1; i >= 0; i--)
  181.                 {
  182.                     DockContentCollection contents = NestedPanes[i].Contents;
  183.                     for (int j = contents.Count - 1; j >= 0; j--)
  184.                     {
  185.                         IDockContent content = contents[j];
  186.                         if (content.DockHandler.DockState != DockState.Float)
  187.                             continue;
  188.                         if (!content.DockHandler.CloseButton)
  189.                             continue;
  190.                         if (content.DockHandler.HideOnClose)
  191.                             content.DockHandler.Hide();
  192.                         else
  193.                             content.DockHandler.Close();
  194.                     }
  195.                 }
  196.                 return;
  197.             }
  198.             else if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDBLCLK)
  199.             {
  200.                 uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
  201.                 if (result != 2) // HITTEST_CAPTION
  202.                 {
  203.                     base.WndProc(ref m);
  204.                     return;
  205.                 }
  206.                 DockPanel.SuspendLayout(true);
  207.                 // Restore to panel
  208.                 foreach (DockPane pane in NestedPanes)
  209.                 {
  210.                     if (pane.DockState != DockState.Float)
  211.                         continue;
  212.                     pane.RestoreToPanel();
  213.                 }
  214.                 DockPanel.ResumeLayout(true, true);
  215.                 return;
  216.             }
  217.             else if (m.Msg == WM_CHECKDISPOSE)
  218.             {
  219.                 if (NestedPanes.Count == 0)
  220.                     Dispose();
  221.                 return;
  222.             }
  223. base.WndProc(ref m);
  224. }
  225. internal void RefreshChanges()
  226. {
  227.             if (IsDisposed)
  228.                 return;
  229. if (VisibleNestedPanes.Count == 0)
  230. {
  231. ControlBox = true;
  232. return;
  233. }
  234. for (int i=VisibleNestedPanes.Count - 1; i>=0; i--)
  235. {
  236. DockContentCollection contents = VisibleNestedPanes[i].Contents;
  237. for (int j=contents.Count - 1; j>=0; j--)
  238. {
  239. IDockContent content = contents[j];
  240. if (content.DockHandler.DockState != DockState.Float)
  241. continue;
  242. if (content.DockHandler.CloseButton && content.DockHandler.CloseButtonVisible)
  243. {
  244. ControlBox = true;
  245. return;
  246. }
  247. }
  248. }
  249. //Only if there is a ControlBox do we turn it off
  250. //old code caused a flash of the window.
  251.             if (ControlBox)
  252. ControlBox = false;
  253. }
  254. public virtual Rectangle DisplayingRectangle
  255. {
  256. get { return ClientRectangle; }
  257. }
  258. internal void TestDrop(IDockDragSource dragSource, DockOutlineBase dockOutline)
  259. {
  260.             if (VisibleNestedPanes.Count == 1)
  261.             {
  262.                 DockPane pane = VisibleNestedPanes[0];
  263.                 if (!dragSource.CanDockTo(pane))
  264.                     return;
  265.                 Point ptMouse = Control.MousePosition;
  266.                 uint lParam = Win32Helper.MakeLong(ptMouse.X, ptMouse.Y);
  267.                 if (NativeMethods.SendMessage(Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, lParam) == (uint)Win32.HitTest.HTCAPTION)
  268.                     dockOutline.Show(VisibleNestedPanes[0], -1);
  269.             }
  270. }
  271.         #region IDockDragSource Members
  272.         #region IDragSource Members
  273.         Control IDragSource.DragControl
  274.         {
  275.             get { return this; }
  276.         }
  277.         #endregion
  278.         bool IDockDragSource.IsDockStateValid(DockState dockState)
  279.         {
  280.             return IsDockStateValid(dockState);
  281.         }
  282.         bool IDockDragSource.CanDockTo(DockPane pane)
  283.         {
  284.             if (!IsDockStateValid(pane.DockState))
  285.                 return false;
  286.             if (pane.FloatWindow == this)
  287.                 return false;
  288.             return true;
  289.         }
  290.         Rectangle IDockDragSource.BeginDrag(Point ptMouse)
  291.         {
  292.             return Bounds;
  293.         }
  294.         public  void FloatAt(Rectangle floatWindowBounds)
  295.         {
  296.             Bounds = floatWindowBounds;
  297.         }
  298.         public void DockTo(DockPane pane, DockStyle dockStyle, int contentIndex)
  299.         {
  300.             if (dockStyle == DockStyle.Fill)
  301.             {
  302.                 for (int i = NestedPanes.Count - 1; i >= 0; i--)
  303.                 {
  304.                     DockPane paneFrom = NestedPanes[i];
  305.                     for (int j = paneFrom.Contents.Count - 1; j >= 0; j--)
  306.                     {
  307.                         IDockContent c = paneFrom.Contents[j];
  308.                         c.DockHandler.Pane = pane;
  309.                         if (contentIndex != -1)
  310.                             pane.SetContentIndex(c, contentIndex);
  311.                         c.DockHandler.Activate();
  312.                     }
  313.                 }
  314.             }
  315.             else
  316.             {
  317.                 DockAlignment alignment = DockAlignment.Left;
  318.                 if (dockStyle == DockStyle.Left)
  319.                     alignment = DockAlignment.Left;
  320.                 else if (dockStyle == DockStyle.Right)
  321.                     alignment = DockAlignment.Right;
  322.                 else if (dockStyle == DockStyle.Top)
  323.                     alignment = DockAlignment.Top;
  324.                 else if (dockStyle == DockStyle.Bottom)
  325.                     alignment = DockAlignment.Bottom;
  326.                 MergeNestedPanes(VisibleNestedPanes, pane.NestedPanesContainer.NestedPanes, pane, alignment, 0.5);
  327.             }
  328.         }
  329.         public void DockTo(DockPanel panel, DockStyle dockStyle)
  330.         {
  331.             if (panel != DockPanel)
  332.                 throw new ArgumentException(Strings.IDockDragSource_DockTo_InvalidPanel, "panel");
  333.             NestedPaneCollection nestedPanesTo = null;
  334.             if (dockStyle == DockStyle.Top)
  335.                 nestedPanesTo = DockPanel.DockWindows[DockState.DockTop].NestedPanes;
  336.             else if (dockStyle == DockStyle.Bottom)
  337.                 nestedPanesTo = DockPanel.DockWindows[DockState.DockBottom].NestedPanes;
  338.             else if (dockStyle == DockStyle.Left)
  339.                 nestedPanesTo = DockPanel.DockWindows[DockState.DockLeft].NestedPanes;
  340.             else if (dockStyle == DockStyle.Right)
  341.                 nestedPanesTo = DockPanel.DockWindows[DockState.DockRight].NestedPanes;
  342.             else if (dockStyle == DockStyle.Fill)
  343.                 nestedPanesTo = DockPanel.DockWindows[DockState.Document].NestedPanes;
  344.             DockPane prevPane = null;
  345.             for (int i = nestedPanesTo.Count - 1; i >= 0; i--)
  346.                 if (nestedPanesTo[i] != VisibleNestedPanes[0])
  347.                     prevPane = nestedPanesTo[i];
  348.             MergeNestedPanes(VisibleNestedPanes, nestedPanesTo, prevPane, DockAlignment.Left, 0.5);
  349.         }
  350.         private static void MergeNestedPanes(VisibleNestedPaneCollection nestedPanesFrom, NestedPaneCollection nestedPanesTo, DockPane prevPane, DockAlignment alignment, double proportion)
  351.         {
  352.             if (nestedPanesFrom.Count == 0)
  353.                 return;
  354.             int count = nestedPanesFrom.Count;
  355.             DockPane[] panes = new DockPane[count];
  356.             DockPane[] prevPanes = new DockPane[count];
  357.             DockAlignment[] alignments = new DockAlignment[count];
  358.             double[] proportions = new double[count];
  359.             for (int i = 0; i < count; i++)
  360.             {
  361.                 panes[i] = nestedPanesFrom[i];
  362.                 prevPanes[i] = nestedPanesFrom[i].NestedDockingStatus.PreviousPane;
  363.                 alignments[i] = nestedPanesFrom[i].NestedDockingStatus.Alignment;
  364.                 proportions[i] = nestedPanesFrom[i].NestedDockingStatus.Proportion;
  365.             }
  366.             DockPane pane = panes[0].DockTo(nestedPanesTo.Container, prevPane, alignment, proportion);
  367.             panes[0].DockState = nestedPanesTo.DockState;
  368.             for (int i = 1; i < count; i++)
  369.             {
  370.                 for (int j = i; j < count; j++)
  371.                 {
  372.                     if (prevPanes[j] == panes[i - 1])
  373.                         prevPanes[j] = pane;
  374.                 }
  375.                 pane = panes[i].DockTo(nestedPanesTo.Container, prevPanes[i], alignments[i], proportions[i]);
  376.                 panes[i].DockState = nestedPanesTo.DockState;
  377.             }
  378.         }
  379.         #endregion
  380.     }
  381. }