CMatrixPrinter类:一种打印矩阵的解决方案

在处理数据时,经常需要将数据以表格的形式整齐地排列在行和列中,以便小数点能够对齐在一列中。尽管GDI API没有内置的文本右对齐功能,但可以通过巧妙地使用前导空白来模拟,不过这只适用于固定宽度的字体。一旦使用可变宽度的字体,精心设计的格式就会变得混乱。本文介绍的CMatrixPrinter类旨在解决这个问题。它是一个包装类,包装了一个HDC打印机设备上下文句柄。它具有设置打印矩阵的成员函数,以及输出文本到特定行和列的函数,无论是左对齐还是右对齐。几乎可以使用任何字体,因为几乎所有的字体都能很好地工作。

代码使用

CMatrixPrinter类提供了四个构造函数,它们要么创建打印机设备上下文,要么包装提供的设备上下文。然后调用StartDoc()和StartPage() API,并设置文本背景模式为TRANSPARENT。

CMatrixPrinter(const TCHAR * DocName, LPDEVNAMES pDevNames, LPDEVMODE pDevMode = NULL); CMatrixPrinter(const TCHAR * DocName, const TCHAR * Device, const TCHAR * Driver = _T("WINSPOOL"), LPDEVMODE pDevMode = NULL); CMatrixPrinter(const TCHAR * DocName, HDC hDC); CMatrixPrinter(DOCINFO & DocInfo, HDC hDC);

构造函数参数包括文档文件名、打印机设备名称、打印提供程序名称(默认为"WINSPOOL")和设备上下文句柄。

~CMatrixPrinter(void);

析构函数调用EndPage()和EndDoc() API,并在构造函数中创建设备上下文时调用DeleteDC()。

int SetRows(int Rows, const TCHAR * FontFaceName = NULL); int SetColumns(int Columns, const TCHAR * FontFaceName = NULL);

这两个函数设置矩阵。它们尝试设置指定的行数或列数,但由于字体的创建方式,可能不会完全精确。SetRows计算所需的列数,SetColumns计算行数。使用CMatrixPrinter::GetMatrixSize()获取确切的行数和列数。

int PlaceTextL(const TCHAR * Text, int Row, int LeftColumn); int PlaceTextR(const TCHAR * Text, int Row, int RightColumn);

使用这些函数在矩阵上放置文本。文本将在指定的列上左对齐或右对齐。

int NextPage(void);

调用EndPage()和StartPage() API以将打印推进到下一页。

int GetPrintJobID(void); int GetPageNumber(void); SIZE GetMatrixSize(void); RECT GetGlyphRect(int Row, int Column);

这些函数用于检索打印作业标识符、当前页码、打印矩阵的尺寸以及矩阵中字形矩形的位置和大小。

operator HDC(void);

使用此运算符检索包装的打印机设备上下文句柄。

示例代码

int _tmain(int argc, _TCHAR* argv[]) { // 设置并调用打印对话框 PRINTDLG pd = {0}; pd.lStructSize = sizeof(PRINTDLG); pd.Flags |= PD_RETURNDC; PrintDlg(&pd); // 将打印机对话框返回的设备上下文包装到CMatrixPrinter类对象中 CMatrixPrinter mp(_T("Matrix Printer Test"), pd.hDC); // 使用可变宽度字体设置矩阵 mp.SetRows(60, _T("Pristina")); // 绘制演示网格线以突出显示矩阵 HPEN Pen = CreatePen(PS_DOT, 1, RGB(128, 128, 128)); HPEN OldPen = (HPEN)SelectObject(mp, Pen); for (int x = 0; x < mp.GetMatrixSize().cx; ++x) { for (int y = 0; y < mp.GetMatrixSize().cy; ++y) { RECT rc = mp.GetGlyphRect(y, x); Rectangle(mp, rc.left, rc.top, rc.right, rc.bottom); } } SelectObject(mp, OldPen); // 首先在第一行放置正常文本,以显示字体在正常绘制时的外观 RECT rc = mp.GetGlyphRect(1, 1); TextOut(mp, rc.left, rc.top, Text, _tcslen(Text)); // 然后在矩阵的第二行放置相同的文本,以显示现在的外观 mp.PlaceTextL(Text, 2, 1); // 现在在第20列放置一些数字,右对齐 for (int i = 0; i < _countof(Numbers); ++i) { TextColour TC(mp, Numbers[i] < 0.0 ? RGB(255, 0, 0) : RGB(0, 0, 255)); mp.PlaceTextR(pja::CBuilder<>(_T("${0}"), Fixed(Numbers[i], 2)).c_str(), i + 4, 20); } return 0; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485