使用MFC打印指定字体文本并在下方打印从文件加载的位图
MFC打印需求调整方案
核心调整逻辑
- 拆分文本绘制与位图加载逻辑,不再将文本绘制到位图素材上
- 打印时先向打印DC输出指定字体的文本,提前计算文本占据的高度,再在文本底部位置绘制加载的位图
- 修复原有代码的GDI资源泄漏问题
修改后完整可运行代码
// 创建指定字体 CFont j1; j1.CreateFont( 120, // nHeight 120, // nWidth 0, // nEscapement 0, // nOrientation FW_NORMAL, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut RUSSIAN_CHARSET, // nCharSet OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T("Arial")); // lpszFacename // 加载本地位图,不要和文本绘制混用位图对象 CBitmap bmp; if (!bmp.Attach(::LoadImage( ::GetModuleHandle(NULL), _T("D:\\UPM\\BMP\\Login.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE))) { AfxMessageBox(_T("Error loading bitmap!")); j1.DeleteObject(); // 异常退出前释放字体资源 return; } BITMAP bm; bmp.GetBitmap(&bm); // 弹出打印对话框 CPrintDialog pd(false); if (pd.DoModal() == IDOK) { CDC PrintDC; HDC hdc = pd.GetPrinterDC(); PrintDC.Attach(hdc); DOCINFO docinfo = { sizeof(docinfo) }; docinfo.lpszDocName = _T("Print test"); PrintDC.StartDoc(&docinfo); PrintDC.StartPage(); // 第一步:绘制文本,先计算文本所需的矩形高度 CFont* pOldFont = PrintDC.SelectObject(&j1); PrintDC.SetTextColor(RGB(255, 0, 0)); CRect textRect(0, 0, GetDeviceCaps(hdc, PHYSICALWIDTH), 0); // 宽度取打印纸可打印宽度 // 先计算文本所需高度,不实际绘制 PrintDC.DrawText(_T("qwerty\nrtrtrt\nttttt"), &textRect, DT_WORDBREAK | DT_EXPANDTABS | DT_CENTER | DT_CALCRECT); // 调整文本矩形到合适的左上边距,这里默认留20像素边距,可自行调整 textRect.OffsetRect(20, 20); // 实际绘制文本 PrintDC.DrawText(_T("qwerty\nrtrtrt\nttttt"), &textRect, DT_WORDBREAK | DT_EXPANDTABS | DT_CENTER); // 第二步:在文本底部绘制位图,位图左上角Y坐标为文本矩形的底部+10像素间距,可自行调整 int bmpX = 20; // 位图左边距和文本对齐 int bmpY = textRect.bottom + 10; // 创建兼容内存DC绘制位图 CDC memdc; memdc.CreateCompatibleDC(&PrintDC); CBitmap* pOldBmp = memdc.SelectObject(&bmp); PrintDC.BitBlt(bmpX, bmpY, bm.bmWidth, bm.bmHeight, &memdc, 0, 0, SRCCOPY); // 资源回收 memdc.SelectObject(pOldBmp); memdc.DeleteDC(); PrintDC.SelectObject(pOldFont); PrintDC.EndPage(); PrintDC.EndDoc(); PrintDC.DeleteDC(); } // 全局资源回收 bmp.DeleteObject(); j1.DeleteObject();
可选优化点
- 打印机DPI远高于屏幕DPI,直接使用像素值绘制的内容会很小,可以通过
GetDeviceCaps获取打印机DPI,按屏幕DPI比例缩放字体大小、坐标值,匹配预期打印尺寸 - 可自行调整文本边距、文本和位图的间距,适配不同打印纸尺寸
内容的提问来源于stack exchange,提问作者Сергей Соколов
相关产品推荐
相关产品推荐

