零GDI绘图如何实现打印:TinyRetroPad的EM_FORMATRANGE分页渲染原理详解
【免费下载链接】TinyRetroPad项目地址https://gitcode.com/gh_mirrors/ti/TinyRetroPad点击查看免费下载TinyRetroPad 是一款仅约 2.5 KB 的 Notepad 风格 Windows 文本编辑器完全用 x86 汇编编写。它的打印功能没有一行自绘 GDI 文字的代码——整个分页渲染 打印流程都交给 RICHEDIT 控件的一条EM_FORMATRANGE消息完成。本文带你拆解 trpad.asm 中PrintDoc函数的实现原理看懂零GDI绘图的打印是怎么做到的。为什么说它是零GDI绘图打开源码可以看到一个有意思的细节trpad.asm 中gdi32.inc被直接注释掉了官方解释是编辑器不使用 GDIRich Edit 的字体通过EM_SETCHARFORMAT设置无需 GDI 导入。换句话说✅ 屏幕上显示文字RICHEDIT 控件自己画✅ 打印到纸上RICHEDIT 通过EM_FORMATRANGE自己画❌ 自己调用TextOut/SetTextColor之类的 GDI 函数一次都没有这就是本文的核心把渲染这件事整体委托给控件程序只负责指挥流程。EM_FORMATRANGE一条消息完成分页渲染EM_FORMATRANGE是 RICHEDIT 的私有消息WM_USER57见 trpad.asm。它的协议非常巧妙你把一个打印机 DC设备上下文和一个FORMATRANGE 结构体发给控件控件按页面大小把指定字符范围的文字排版渲染到这个 DC 上返回值 这一页用掉了多少字符后的位置也就是下一页的起点程序只需要拿这个返回值做循环就能一页一页打完整篇文档——这就是分页渲染原理的全部秘密。页宽页高是怎么算的Rich Edit 内部使用twips1/1440 英寸作为排版单位。TinyRetroPad 用GetDeviceCaps查询打印机 DC 的四项指标trpad.asm| 查询项 | 含义 | | - | - | |HORZRES/VERTRES| 纸张宽/高设备单位 | |LOGPIXELSX/LOGPIXELSY| 每英寸像素密度 |然后做一条乘法除法页面宽度(twips) HORZRES × 1440 ÷ LOGPIXELSX高度同理。这样无论用户选 A4 还是 Letter、打印机 DPI 是多少页面尺寸都能自动换算正确。PrintDoc 完整流程拆解菜单 File → Print 触发后PrintDoctrpad.asm按以下 6 步走完整个打印任务第1步PrintDlgA 拿到打印机 DC调用系统打印对话框并带上PD_RETURNDC标志——用户点确定后PRINTDLGA结构的hDC字段里直接装好了一个可用打印机 DC省去了手动创建逻辑 DC/物理 DC 的繁琐代码。第2步StartDocA 声明打印任务开始填充DOCINFOA文档名后调用StartDocA告诉打印 spooler一份新文档要来了。第3步准备 FORMATRANGE 结构体这是分页渲染的配置核心trpad.asmhdc/hdcTarget都填打印机 DCrc/rcPage上一步换算出的 twips 页面尺寸chrg.cpMin 0、chrg.cpMax 全文长度渲染范围是整篇文档第4步StartPage → EM_FORMATRANGE → EndPage 循环主循环trpad.asm每轮做三件事StartPage声明新一页开始向控件发送EM_FORMATRANGE让它把cpMin..cpMax的文字排进当前页EndPage本页结束第5步用返回值驱动翻页EM_FORMATRANGE返回的下一页起点写回fmt.chrg.cpMin与全文长度比较——只要没打完整篇就继续循环。整个分页算法不到 5 条指令。第6步清理资源文档全部输出后再发一次长度为 0 的EM_FORMATRANGE用于刷新控件内部的格式化缓存然后EndDoc结束任务、DeleteDC释放 DC。如何体验这个打印功能菜单File → Print菜单 ID 为IDM_FILE_PRINTtrpad.asm由WndProc中的命令分发路由到PrintDoc菜单File → Page Setup调用PageSetupDlgA公共对话框调整纸张与页边距trpad.asm值得一提的是这套完整打印能力含打印对话框、分页循环、资源管理在这个以字节数论英雄的項目里只花费了固定的 2476 字节基线增长日志见 trpad.asm堪称极小体积下最便宜的打印方案。总结给新手的最短实践路径| 环节 | TinyRetroPad 的做法 | 复用要点 | | - | - | - | | 拿打印机 DC |PrintDlgAPD_RETURNDC| 对话框替你建好 DC | | 页面尺寸 |GetDeviceCaps换算 twips | 一次乘法除法适配任意纸张 | | 排版渲染 |EM_FORMATRANGE| 控件渲染零 GDI 代码 | | 分页驱动 | 用返回值更新cpMin| 一个 while 循环搞定 |如果你正在写一个小而全的 Windows 文本编辑器TinyRetroPad 给出的答案很清晰能不写 GDI 就不写 GDI让 RICHEDIT 替你排版分页。完整实现可对照 trpad.asm 阅读背景资料见 README.md。赞分享【免费下载链接】TinyRetroPad项目地址https://gitcode.com/gh_mirrors/ti/TinyRetroPad点击查看免费下载相关推荐Makepad图形渲染原理从2D绘图到3D渲染的技术实现Makepad图形渲染原理从2D绘图到3D渲染的技术实现 Makepad是一个基于Rust语言的创意软件开发平台它通过创新的图形渲染技术实现了跨平台的2D和前端UI组件3D渲染跨平台游戏开发addLegend.js实现原理图表图例的手绘风格渲染技术addLegend.js实现原理图表图例的手绘风格渲染技术 图表图例是数据可视化中连接视觉元素与数据含义的关键桥梁。在xkcd风格的手绘图表库中 addLe数据可视化前端UI组件gte-micro-openmind常见问题解答解决使用中的10个难题gte micro openmind常见问题解答解决使用中的10个难题 gte micro openmind是一款高效的文本嵌入模型在使用过程中可能会遇到各创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考