自定义图形控件(二):把控件做成 IncGUI 库
一、上篇回顾与本文目标
上篇讲了标准控件体系与事件路由。本篇更进一步:从 CControl 继承,自建一个能画、能点、能暴露属性的自定义控件。目标不是炫技,而是把'标准控件做不到的显示'变成可复用组件。
二、从 CControl 继承:必须重写的方法
自建控件要继承 CControl,至少重写构造(设尺寸)、绘制入口、事件处理。CControl 已经把坐标、可见性、父控件管好了,你只补'这个控件长什么样、怎么响应'。
三、绘制:OnDraw 与 Canvas 配合
绘制逻辑写在控件的绘制方法里,用 Canvas 画线、矩形、文字。注意只画自己这一块区域,别越界覆盖兄弟控件;图表缩放或数据变化时,由父窗口触发重绘。
四、事件:鼠标与键盘怎么接
控件在父窗口的事件分发中按自己的 ID 收到鼠标/键盘消息。你在处理函数里判断点击位置是否落在控件矩形内,再决定高亮、按下、选中等状态。命中检测用'点是否在矩形内'即可。
五、属性与方法:对外暴露什么
好的自定义控件只暴露必要的属性(如数值、颜色、是否启用)和方法(如 SetValue/GetValue/Redraw)。内部状态私有,外部通过方法改,避免被随意改坏。这点和上篇类图思想一致。
- 暴露:当前值、颜色、启用状态、重绘方法。
- 私有:Canvas 句柄、内部命中区域、临时缓冲。
- 禁止:外部直接改内部绘制缓冲。
六、一个最小可运行示例
以'带数值显示的圆形按钮'为例:继承 CControl,构造里定半径;绘制时画圆+居中数值;点击命中检测判断点到圆心距离≤半径;SetValue 改数值后触发 Redraw。几十行就能跑起来,是上手自定义控件的最佳练手。
七、调试与常见坑
最常踩的坑:重绘没触发(忘了调父窗口 Redraw 或没在 OnChartEvent 转发)、坐标没换算图表缩放、命中区域和绘制区域不一致。逐一打印状态就能定位。
八、最小示例的伪代码走读
圆形按钮的绘制方法里:先按背景色画圆,再在圆心用 Canvas 写当前数值;事件处理里计算“点到圆心距离是否 ≤ 半径”判定命中,命中则切到按下状态并 Redraw。SetValue 改数值后同样触发 Redraw。整条链路就是“构造定尺寸 → 绘制画自己 → 事件做命中 → 改值就重绘”,几十行即可跑通。
九、复用与扩展
- 自定义控件内部可组合标准控件(如 CButton),逐步替换做不到的部分。
- 把控件做成容器 Add 子控件,直接复用上篇的事件路由。
- 对外接口保持稳定,内部绘制怎么改都不影响调用方。
- 多个相似控件抽公共基类,减少重复代码。
十、小结
自建控件 = 继承 CControl + 重写绘制与事件 + 只暴露必要属性方法。绘制交给 Canvas 并守好自己的区域,事件靠'点是否在矩形/圆内'做命中检测,状态变更后触发重绘。把它当成上篇类图思想的落地:内部状态私有、对外只给干净接口,自定义显示就能稳定复用。