65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 GDI+ 打印:一些技巧

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (9投票s)

2002 年 7 月 29 日

2分钟阅读

viewsIcon

167749

downloadIcon

1366

一些关于使用 GDI+ 打印图形的“特殊”技巧

引言

本文给出了一些关于使用 GDI+ 打印图形的提示。 众所周知,打印是 MFC 中最神秘的功能之一(这是我的观点)。 它没有得到很好的(根本没有)记录,事实上,最好的例子可以在 CodeProject 打印部分找到。

由于 GDI+ 是一项新技术,因此在尝试打印时会带来新的问题。

在下文中,我将尝试给出在尝试打印 GDI+ 内容时遇到的一些提示。 我将假设您对打印有一些基本的了解,尤其是您已经阅读了以下文章之一,因此我将不必讨论获得打印机 DC 的工作原理以及这些文章中已有的其他细节,而是侧重于与 GDI+ 相关的问题

在下文中,dc 表示打印机 dc,graphics 表示 GDI+ 图形上下文

    CDC dc;
    Graphics graphics;

设置映射模式

dcgraphics 的映射模式必须一起调整

    dc.SetMapMode(MM_TEXT);
    graphics.SetPageUnit(UnitDocument); 

使用这些设置,每个逻辑单位转换为 1 个设备单位 (MM_TEXT),并且一个设备单位为 1/300 英寸 (UnitDocument)。 因此我们得到 300dpi 打印,很棒。

那么其他 DPI 呢?

哇,我们让它在 300dpi 下工作,但是 600 dpi 呢? 或者 1200?

经过几次反复试验后,我发现我们必须自己做这项脏活,也就是说检查打印机的 dpi 并相应地缩放图形

  1. 获取 dpi 比率 dpiRatio
        CPrintDialog MyPrintDialog;
         ...
         // the dpi of printer is enclosed in DEVMODE structure,
         DEVMODE* pDev=MyPrintDialog.GetDevMode();
        // getting dpi ratio between 300dpi and current printer dpi
        double dpiRatio=300.0/pDev->dmPrintQuality;
        // deallocating memory for pDev
        VERIFY(GlobalUnlock(pDev));
    
  2. 将页面缩放比例设置为 graphics
        graphics.SetPageScale(dpiRatio);
    

那个丑陋的黑客应该可以完成这项工作。 当然,欢迎任何更好的方法 :-)

那么文本呢?

获取字体大小

不幸的是,缩放图形是不够的,在计算字体大小时必须考虑 Dpi 缩放!

这是 Barnhart 文章中 CreateFontSize 的修改。 如您所见,用户必须传递 dpiRatio 以相应地缩放字体

int CreateFontSize(HDC hDC, int points, double dpiRatio)
{
	// This will calculate the font size for the printer that is specified
	// by a point size.
	//
	// if points is:
	//  (-) negative uses height as value for Net Font Height (ie. point size)
	//	(+) positive height is Total Height plus Leading Height!
	ASSERT(hDC);
	
	POINT size;
	int logPixelsY=::GetDeviceCaps(hDC, LOGPIXELSY);
	size.x = size.y = MulDiv(points, logPixelsY, 72);

	// here we scale the font...
	return (float)floor(size.y*dpiRatio);
}

创建用于打印的字体

创建字体时,使用以下单位
Unit fontUnit = m_pGraphics->GetPageUnit();
// if fontUnit is UnitDisplay, then specify UnitPixel, 
// otherwise you'll get a "InvalidParameter" from GDI+
if (fontUnit == UnitDisplay)
fontUnit = UnitPixel;
// classical constructor use, lfHeight is the font height
Font font(&fontFamily, CreateFontSize(hDC, 
          lfHeight, dpiRatio), FontStyleRegular, fontUnit);

致谢

打印部分提供了许多有用的文章

更新历史

11/09/2002修复了在预览模式下使用缩放时文本大小发生变化的问题。 更新了演示项目。
© . All rights reserved.