Anmerkung: Ich weiß nicht ob die Frage hier rein gehört oder in den Tab
Programmierwerkzeuge
Ich habe eine Form-Klasse erstellt, die ich als Basisklasse für alle meine borderless Forms verwende. Diese Klasse ermöglicht es mir, die Größe des Fensters zu ändern, ohne eine Border zu haben. Diese Klasse verwendet die Nachricht
WM_NCHITEST der WndProc. Das Problem ist, dass alle im Formular platzierten Controls im Designer nicht per Klick auswählbar sind. Ich kann Container wie Panels auswählen, indem ich einen Bereich darin markiere, aber wenn ich darauf klicke, wähle ich das Formular erneut aus. Das bedeutet auch, dass ich keine Controls durch Ziehen platzieren kann.
Dies ist die Klasse BorderlessResizeableForm:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280:
| using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Windows.Forms;
namespace CustomWinFormsControls { public class BorderlessResizableForm : Form { private FormDragControl dragControl; private Dictionary<Control, BorderWndProcFilter> borderFilters;
private int _resizeBorderThickness = 5;
[EditorBrowsable(EditorBrowsableState.Always)] [Browsable(true)] [DefaultValue(null)] [Category("Behaviour")] [Description("The control which should be used to move the window around.")] public Control DragTarget { get => this.dragControl?.Target; set { if (!(this.dragControl is null)) this.dragControl.Target = value; } }
[EditorBrowsable(EditorBrowsableState.Always)] [Browsable(true)] [DefaultValue(null)] [Category("Behaviour")] [Description("The thickness of the resize border on all sides of the window. The border is invisible. Setting it will not result in a padding.")] public int ResizeBorderThickness { get => this._resizeBorderThickness; set { if (this._resizeBorderThickness == value) return;
this._resizeBorderThickness = value;
foreach (BorderWndProcFilter filter in this.borderFilters.Values) filter.BorderThinckness = value; } }
public BorderlessResizableForm() { this.FormBorderStyle = FormBorderStyle.None; this.SetStyle(ControlStyles.ResizeRedraw, true);
this.dragControl = new FormDragControl(); this.borderFilters = new Dictionary<Control, BorderWndProcFilter>(); this.ControlAdded += this.Control_ControlAdded; this.ControlRemoved += this.Control_ControlRemoved; }
private void Control_ControlAdded(object sender, ControlEventArgs e) { this.ApplyFiltersRecursive(this, e.Control); }
private void Control_ControlRemoved(object sender, ControlEventArgs e) { this.RemoveFiltersRecursive(e.Control); }
private void ApplyFiltersRecursive(Control parent, Control control) { if (control is null) return;
this.borderFilters[control] = new BorderWndProcFilter(parent, control, this.ResizeBorderThickness);
control.ControlAdded -= this.Control_ControlAdded; control.ControlRemoved -= this.Control_ControlRemoved;
control.ControlAdded += this.Control_ControlAdded; control.ControlRemoved += this.Control_ControlRemoved;
foreach (Control c in control.Controls) if (!(c is null)) this.ApplyFiltersRecursive(parent, c); }
private void RemoveFiltersRecursive(Control control) { if (control is null) return;
this.borderFilters.Remove(control); control.ControlAdded -= this.Control_ControlAdded; control.ControlRemoved -= this.Control_ControlRemoved;
foreach (Control c in control.Controls) if (!(c is null)) this.RemoveFiltersRecursive(c); }
protected override void WndProc(ref Message m) { if (m.Msg != BorderWndProcFilter.WM_NCHITTEST) { base.WndProc(ref m); return; }
Point pos = this.PointToClient(new Point(m.LParam.ToInt32()));
if (pos.X <= this.ResizeBorderThickness && pos.Y <= this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTTOPLEFT); return; }
if (pos.X >= this.ClientSize.Width - this.ResizeBorderThickness && pos.Y <= this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTTOPRIGHT); return; }
if (pos.X <= this.ResizeBorderThickness && pos.Y >= this.ClientSize.Height - this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTBOTTOMLEFT); return; }
if (pos.X >= this.ClientSize.Width - this.ResizeBorderThickness && pos.Y >= this.ClientSize.Height - this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTBOTTOMRIGHT); return; }
if (pos.X <= this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTLEFT); return; }
if (pos.Y <= this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTTOP); return; }
if (pos.X >= this.ClientSize.Width - this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTRIGHT); return; }
if (pos.Y >= this.ClientSize.Height - this.ResizeBorderThickness) { m.Result = new IntPtr(BorderWndProcFilter.HTBOTTOM); return; }
base.WndProc(ref m); } }
public class BorderWndProcFilter : NativeWindow { public const int WM_NCHITTEST = 0x0084;
public const int HTCAPTION = 0x00000002; public const int HTTOP = 0x0000000C; public const int HTBOTTOM = 0x0000000F; public const int HTLEFT = 0x0000000A; public const int HTRIGHT = 0x0000000B; public const int HTTOPLEFT = 0x0000000D; public const int HTTOPRIGHT = 0x0000000E; public const int HTBOTTOMLEFT = 0x00000010; public const int HTBOTTOMRIGHT = 0x00000011; public const int HTTRANSPARENT = -1;
public static List<Type> TypeBlacklist { get; set; } = new List<Type>();
private Control parent; private Control child;
public int BorderThinckness { get; set; } public bool ResizeBorderLeft { get; set; } public bool ResizeBorderRight { get; set; } public bool ResizeBorderTop { get; set; } public bool ResizeBorderBottom { get; set; }
public BorderWndProcFilter(Control parent, Control child, int borderThinckness) { this.parent = parent; this.child = child;
try { if (!BorderWndProcFilter.TypeBlacklist.Contains(child.GetType())) this.AssignHandle(child.Handle); } catch (Exception) { }
this.BorderThinckness = borderThinckness;
this.ResizeBorderLeft = true; this.ResizeBorderRight = true; this.ResizeBorderTop = true; this.ResizeBorderBottom = true; }
public BorderWndProcFilter(Control parent, Control child, int borderThinckness, bool left, bool right, bool top, bool bottom) { this.parent = parent; this.child = child; this.AssignHandle(child.Handle); this.BorderThinckness = borderThinckness;
this.ResizeBorderLeft = left; this.ResizeBorderRight = right; this.ResizeBorderTop = top; this.ResizeBorderBottom = bottom; }
protected override void WndProc(ref Message m) { if (m.Msg != WM_NCHITTEST) { base.WndProc(ref m); return; }
if (this.parent is null) { base.WndProc(ref m); return; }
Point pos = new Point(m.LParam.ToInt32()); Point parentGlobalPos = this.parent is Form ? this.parent.Location : this.parent.PointToScreen(this.parent.Location);
if (pos.X <= parentGlobalPos.X + this.BorderThinckness && this.ResizeBorderLeft) { m.Result = new IntPtr(HTTRANSPARENT); return; }
if (pos.Y <= parentGlobalPos.Y + this.BorderThinckness && this.ResizeBorderTop) { m.Result = new IntPtr(HTTRANSPARENT); return; }
if (pos.X >= parentGlobalPos.X + this.parent.Width - this.BorderThinckness && this.ResizeBorderRight) { m.Result = new IntPtr(HTTRANSPARENT); return; }
if (pos.Y >= parentGlobalPos.Y + this.parent.Height - this.BorderThinckness && this.ResizeBorderBottom) { m.Result = new IntPtr(HTTRANSPARENT); return; }
base.WndProc(ref m); } } } |
Was is ebenfalls versucht habe, ist das standardmäßige Ausführen der WndProc während der design-time. Funktioniert ebenfalls nicht.
C#-Quelltext
1: 2: 3: 4:
| if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) { base.WndProc(ref m); return; } |