如何消除C++/WinRT中使用GDI打印Bitmap时的细黑边?
打印Bitmap出现细黑边的原因及解决方法
原因分析
Rectangle函数的绘制边界特性:
Rectangle(hdc_bitmap, 0, 0, width, height)的绘制逻辑是右边界和下边界独占——实际填充的区域仅到(width-1, height-1),最右侧一列和最底部一行像素未被白色画刷覆盖,保留了Bitmap创建时的默认黑色,最终打印时呈现为细黑边。打印机可打印区域的潜在影响:
GetDeviceCaps获取的HORZRES/VERTRES是整张纸的像素尺寸,但绝大多数打印机存在不可打印边距。直接按全纸尺寸绘制打印,部分边缘内容可能被打印机裁剪,或驱动自动调整时产生黑边。
解决方法
方法1:替换Rectangle为FillRect/PatBlt(彻底解决边界未填充问题)
放弃Rectangle,改用能完整填充指定区域的函数:
- 使用
FillRect:
RECT rect = {0, 0, width, height}; FillRect(hdc_bitmap, &rect, hbrush);
- 或使用
PatBlt:
PatBlt(hdc_bitmap, 0, 0, width, height, PATCOPY);
这两个函数会完整覆盖0到width、0到height的所有像素,不会留下未填充边缘。
方法2:修正Rectangle的参数
若坚持使用Rectangle,需将右、下边界各加1,确保覆盖全部像素:
Rectangle(hdc_bitmap, 0, 0, width + 1, height + 1);
方法3:适配打印机可打印区域(避免裁剪黑边)
获取打印机实际可打印的尺寸与偏移,调整绘制目标:
// 获取可打印区域的偏移和有效尺寸 int printOffsetX = GetDeviceCaps(hdc_printer, PHYSICALOFFSETX); int printOffsetY = GetDeviceCaps(hdc_printer, PHYSICALOFFSETY); int printWidth = GetDeviceCaps(hdc_printer, PHYSICALWIDTH) - 2 * printOffsetX; int printHeight = GetDeviceCaps(hdc_printer, PHYSICALHEIGHT) - 2 * printOffsetY; // 创建适配可打印区域的Bitmap HBITMAP bitmap = CreateBitmap(printWidth, printHeight, 1, 32, NULL); // 绘制时偏移到可打印区域起点 BitBlt(hdc_printer, printOffsetX, printOffsetY, printWidth, printHeight, hdc_bitmap, 0, 0, SRCCOPY);
额外注意事项
- 操作GDI对象时必须保存旧对象并恢复,避免资源泄漏:
HBRUSH oldBrush = (HBRUSH)SelectObject(hdc_bitmap, hbrush); // 执行绘制操作 SelectObject(hdc_bitmap, oldBrush); DeleteObject(hbrush);
- 确保
hdc_bitmap正确关联创建的bitmap,代码中注释的SelectObject(hdc_bitmap, bitmap)需要实际执行,否则绘制目标并非预期Bitmap。
内容的提问来源于stack exchange,提问作者Shyam Butani
相关产品推荐
相关产品推荐

