public ToolBox() { miShrink.Anchor = AnchorStyles.Left | AnchorStyles.Right; miFill.Anchor = AnchorStyles.Left | AnchorStyles.Right; miLock.Anchor = AnchorStyles.Left | AnchorStyles.Right; this.Items.Add(miShrink); this.Items.Add(miFill); this.Items.Add(miLock); this.DropShadowEnabled = false; this.BackColor = Color.Transparent; this.Padding = new Padding(0, 2, 1, 2); // remove extra left pixel on left side miFill.Click += delegate { FlowLayoutPanel2 host = (FlowLayoutPanel2)Current.Parent; foreach (Control c in host.Controls) { if (c is Control2) { Control2 c2 = (Control2)c; if (!c2.isLocked) { c2.dh = 0; } } } Current.lastClicked = DateTime.Now; bool origLocked = Current.isLocked; Current.isLocked = false; host.UpdateDeltaHeights(); Current.isLocked = origLocked; host.PerformLayout(); }; miShrink.Click += delegate { Current.dh = 0; Current.lastClicked = DateTime.MinValue; FlowLayoutPanel2 host = (FlowLayoutPanel2)Current.Parent; bool origLocked = Current.isLocked; Current.isLocked = true; host.UpdateDeltaHeights(); Current.isLocked = origLocked; host.PerformLayout(); }; miLock.Click += delegate { Current.isLocked = !Current.isLocked; FlowLayoutPanel2 host = (FlowLayoutPanel2)Current.Parent; host.UpdateDeltaHeights(); host.PerformLayout(); }; }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); FlowLayoutPanel2 p = (FlowLayoutPanel2)this.Parent; Accordion acc = (Accordion)p.Parent; if (!acc.AllowMouseResize) { return; } // PerformLayout causes the control to move which triggers a MouseMove // even though the mouse didn't move. Thus, the absolute location is // used to determine if the mouse actually moved. There is probably a // better way to handle the resizing. Point pt = this.PointToScreen(e.Location); if (oldPoint == pt) { return; } oldPoint = pt; if (isGrabbing) { int dy = pt.Y - grabPoint.Y; dh = Math.Max(0, dhOrig + dy); p.UpdateDeltaHeights(); p.PerformLayout(); resetLocked = false; } else { int by = this.Height - e.Y; if (by < this.Padding.Bottom) { this.Cursor = cursorResize; } else { this.Cursor = this.DefaultCursor; } } }
// fillWt specifies that the control should be vertically expanded if there is extra // height available. There are two different modes: // 1) The last opened content that has fillWt > 0 will receive any extra height. // All other opened contents appear at their preferred size. // 2) The extra height is distributed between open contents that have fillWt > 0 // and are not locked by the user. The fillWt divided by the sum of open-unlocked // fillWts determines the exact distribution. public void Add(Control c, String text, String toolTip = null, double fillWt = 0, bool expand = false) { String da = GetDownArrow(); String ua = GetUpArrow(); // AutoSize must be true or the text will wrap under and be hidden var cb = new CheckBox { Appearance = Appearance.Button, Text = da + text, AutoSize = true }; cb.Anchor = AnchorStyles.Left | AnchorStyles.Right; // cb.Dock = DockStyle.Fill also works. cb.Margin = new Padding(0); // otherwise there are gaps between the buttons var c2 = new Control2(cb, c, fillWt) { Dock = DockStyle.Fill }; if (ContentPadding.HasValue) { c2.Padding = ContentPadding.Value; } if (!String.IsNullOrEmpty(toolTip)) { tips.SetToolTip(cb, toolTip); } host.Controls.Add(cb); host.Controls.Add(c2); cb.MouseHover += delegate { if (ShowToolMenu && cb.Checked && c2.fillWt > 0 && !toolBox.Visible) { var p1 = cb.PointToClient(Control.MousePosition); if (p1.X >= cb.Width - toolBox.Width) { Point p = new Point { X = cb.Width - toolBox.Width, Y = cb.Height }; toolBox.Current = c2; toolBox.Show(cb, p); } } }; cb.MouseUp += (o, e) => { if (ShowToolMenu && cb.Checked && c2.fillWt > 0 && e.Button == MouseButtons.Right) { var p1 = cb.PointToClient(Control.MousePosition); int w = toolBox.Width; p1.X -= w / 2; p1.Y -= w / 2; toolBox.Current = c2; toolBox.Show(cb, p1); } }; DateTime leaveTime; toolBox.MouseLeave += delegate { // the tooltip of a menu item causes a mouse leave, so // confirm the mouse is outside of the bounds before hiding leaveTime = DateTime.Now; new System.Threading.Thread((o) => { // allow the mouse to leave for up to 1 second before closing System.Threading.Thread.Sleep(1000); if ((DateTime)o != leaveTime) { return; } toolBox.BeginInvoke((Action) delegate { if (!toolBox.Bounds.Contains(Control.MousePosition)) { toolBox.Hide(); } }); }).Start(leaveTime); }; cb.MouseLeave += delegate { if (toolBox.Visible) { // since toolBox has no parent, its bounds are in screen coordinates if (!toolBox.Bounds.Contains(Control.MousePosition)) { toolBox.Hide(); } } }; cb.CheckedChanged += delegate { String a = (cb.Checked ? GetUpArrow() : GetDownArrow()); cb.Text = a + text; // must set text regardless of isAdjusting if (cb.Checked) { c2.lastClicked = DateTime.Now; } if (isAdjusting) { return; } // for some reason, when the scrollbar first appears, it scrolls an // amount equal to the ContentPadding.Left to the right. Also, the scroll // value resets to 0 right before the checkbox is changed, so it's not // easy to know what the previous value is. //int hsorig = 0; //if (host.HorizontalScroll.Visible) // hsorig = host.HorizontalScroll.Value; if (OpenOneOnly) { if (lastChecked != null && cb.Checked && c2 != lastChecked) { isAdjusting = true; lastChecked.cb.Checked = false; isAdjusting = false; } } lastChecked = c2; host.UpdateDeltaHeights(); host.AutoScroll = false; // forces proper refresh host.AutoScroll = true; host.Invalidate(true); host.PerformLayout(); GetFirstFocus(c).Focus(); if (host.HorizontalScroll.Visible) { // something causes the scrollbar to scroll to the right by an amount equal // to the ContentPadding.Left value. host.AutoScrollPosition = Point.Empty; } }; // wait for all controls to be added before expanding if currently not visible if (expand) { if (this.Visible) { cb.Checked = true; } else { this.HandleCreated += delegate { cb.Checked = true; } }; } }