/// ------------------------------------------------------------------------------------ /// <summary> /// attach this class to any dockable type of container control to make it dockable. /// Attach a container control and use it as a grip hande. The handle must support mouse /// move events. Supply a splitter control to allow resizing of the docked container /// </summary> /// <param name="container">control to be dockable</param> /// <param name="handle">handle to be used to track the mouse movement (e.g. caption of /// the container)</param> /// <param name="splitter">splitter to resize the docked container (optional)</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public IFloaty Attach(ScrollableControl container, Control handle, Splitter splitter) { if (container == null) throw new ArgumentException("container cannot be null"); if (handle == null) throw new ArgumentException("handle cannot be null"); DockState dockState = new DockState(); dockState.Container = container; dockState.Handle = handle; dockState.OrgDockHost = _dockHost; dockState.Splitter = splitter; dockState.OrgFloatingBounds = container.Bounds; Floaty floaty = new Floaty(this); floaty.Persistence = m_persistence; floaty.Attach(dockState); _floaties.Add(floaty); return floaty; }
/// ------------------------------------------------------------------------------------ /// <summary> /// makes the docked control floatable in this Floaty form /// </summary> /// <param name="dockState">State of the dock.</param> /// <param name="offsetx">The offset in x direction from left of container.</param> /// <param name="offsety">The offset in y direction from top of container.</param> /// <remarks>This method calls SuspendLayout on the control's parent.</remarks> /// ------------------------------------------------------------------------------------ private void MakeFloatable(DockState dockState, int offsetx, int offsety) { if (m_isFloating) { return; } Point location = Cursor.Position; m_dockState = dockState; Text = m_dockState.Handle.Text; Size containerSize = m_dockState.OrgFloatingBounds.Size; if (m_dockState.Container.Equals(m_dockState.Handle)) { // REVIEW: what are these values? containerSize.Width += 18; containerSize.Height += 28; } else { containerSize.Width += 2 * SystemInformation.FrameBorderSize.Width; containerSize.Height += SystemInformation.ToolWindowCaptionHeight + 2 * SystemInformation.FrameBorderSize.Height; } if (containerSize.Width > 600) { containerSize.Width = 600; } if (containerSize.Height > 600) { containerSize.Height = 600; } // We try to put the left/top corner of the floaty at the location of the // container. However, if we'll display the container too small, we have // to move the top/left corner so that the Cursor.Position is inside of the // floaty window title bar. location.X -= Math.Min(Math.Max(0, offsetx), containerSize.Width); location.Y -= Math.Min(Math.Max(0, offsety), containerSize.Height); Bounds = new Rectangle(location, containerSize); m_dockState.OrgDockingParent = m_dockState.Container.Parent; m_dockState.OrgDockStyle = m_dockState.Container.Dock; if (m_dockState.Container.Dock == DockStyle.Left || m_dockState.Container.Dock == DockStyle.Right) { m_dockState.OrgWidth = m_dockState.Container.Width; } else { m_dockState.OrgHeight = m_dockState.Container.Height; } if (m_hideHandle) { m_dockState.Handle.Hide(); } // Prevent resizing of parent until the user releases mouse button m_dockState.OrgDockingParent.SuspendLayout(); m_parentLayoutIsSuspended = true; m_dockState.Container.Parent = this; m_dockState.Container.Dock = DockStyle.Fill; if (m_dockState.Splitter != null) { m_dockState.Splitter.Visible = false; // hide splitter m_dockState.Splitter.Parent = this; } // allow redraw of floaty and container // Application.DoEvents(); // this is kind of tricky // disable the mousemove events of the handle SendMessage(m_dockState.Handle.Handle.ToInt32(), WM_LBUTTONUP, 0, 0); m_isFloating = true; // If we're not undocking via dragging the window away from the host, then // place the window where it was the last time it was floating. If we called // the PlaceUndockedWindow method even when dragging window from it's host // then as the user dragged the window, it would snap to some position that // is likely unexpected. if (!m_startFloating) { PlaceUndockedWindow(); } Show(); if (Undocked != null) { Undocked(this, EventArgs.Empty); } // enable the mousemove events of the new floating form, start dragging the form immediately SendMessage(this.Handle.ToInt32(), WM_SYSCOMMAND, SC_MOVE | 0x02, 0); }