打印API

Posted 小米渣的逆袭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打印API相关的知识,希望对你有一定的参考价值。

int testPrint()
{
	PRINTDLG printInfo = { 0 };
	printInfo.lStructSize = sizeof(printInfo);
	printInfo.Flags = PD_RETURNDC;
	//PD_RETURNDEFAULT 意味着直接返回当前系统默认的打印机设置,若没有这个标识,则会弹出对话框让用户自己选择
	//PD_RETURNDC 意味着返回的是dc而不是ic(information context)
	//PD_ALLPAGES 指定“全部”单选钮在初始时被选中(缺省标志)
	//对于错误的时候,若需要知道更多的错误消息,请执行CommDlgError来查看返回值

	//PrintDlg目的是获取当前系统设置的默认打印机相关信息,供后面使用
	//if (!PrintDlg(&printInfo))
	{
		//printInfo.Flags = 0;	//清除标志,然后执行将会弹出对话框让用户选择打印机
		if (!PrintDlg(&printInfo))
		{
			printf("没有选择打印机。\\n");
			return 0;
		}
	}

	//获取打印的时候的dc,然后往这个dc上绘图就是打印出来的样子了
	HDC hPrintDC = printInfo.hDC;
	if (hPrintDC == NULL)
	{
		return 0;
	}

	锁定全局对象,获取对象指针。 devmode是有关设备初始化和打印机环境的信息
	//DEVMODE* devMode = (DEVMODE*)GlobalLock(printInfo.hDevMode);
	//if (devMode == 0)
	//{
	//	printf("获取打印机设置时发生了错误.\\n");
	//	return 0;
	//}

	//devMode->dmPaperSize = DMPAPER_A4;				//打印机纸张设置为A4。
	//devMode->dmOrientation = DMORIENT_PORTRAIT;		//打印方向设置成纵向打印
	//												//DMORIENT_LANDSCAPE 是横向打印
	//												//对打印方向的设置,会影响hPrintDC的大小,假设宽度为1024,高度为300
	//												//则在横向打印的时候dc大小会是宽1024 * 高300
	//												//而纵向打印的时候dc大小会是宽300 * 高1024

	//int printQuality = devMode->dmPrintQuality;			//获取打印机的打印质量
	//													//devMode->dmPrintQuality = DMRES_MEDIUM;
	//													//设置打印质量的,因为像素被打印到纸上的时候是有做转换的
	//													//单位是dpi,意为像素每英寸(dots per inch)。就是一英寸的纸张上
	//													//打印多少个像素点,意味着这个质量越高,打印结果越精细,越低,越粗糙
	//													//设置的质量可以是具体数值,也可以是宏DMRES_MEDIUM
	//													//一般我们选择300,或者600,DMRES_MEDIUM = 600dpi

	//													//应用我们修改过后的设置.
	//ResetDC(hPrintDC, devMode);

	解锁全局对象,对应GlobalLock
	//GlobalUnlock(printInfo.hDevMode);

	//设置绘图模式,以保证绘图可以不失真的绘制上去,因为StretchDIBits函数要求设置这个才能够不是失真的绘图
	//当你用StretchDIBits绘图往窗口显示的时候就会发现,24位图,若没有这个设置,是会失真的
	//SetStretchBltMode(hPrintDC, HALFTONE);
	

	//设置打印时候的字体
	LOGFONT lf;
	lf.lfHeight = -600 * 1 / 2.54;
	//打印出来的字像素高度有n个,注意是像素高度,打印到纸上的时候是需要将
	//像素转换成实际尺寸单位,比如你需要在纸上打印高度为1cm的字,当你打印质量为600dpi的时候
	//这里就设置为 -236, -600dpi * 1cm / 2.54 = -236pix
	lf.lfWidth = 0;
	lf.lfEscapement = 0;
	lf.lfOrientation = 0;
	lf.lfWeight = 5;		//这里设置字体重量,意味着字体的厚度
	lf.lfItalic = false;	//斜体
	lf.lfUnderline = false;	//下划线
	lf.lfStrikeOut = 0;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfOutPrecision = 0;
	lf.lfClipPrecision = 0;
	lf.lfQuality = PROOF_QUALITY;
	lf.lfPitchAndFamily = 0;
	wcscpy_s(lf.lfFaceName, L"宋体");	//使用宋体进行打印

									//实际上这一步并不是必须的,因为默认打印机设置已经配置好了,这里只是我们自己固定好字体
	HFONT hUseFont = CreateFontIndirect(&lf);					//创建字体
	HFONT hOldFont = (HFONT)SelectObject(hPrintDC, hUseFont);	//选用创建的字体

																//获取dc的大小,实际上还有一种HORZRES和VERTRES就是宽度和高度,但是我查得到的结果说计算下来准确的
																//HORZSIZE 是Horizontal size in millimeters,页面宽度(水平),单位毫米mm
																//VERTSIZE 是Vertical size in millimeters,页面高度(垂直),单位毫米mm
																//LOGPIXELSX 是Logical pixels/inch in X,x方向的逻辑像素每英寸.单位 pix / inch,像素每英寸
																//LOGPIXELSY 是Logical pixels/inch in Y,y方向的逻辑像素每英寸.单位 pix / inch,像素每英寸
																//不用管逻辑是个什么东西,不理会他,知道单位是pix / inch就行了
																//1 inch = 2.54 cm,所以这里是 mm / 25.4 * pix / inch,得到的结果就是dc大小像素数为单位
	int dc_page_width = GetDeviceCaps(hPrintDC, HORZSIZE) / 25.4 * GetDeviceCaps(hPrintDC, LOGPIXELSX);
	int dc_page_height = GetDeviceCaps(hPrintDC, VERTSIZE) / 25.4 * GetDeviceCaps(hPrintDC, LOGPIXELSY);
	//设定文字和图像绘制的区域
	RECT rcText = { 0, 30, dc_page_width, 300 };
	RECT rcImage = { 30, 300,399, 400 };
	//好了,可以开始打印了
	DOCINFO doc_info = { sizeof(DOCINFO), L"测试打印机" };
	//cbSize
	//结构体的字节大小
	//lpszDocName
	//指明文档名的字符串指针,该字符串以null为尾。
	//lpszOutput
	//指明输出文件的名称的字符串指针,该字符串以null为尾。如果指针为null,那么输出将会发送至某个设备,该设备将由传递至 StartDoc 函数的‘设备上下文句柄’HDC来指明。
	//lpszDatatype
	//指针指向代表某种数据类型的字符串,而数据用于记录打印工作,该字符串以null为尾。合法值可通过调用函数 EnumPrintProcessorDatatypes 可得到,亦可为 NULL。
	//fwType
	//指明打印工作的其它信息。可为0或者以下值之一:
	//DI_APPBANDING
	//DI_ROPS_READ_DESTINATION

	//开始一个档案,打印的时候是按照档案来区分的,返回作业编号(大于0的为正常)
	int doc_idd = StartDoc(hPrintDC, &doc_info);
	if (doc_idd <= 0)
	{
		printf("StartDoc 错误,错误代码:%d\\n", GetLastError());
		goto last_code;
	}
	printf("作业编号:%d\\n", doc_idd);

	//开始一个打印页面,大于等于0为正确
	if (StartPage(hPrintDC) < 0)
	{
		printf("StartPage 错误\\n");
		AbortDoc(hPrintDC);	//结束doc打印
		goto last_code;
	}

	//写下文字
	SYSTEMTIME time;
	GetLocalTime(&time);
	WCHAR buf[1000] = { 0 };
	wsprintf(buf, L"打印时间:%02d%02d%02d", time.wHour, time.wMinute, time.wSecond);
	DrawText(hPrintDC, buf, -1, &rcText, DT_VCENTER | DT_SINGLELINE | DT_CENTER);
	//结束这一页,其实可以循环的startpage、endpage,这样在一个文档中进行多个页面的打印
	EndPage(hPrintDC);
	EndDoc(hPrintDC);
	printf("打印顺利完成了. o(∩_∩)o \\n");

last_code:
	//选取旧的字体
	SelectObject(hPrintDC, hOldFont);
	//删除gdi对象,释放内存
	DeleteObject(hUseFont);
	return 0;
}


参考文档

 打印效果

 

以上是关于打印API的主要内容,如果未能解决你的问题,请参考以下文章

php header在浏览器上打印完整的html代码

onActivityResult 未在 Android API 23 的片段上调用

数组和适配器不能调用虚空片段

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

webstorm代码片段的创建

导航到另一个片段时触发 API 调用