You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hook EndDoc调用GDI LineTo画线错误生成新页的解决方法

问题根因

你现在的实现把线条画到末尾新增页面,核心问题是Hook的函数触发时机完全错误:

  • EndDoc是整个打印作业所有页面绘制、提交完成后才执行的最终收尾接口,代码走到EndDoc时,PDF虚拟打印驱动已经把所有已生成页面的内容写入PDF流,此时再调用LineTo这类GDI绘图接口,驱动会判定你要追加新的绘制内容,自动创建空白页承载这部分绘图,根本不可能把线条画到已经提交完成的原有页面上。
实现方案

要在所有现有页面上画线且不新增页面,按以下逻辑调整即可:

  • 把Hook目标从EndDoc换成EndPage:这个接口是单页级别的收尾函数,每打印完一页内容、提交当前页之前就会触发一次,整个打印流程里有多少页就会触发多少次。此时当前页的HDC上下文还处于可绘制状态,在调用原始EndPage接口前执行画线逻辑,线条会直接落在当前页上,完全不会触发新页面创建。
  • 补上GDI资源回收逻辑:你原来的代码创建画笔后没有还原DC原有对象、也没有删除自定义画笔,会造成GDI资源泄漏,打印任务多了会耗尽系统GDI资源,导致绘图、打印功能异常。
参考实现代码
// Hook EndPage 而非 EndDoc
int StopPrint::hookEndPage(HDC hdc)
{
    // 创建实线画笔
    HPEN hLinePen = CreatePen(PS_SOLID, 1, BLACK_PEN);
    // 将自定义画笔选入DC,保存DC原有画笔对象
    HGDIOBJ hOldPen = SelectObject(hdc, hLinePen);

    // 执行画线逻辑,坐标可根据实际业务需求调整
    MoveToEx(hdc, 500, 500, NULL);
    LineTo(hdc, 2000, 2000);

    // 还原DC原有对象
    SelectObject(hdc, hOldPen);
    // 释放自定义画笔资源,避免泄漏
    DeleteObject(hLinePen);

    // 调用原始EndPage接口提交当前页面
    return getOriginalEndPageFunc()(hdc);
}

额外提示:如果要画固定位置的线条(比如页眉线、作业行线、页脚分割线),建议提前通过GetDeviceCaps接口获取当前打印DC的水平/垂直分辨率、可打印区域尺寸,按比例换算绘图坐标,避免不同纸张尺寸、不同打印DPI下线条位置错位。

内容的提问来源于stack exchange,提问作者Mohammadreza Hojatoleslami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:45:35