文章目录一、它演示什么二、怎么用三、一屏总览四、关键接口五、录制-回放 vs 像素擦除六、容易踩的坑七、常见问题排查问题速查表一、它演示什么画板上的图形不是像素而是被录制的绘制命令每画一笔记一条命令控件重绘被盖住又露出、改大小时按序回放 —— 所以没有擦掉某一笔的接口。示例把每条命令另存进一张固定数组它才是可撤销的真相来源撤销 丢掉最后一条 → 清空记录 → 重放剩下的。鼠标事件挂在画板自己mousedown/mousemove/mouseup按下时运行时自动捕获鼠标拖出边界也不断笔直线 / 矩形 / 椭圆在拖动中有橡皮筋预览松手才提交。下面是「录制-回放」模型的核心流程是松手提交用户按下鼠标捕获鼠标并记录起点拖动中写入临时命令 整表重放橡皮筋预览把命令追加进命令表真相来源重放整张画布状态栏更新命令条数撤销丢最后一条 → 清空 → 重放二、怎么用在项目根编译build-app.bat drawpad双击examples\drawpad\drawpad.exe。顶部「工具」下拉选一种直线 / 矩形 / 椭圆 / 文字 / 自由笔点「颜色」色块弹系统取色器「笔宽」数值框调 1…12。在白色画板上按下拖动直线 / 矩形 / 椭圆拖动中就有预览、松手提交文字工具单击一次落一个字自由笔一路划过去逐段提交。「撤销」退掉最后一笔「重做」放回来「清空」全部丢弃状态栏三段分别是当前工具、命令条数、最近一次操作。「导出 PNG」把画板截图存进用户数据目录文件名带时间戳底部终端会记下每一步作图 / 撤销 / 导出。命令行drawpad.exe自动找同名.cgui、drawpad.exe xxx.cgui、--selftest。三、一屏总览控件 id类型干什么cbo_toolcombo工具0 直线 / 1 矩形 / 2 椭圆 / 3 文字 / 4 自由笔cp_inkcolorpicker当前色value0xRRGGBB点它弹系统取色器edt_peneditspin笔宽数值框1…12btn_undo/btn_redo/btn_clearbutton撤销 / 重做 / 清空共用一个回调btn_exportbutton导出 PNGcv_boardcanvas画板本身挂mousedown/mousemove/mouseupterm_logterminal每一步操作记一行sb_mainstatusbar三段当前工具 / 命令条数 / 最近操作四、关键接口画板绘制cg_canvas_clear、cg_canvas_set_color、cg_canvas_set_line_width、cg_canvas_line、cg_canvas_rect、cg_canvas_ellipse、cg_canvas_text鼠标坐标cg_event_x、cg_event_y就是画板内的逻辑像素截图与落盘cg_widget_screenshot、cg_app_data_dir、cg_path_join记录与状态cg_term_write、cg_status_set、cg_status_setf五、录制-回放 vs 像素擦除维度录制-回放本示例像素擦除位图结论撤销粒度按「命令」撤销可精确回退到任意一笔只能整块擦除像素无法还原被覆盖的笔画录制-回放更精细支持逐笔撤销内存占用只存命令参数类型 坐标 颜色 笔宽固定数组上限kMaxOps 4096每帧都要存整张位图画布越大内存越高录制-回放更省内存且占用可预估缩放质量重放时按当前尺寸重新绘制任意缩放都清晰位图缩放会模糊 / 锯齿需额外重采样录制-回放缩放无损质量更高实现复杂度需维护命令表 重放逻辑预览要「临时命令 整表重放」直接改像素实现直观但撤销 / 缩放难做录制-回放略复杂但换来前三个维度的收益两种方案的取舍可以这样看需要逐笔撤销只整块擦除即可画板方案选型撤销粒度要求录制-回放本示例像素擦除位图优点逐笔撤销 / 省内存 / 缩放无损代价命令表 重放逻辑较复杂优点实现直观代价撤销难 / 内存高 / 缩放模糊结论追求精细撤销与质量 → 选录制-回放结论简单场景够用 → 选像素擦除六、容易踩的坑鼠标事件必须挂在画板这个子控件上不能挂窗口级app.events—— 按下 / 移动 / 抬起落在画板上时消息只送给画板父窗口收不到早先挂窗口的写法在真机上按下拖动毫无反应。画板事件里的坐标就是画板内像素不用再减cg_widget_x/cg_widget_y。画板的绘制是录制 → 回放模型没有画一笔但不作数的接口所以拖动预览只能把临时命令写进命令表空槽 整表重放见preview_op。命令表是固定数组上限kMaxOps 4096满了只报一次提示并拒绝起笔自由笔贴着上一个点 2px 以内的移动不记免得几秒见底。画板重绘走双缓冲所以每步重放整张画布的预览不会闪。七、常见问题排查Q1画板无响应按下拖动毫无反应原因鼠标事件挂错了对象挂到了窗口级app.events而不是画板子控件cv_board上。解决把mousedown/mousemove/mouseup全部挂到cv_board上按下时运行时自动捕获鼠标拖出边界也不断笔。Q2拖动预览闪烁原因画板重绘没有走双缓冲或预览时直接改像素导致整块重绘。解决确认画板重绘走双缓冲预览用「临时命令写进命令表空槽 整表重放」的方式避免逐像素直接改。Q3命令表满了画不进去原因命令表是固定数组上限kMaxOps 4096画满后拒绝起笔。解决先「清空」或「撤销」释放空间自由笔贴着上一个点 2px 以内的移动不记可有效延缓命令表见底。Q4导出 PNG 失败原因用户数据目录不可写或文件名带非法字符。解决确认cg_app_data_dir返回的目录存在且可写导出文件名带时间戳若仍失败请检查磁盘空间与目录权限。Q5文字工具单击落字位置偏移原因文字工具单击落字时坐标换算用了窗口坐标而不是画板内坐标或没考虑画板在窗口内的偏移。解决确认落字坐标直接用cg_event_x/cg_event_y就是画板内逻辑像素不要再减cg_widget_x/cg_widget_y。问题速查表问题现象原因解决方案Q1 画板无响应按下拖动毫无反应鼠标事件挂到了窗口级app.events而非画板子控件cv_board把mousedown/mousemove/mouseup全部挂到cv_board上Q2 预览闪烁拖动中画布闪烁画板重绘未走双缓冲或预览时直接改像素重绘走双缓冲预览用「临时命令 整表重放」Q3 命令表满画不进去拒绝起笔命令表固定数组上限kMaxOps 4096已满先「清空」或「撤销」释放空间自由笔 2px 内移动不记Q4 导出 PNG 失败导出报错或文件未生成用户数据目录不可写或文件名带非法字符确认cg_app_data_dir目录存在且可写检查磁盘空间与权限Q5 文字落字偏移单击落字位置不对坐标用了窗口坐标或没考虑画板偏移直接用cg_event_x/cg_event_y不再减cg_widget_x/cg_widget_y