using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.Windows.Forms; using Microsoft.Win32; namespace Common { class ResizableControls { int dragSize = 16; Point mouseStartPos = Point.Empty; Control movedControl = null; Size movedControlSize; Size movedControlParentSize; Form form; Point lastMousePos; string RegSubKey = "ControlHeight"; RegistryKey regKey; int richTextBoxMinHeight = 24; int listViewMinHeight = 48; int dataGridViewMinHeight = 24; public void InitForm(Form form) { this.form = form; InitControlsRecursive(form.Controls); LoadFromRegistry(form); } public void InitControlsRecursive(Control.ControlCollection coll) { foreach (Control c in coll) { if (c is ResizableListView) (c as ResizableListView).MouseDownEx += HandleMouseDownEx; else c.MouseDown += HandleMouseDown; if (c is ResizableListView) (c as ResizableListView).MouseUpEx += HandleMouseUpEx; else c.MouseUp += HandleMouseUp; if (c is ResizableListView) (c as ResizableListView).MouseMoveEx += HandleMouseMoveEx; else c.MouseMove += HandleMouseMove; c.MouseLeave += HandleMouseLeave; //c.MouseCaptureChanged += MouseCaptureChanged; InitControlsRecursive(c.Controls); } } public static Control FindControlAtPoint(Control container, Point pos) { Control child; foreach (Control c in container.Controls) { if (c.Visible && c.Bounds.Contains(pos)) { child = FindControlAtPoint(c, new Point(pos.X - c.Left, pos.Y - c.Top)); if (child == null) return c; else return child; } } return null; } public static Control FindControlAtCursor(Form form) { Point pos = Cursor.Position; if (form.Bounds.Contains(pos)) return FindControlAtPoint(form, form.PointToClient(pos)); return null; } private void MouseCaptureChanged(object sender, EventArgs e) { mouseStartPos = Point.Empty; movedControl = null; } private void HandleMouseDown(object sender, MouseEventArgs e) { HandleMouseDownEx(sender, new MouseEventArgsEx(e.Button, e.Clicks, e.X, e.Y, e.Delta)); } private void HandleMouseDownEx(object sender, MouseEventArgsEx e) { Point pos = Cursor.Position; mouseStartPos = pos; lastMousePos = pos; movedControl = FindControlAtPoint(form, form.PointToClient(pos)); if (movedControl != null) { Rectangle dragArea = new Rectangle(movedControl.PointToScreen(new Point(0, movedControl.Size.Height - dragSize)), new Size(movedControl.Size.Width, dragSize)); if (dragArea.Contains(pos) && ((movedControl is RichTextBox) || (movedControl is ListView) || (movedControl is DataGridView))) { movedControlSize = movedControl.Size; movedControlParentSize = movedControl.Parent.Parent.Size; e.Handled = true; } else movedControl = null; } } private void HandleMouseLeave(object sender, EventArgs e) { mouseStartPos = Point.Empty; movedControl = null; } private void HandleMouseUp(object sender, MouseEventArgs e) { HandleMouseUpEx(sender, new MouseEventArgsEx(e.Button, e.Clicks, e.X, e.Y, e.Delta)); } private void HandleMouseUpEx(object sender, MouseEventArgsEx e) { mouseStartPos = Point.Empty; movedControl = null; } private void HandleMouseMove(object sender, MouseEventArgs e) { HandleMouseMoveEx(sender, new MouseEventArgsEx(e.Button, e.Clicks, e.X, e.Y, e.Delta)); } private void HandleMouseMoveEx(object sender, MouseEventArgsEx e) { Point pos = Cursor.Position; // Show pan cursor for bottom right corner Control movableControl = FindControlAtPoint(form, form.PointToClient(pos)); if (movableControl != null) { Rectangle dragArea = new Rectangle(movableControl.PointToScreen(new Point(0, movableControl.Size.Height - dragSize)), new Size(movableControl.Size.Width, dragSize)); if (dragArea.Contains(pos) && ((movableControl is RichTextBox) || (movableControl is ListView) || (movableControl is DataGridView))) { if (Cursor.Current != Cursors.SizeNS) Cursor.Current = Cursors.SizeNS; } else if (Cursor.Current == Cursors.SizeNS) Cursor.Current = Cursors.Default; } if ((mouseStartPos != Point.Empty) && (movedControl != null) && (lastMousePos != pos)) { Point posDiff = Point.Subtract(pos, (Size)lastMousePos); posDiff.X = 0; // Allow only resize of height //movedControl.Size = (Size)Point.Add(posDiff, movedControl.Size); Cursor.Current = Cursors.Arrow; Size newControlSize = (Size)Point.Add(posDiff, movedControl.Size); if ((movedControl is RichTextBox) && (newControlSize.Height < richTextBoxMinHeight)) posDiff.Y = movedControl.Height - richTextBoxMinHeight; else if ((movedControl is ListView) && (newControlSize.Height < listViewMinHeight)) posDiff.Y = movedControl.Height - listViewMinHeight; else if ((movedControl is DataGridView) && (newControlSize.Height < dataGridViewMinHeight)) posDiff.Y = movedControl.Height - dataGridViewMinHeight; ResizeParent(movedControl, posDiff); lastMousePos = pos; regKey.SetValue(movedControl.Name, movedControl.Height); } } private void ResizeParent(Control control, Point diff) { if ((control.Parent != null) && !diff.IsEmpty) { if ((control.Parent is Panel) && (control.Parent as Panel).AutoScroll) return; if (control.Parent is Panel) control.Parent.Size = (Size)Point.Add(diff, control.Parent.Size); ResizeParent(control.Parent, diff); } } private void LoadFromRegistry(Form form) { regKey = Application.UserAppDataRegistry.OpenSubKey(RegSubKey + "\\" + form.Name, true); if (regKey == null) regKey = Application.UserAppDataRegistry.CreateSubKey(RegSubKey + "\\" + form.Name); LoadControlFromRegistry(form, regKey); } private void LoadControlFromRegistry(Control control, RegistryKey regKey) { if ((control is RichTextBox) || (control is ListView) || (control is DataGridView)) { int newHeight = (int)regKey.GetValue(control.Name, control.Height); if ((control is RichTextBox) && (newHeight < richTextBoxMinHeight)) newHeight = richTextBoxMinHeight; else if ((control is ListView) && (newHeight < listViewMinHeight)) newHeight = listViewMinHeight; else if ((control is DataGridView) && (newHeight < dataGridViewMinHeight)) newHeight = dataGridViewMinHeight; ResizeParent(control, Point.Subtract(new Point(control.Width, newHeight), control.Size)); } foreach (Control child in control.Controls) { LoadControlFromRegistry(child, regKey); } } } public class MouseEventArgsEx : MouseEventArgs { bool handled; public MouseEventArgsEx(MouseButtons button, int clicks, int x, int y, int delta): base(button, clicks, x, y, delta) { handled = false; } public bool Handled { get { return handled; } set { handled = value; } } } public class ResizableListView : ListView { public event EventHandler MouseDownEx; public event EventHandler MouseUpEx; public event EventHandler MouseMoveEx; protected override void WndProc(ref Message m) { Boolean handled = false; m.Result = IntPtr.Zero; const int WM_MOUSEMOVE = 0x0200; const int WM_LBUTTONDOWN = 0x0201; const int WM_LBUTTONUP = 0x0202; if (m.Msg == WM_LBUTTONDOWN) { IntPtr xy = m.LParam; int x = unchecked((short)(long)xy); int y = unchecked((short)((long)xy >> 16)); MouseEventArgsEx eventArgs = new MouseEventArgsEx(MouseButtons.Left, 1, x, y, 0); MouseDownEx(this, eventArgs); handled = eventArgs.Handled; } else if (m.Msg == WM_LBUTTONUP) { IntPtr xy = m.LParam; int x = unchecked((short)(long)xy); int y = unchecked((short)((long)xy >> 16)); MouseEventArgsEx eventArgs = new MouseEventArgsEx(MouseButtons.Left, 1, x, y, 0); MouseUpEx(this, eventArgs); handled = eventArgs.Handled; } else if (m.Msg == WM_MOUSEMOVE) { IntPtr xy = m.LParam; int x = unchecked((short)(long)xy); int y = unchecked((short)((long)xy >> 16)); MouseEventArgsEx eventArgs = new MouseEventArgsEx(MouseButtons.Left, 1, x, y, 0); MouseMoveEx(this, eventArgs); handled = eventArgs.Handled; } if (!handled) base.WndProc(ref m); // else DefWndProc(ref m); } } }