核心内容摘要
P1140 [ICPC 2001 Taejon R] 相似基因
winfrom开发框架源码来看消息循环这个心脏部件。
Application.Run方法里的那坨代码其实是个永动机while (GetMessage(ref msg, IntPtr.Zero, 0,
) { TranslateMessage(ref msg); DispatchMessage(ref msg); }这死循环看着吓人但正是它让窗口能持续响应事件。
有意思的是微软在这里埋了个彩蛋——Application.DoEvents()其实就是手动触发消息处理用不好容易让界面抽风新手慎碰。
控件绘制这块Control类的CreateGraphics方法暗藏玄机public Graphics CreateGraphics() { IntPtr hdc UnsafeNativeMethods.GetDC(new HandleRef(this, Handle)); return Graphics.FromHdcInternal(hdc); }这暴露了GDI的老底每次调用都会创建新Graphics对象。
所以千万别在OnPaint外面乱用这玩意内存泄漏分分钟教你做人。
记得用using包裹或者重写Paint事件才是正解。
winfrom开发框架源码数据绑定方面BindingSource的机制有点意思。
看这段同步代码private void CurrencyManager_CurrentChanged(object sender, EventArgs e) { if (_inCurrentChanged) return; _inCurrentChanged true; // 同步UI和数据的黑魔法 UpdateControls(); _inCurrentChanged false; }这个_inCurrentChanged标志位玩得溜防住了无限递归。
实战中要是自己写双向绑定记得抄这个防呆设计不然改个数值能让界面和后台数据打起来。
再看控件树的处理Control.ControlCollection的Add实现里藏着彩蛋public virtual void Add(Control value) { if (value null) return; if (value.Parent ! null) value.Parent.Controls.Remove(value); // 这里开始排列组合Z序 InnerList.Add(value); value.AssignParent(this._owner); }这解释了为什么同一个控件不能有多个爹。
有意思的是InnerList用ArrayList而非泛型集合估计是.NET
0时代的老代码没改现在看着确实有点考古的味道。
最后给个实战建议处理复杂界面时别被自动生成的Designer.cs文件带沟里。
试着重写控件的布局逻辑protected override void OnLayout(LayoutEventArgs levent) { base.OnLayout(levent); // 在这里玩自定义布局 textBox