Entwickler-Ecke
WinForms - Controls nicht auswählbar beim Überschreiben der WndProc
Kasko - Do 08.07.21 14:19
Titel: Controls nicht auswählbar beim Überschreiben der WndProc
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:
C#-Quelltext
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; } |
Th69 - Do 08.07.21 16:37
Da fallen mir nur 2 Möglichkeiten zum Finden des Problems ein:
1. Eine zweite VS-Instanz öffnen, deine Solution laden + dich an den ersten VS-Prozess hängen und deinen Code debuggen (Haltepunkte vorher passend setzen).
2. Deinen Code stückweise reduzieren (auskommentieren), bis du die fehlerhafte Codestelle gefunden hast.
PS: Die Frage ist hier schon richtig, da es ja um eine von dir erstellte WinForms-Klasse geht.
Ralf Jansen - Do 08.07.21 19:54
Habs mal gerade ausprobiert und konnte kein Problem feststellen. Musste nur die Teile die sich auf FormDragControl beziehen auskommentieren.
Der Designer verhält sich bei mir nicht anders egal ob ich von Form oder dieser BorderlessResizableForm ableite.
Kasko - Do 08.07.21 20:38
Hab das Problem gefunden. Es ist die
WndProc des
BorderWndProcFilters. Ich weiß jedoch nicht, ob die Position der Message oder die Bounds der Control das Problem sind - ist jedoch nicht von Bedeutung. Zudem ist
LicenseManager.UsageMode zum Zeitpunkt des Aufrufes der Filter-WndProc nicht auf
Designtime gesetzt, wodurch der Fehler auch nach dem Versuch die Filterung auf die Runtime zu begrenzen auftrat. Ein einfaches Forwarden der
protected Property
DesignMode über eine weitere
internal Property hat das Problem gelöst.
Jedoch ist mir schleierhaft wie es bei dir @Ralf Jansen einwandfrei funktionieren konnte.
Moderiert von Th69: C#-Tags hinzugefügt
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!