在微软的MSDN网站上有一篇文章:“How To: Send Data Directly to a GDI Printer”,网址是:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162959(v=vs.85).aspx
在这篇文章里,介绍了如何将需要打印的数据直接发送给基于GDI的打印机驱动,并给出了示例程序。使用这篇文章里介绍的方法进行打印,不会弹出“打印”对话框,但是只能直接打印ASCII码中那些可被打印的字符,不能打印中文字符。这篇文章启示我们,可以通过编写程序的方法实现在不弹出“打印”设置对话框的情况下,直接使用默认的打印机进行打印。下面给出一个基于 MFC 的示例程序:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162959(v=vs.85).aspx
在这篇文章里,介绍了如何将需要打印的数据直接发送给基于GDI的打印机驱动,并给出了示例程序。使用这篇文章里介绍的方法进行打印,不会弹出“打印”对话框,但是只能直接打印ASCII码中那些可被打印的字符,不能打印中文字符。这篇文章启示我们,可以通过编写程序的方法实现在不弹出“打印”设置对话框的情况下,直接使用默认的打印机进行打印。下面给出一个基于 MFC 的示例程序:
/**************************************************
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: July 16th, 2016
* Description: demonstrate how to send Chinese character
directly to a default printer in a MFC program
**************************************************/
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <tchar.h>
#include <afxdlgs.h>
#include <Winspool.h>
/**************************************************
*函数名称:PrintData
*功能: 在指定矩形区域范围内打印字符串
*参数:
left[in] 矩形区域左上角的横坐标
top[in] 矩形区域左上角的纵坐标
right[in] 矩形区域右下角的横坐标
bottom[in] 矩形区域右下角的纵坐标
strToBePrinted[in] 要被打印的字符串
*返回值: 无
*备注:
1) 本函数直接调用默认的打印机打印输出字符串,不会弹出“打印”设置对话框;
2) 对于输入参数中的坐标,取值单位都是像素;
3) 本函数能够打印输出中文字符串;
4) 输入参数 strToBePrinted 中可以包含换行符;
5) 在打印时,字符串靠左对齐。
**************************************************/
void PrintData(LONG left, LONG top, LONG right, LONG bottom, LPCTSTR strToBePrinted)
{
// 获取默认的打印机
CPrintDialog dlg(false);
dlg.GetDefaults();
HDC hdcPrinter = dlg.CreatePrinterDC();
if (hdcPrinter == NULL)
{
AfxMessageBox(_T("未检测到默认打印机!"));
}
else
{
CDC dcPrinter;
dcPrinter.Attach(hdcPrinter);
dcPrinter.SetMapMode(MM_LOENGLISH); /* 注意这里的设置 */
DOCINFO docinfo;
memset(&docinfo, 0, sizeof(docinfo));
docinfo.cbSize = sizeof(docinfo);
if (dcPrinter.StartDoc(&docinfo) < 0)
{
AfxMessageBox(_T("打印机初始化失败!"));
}
else
{
CFont font;
font.CreateFont(18,
0,
0,
0,
FW_NORMAL,
0,
0,
0,
DEFAULT_CHARSET,
OUT_CHARACTER_PRECIS,
CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH |FF_DONTCARE,
_T("宋体"));
CFont *pOldFont = dcPrinter.SelectObject(&font);
if (dcPrinter.StartPage() < 0)
{
AfxMessageBox(_T("打印起始页失败!"));
dcPrinter.AbortDoc();
}
else
{
dcPrinter.SetBkMode(TRANSPARENT);
dcPrinter.SetTextColor(RGB(0, 0, 0));
RECT rect = {left, top, right, bottom};
dcPrinter.DrawText(strToBePrinted, &rect, DT_WORDBREAK | DT_LEFT);
dcPrinter.EndPage();
}
dcPrinter.EndDoc();
dcPrinter.SelectObject(pOldFont);
font.DeleteObject();
}
CDC::FromHandle(dcPrinter)->DeleteDC();
}
if (dlg.m_pd.hDevMode)
{
GlobalFree(dlg.m_pd.hDevMode);
}
if (dlg.m_pd.hDevNames)
{
GlobalFree(dlg.m_pd.hDevNames);
}
}
/**************************************************
说明:演示如何调用 PrintData() 进行打印
**************************************************/
int main(void)
{
LONG left, top, right, bottom;
TCHAR strPrinted[256] = {_T("[“打印测试”]\r\n你好,中国!\r\n你好,西安。")};
left = 10;
top = -10; /* 注意这里赋值时要用负数 */
right = 360;
bottom = -280; /* 注意这里赋值时要用负数 */
PrintData(left, top, right, bottom, strPrinted);
return 0;
}
对于这个示例程序,需要说明的地方如下:
1)它是一个简单的控制台应用程序,能够直接打印包含中文的字符串,在打印之前不会弹出“打印”设置对话框;
2)通过使用 MFC 中 CPrintDialog 类的 GetDefaults() 方法,可以获取到默认的打印机信息;
3)为了打印字符串,除了使用 DrawText( ) 函数,还可以使用 TextOut( ) 函数。这里使用 DrawText( ),其优点是可以在待打印的字符串中包含换行符,使用 TextOut( ) 时待打印字符串中不能包含换行符;
4)在编译器的设置中,“字符集”要设为“使用Unicode字符集”。