C++打印机首选项设置

C++打印机首选项设置

前言

最近在开发打印机SDK,之前一直做黑白打印机,后面来了一个彩色打印机,要求彩色文档不但可以打印出彩色纸张,也能打印出黑白纸张;打印机默认是黑白文档打印黑白纸张,彩色文档打印彩色纸张,需要调用windows api来控制。


一、打印机首选项

首先查看打印机是否支持颜色设置(必须先安装打印机驱动,并且正常连接打印机),去电脑查看打印机首选项,【控制面板】->【设备和打印机】->【选中彩色打印机】->【右击选择打印机首选项】->【点击颜色窗口】,如下图所示:
在这里插入图片描述
PS:每一台打印机的首选项界面不同,只要找到颜色设置界面,基本可以通过windows API来控制

二、打印流程

window打印都是右击文件点击打印,使用打印机默认配置进行打印;如果需要自定义打印,打开打印机首选项对话框,在里面可以设置纸张尺寸、纸张来源、纸张类型和单双面打印等等,修改完之后,再次选择文件打印,就会按照修改后的打印机配置进行打印;

C++控制打印机打印的流程和windows打印一样,先通过Windows API来修改打印机首选项里面的配置

代码如下(示例):

#include <windows.h>
#include <string.h>

int SetPrintParams(void)
{
	HANDLE hPrinter = NULL;
	PRINTER_INFO_2* pi2 = NULL;
	DEVMODE* pDevMode = NULL;
	PRINTER_DEFAULTS pd;
	DWORD dwNeeded = 0;

	BOOL bFlag;
	LONG lFlag;

	// 获取默认打印机名称
	CHAR szDevName[MAX_PATH] = "";
	DWORD dwLength = MAX_PATH;
	if (!GetDefaultPrinter(szDevName, &dwLength))
	{
		return 1;
	}

	ZeroMemory(&pd, sizeof(pd));
	pd.DesiredAccess = PRINTER_ALL_ACCESS;
	// 打开打印机
	bFlag = OpenPrinter(szDevName, &hPrinter, &pd);
	if (!bFlag || (hPrinter == NULL))
	{
		return 2;
	}
	// 获取pi2数据结构的尺寸
	bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
	if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
	{
		ClosePrinter(hPrinter);
		hPrinter = NULL;
		return 3;
	}

	pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
	if (pi2 == NULL)
	{
		ClosePrinter(hPrinter);
		hPrinter = NULL;
		return 4;
	}

	// 取得与指定打印机有关的信息PRINTER_INFO_2
	bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
	if (!bFlag)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		hPrinter = NULL;
		return 5;
	}

	// DEVMODE数据结构中包含了有关设备初始化和打印机环境的信息
	if (pi2->pDevMode == NULL)
	{
		// 获取pDevMode数据结构的尺寸
		dwNeeded = DocumentProperties(NULL, hPrinter,
			szDevName,
			NULL, NULL, 0);
		if (dwNeeded <= 0)
		{
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			hPrinter = NULL;
			return 6;
		}

		pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded);
		if (pDevMode == NULL)
		{
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			hPrinter = NULL;
			return 7;
		}

		// 输出打印机设置信息到pDevMode
		lFlag = DocumentProperties(NULL, hPrinter,
			szDevName,
			pDevMode, NULL,
			DM_OUT_BUFFER);
		if (lFlag != IDOK || pDevMode == NULL)
		{
			GlobalFree(pDevMode);
			GlobalFree(pi2);
			ClosePrinter(hPrinter);
			hPrinter = NULL;
			return 8;
		}

		pi2->pDevMode = pDevMode;
	}

	// 指定打印机的出纸匣,每台打印机的纸匣号不一样,我这边是,0自动选择, 1是纸匣1,2是纸匣2
	pi2->pDevMode->dmFields = pi2->pDevMode->dmFields | DM_DEFAULTSOURCE;
	int iBoxID = 0;
	pi2->pDevMode->dmDefaultSource = iBoxID;

	// 打印机使用的纸张尺寸(查找对应系统宏定义: DMPAPER_A4  9)
	pi2->pDevMode->dmFields = pi2->pDevMode->dmFields | DM_PAPERSIZE;
	int iPageSize = DMPAPER_A4;
	pi2->pDevMode->dmPaperSize = iPageSize;

	// 纸张类型,根据不同打印机有不同配置,我这边普通纸张是284
	pi2->pDevMode->dmFields = pi2->pDevMode->dmFields | DM_MEDIATYPE;
	int iMediaType = 284;
	pi2->pDevMode->dmMediaType = iMediaType;

	// 双面打印模式
	pi2->pDevMode->dmFields = pi2->pDevMode->dmFields | DM_DUPLEX;
	int iOffset = pi2->pDevMode->dmSize;
	LPBYTE lpByteDevMode = (LPBYTE)pi2->pDevMode;
	// 是否双面(1单面 / 2双面)
	int iDuplex = 1;
	if (iDuplex == 1)
	{
		pi2->pDevMode->dmDuplex = 1;
		lpByteDevMode[iOffset + 84] = 1;
		lpByteDevMode[iOffset + 86] = 0;
	}
	else if(iDuplex == 2)
	{
		pi2->pDevMode->dmDuplex = 2;
		lpByteDevMode[iOffset + 84] = 2;
		lpByteDevMode[iOffset + 86] = 1;
	}

	// 彩色打印机颜色设置
	pi2->pDevMode->dmFields = pi2->pDevMode->dmFields | DM_COLOR;
	//1单色, 2彩色打印
	int	iColor = 1;
	if (iColor == 1)
	{
		pi2->pDevMode->dmColor = DMCOLOR_MONOCHROME;
	}
	else if (iColor == 2)
	{
		pi2->pDevMode->dmColor = DMCOLOR_COLOR;
	}

	pi2->pSecurityDescriptor = NULL;

	// 将修改后的pDevMode载入打印机驱动程序的新位置
	lFlag = DocumentProperties(NULL, hPrinter,
		szDevName,
		pi2->pDevMode, 
		pi2->pDevMode,
		DM_IN_BUFFER | DM_OUT_BUFFER);
	if (lFlag != IDOK)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
		{
			GlobalFree(pDevMode);
		}
		hPrinter = NULL;
		return 10;
	}

	// 将pi2载入打印机
	bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
	if (!bFlag)
	{
		GlobalFree(pi2);
		ClosePrinter(hPrinter);
		if (pDevMode)
		{
			GlobalFree(pDevMode);
		}
		hPrinter = NULL;
		return 11;
	}
	
	// 使打印机配置修改生效
	SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE,
		0L,
		(LPARAM)(LPCSTR)szDevName,
		SMTO_NORMAL, 1000, NULL);
	
	//关闭打印机释放资源
	if (hPrinter != NULL)
	{
		int iC = ClosePrinter(hPrinter);
		hPrinter = NULL;

		if (pi2 != NULL)
		{
			GlobalFree(pi2);
			pi2 = NULL;
		}

		if (pDevMode != NULL)
		{
			GlobalFree(pDevMode);
			pDevMode = NULL;
		}
	}

	return 0;
}

总结

以上代码就是打印机首选项里面部分参数的配置,实际使用可以通过传参进行控制,我这里都是写死参数,其他参数根据自己需要进行添加,主要是修改pDevMode的属性,附一个pDevMode格式说明,如下:

//PDevMode = _devicemodeW;
//  _devicemodeW = record
//    dmDeviceName: array[0..CCHDEVICENAME - 1] of WideChar; {打印设备名称,唯一值}
//    dmSpecVersion: Word;  {DevMode的版本号}
//    dmDriverVersion: Word;  {打印驱动程序版本号}
//    dmSize: Word; {DevMode结构的字节大小}
//    dmDriverExtra: Word; {dmDriverExtra成员结构的大小}
//    dmFields: DWORD; {DevMode结构中哪些成员已被初始化}
//    dmOrientation: SHORT; {纸张方向;1(纵向)2(横向)}
//    dmPaperSize: SHORT; {纸张大小}
//    dmPaperLength: SHORT; {自定义纸张的高度,PageSize为0或256时有效}
//    dmPaperWidth: SHORT; {自定义纸张的宽度,PageSize为0或256时有效}
//    dmScale: SHORT; {打印输出的缩放系数}
//    dmCopies: SHORT; {打印份数}
//    dmDefaultSource: SHORT; {送纸的默认纸盒}
//    dmPrintQuality: SHORT; {打印机的分辨率;4-高品质 3-中品质 2-低品质 1-草稿}
//    dmColor: SHORT; {打印输出为彩色或是单色;1-彩色 2-单色}
//    dmDuplex: SHORT; {纸张是否为双面打印输出;1-单面 2-水平 3-垂直(需打印支持)}
//    dmYResolution: SHORT; {Y方向分辨率;单位:点}
//    dmTTOption: SHORT; {如何打印TrueType字体}
//    dmCollate: SHORT; {多份时,是否逐份打印}
//    dmFormName: array[0..CCHFORMNAME - 1] of WideChar; {纸张名称}
//    dmLogPixels: Word; {}
//    dmBitsPerPel: DWORD; {显示设备的颜色分辨率;单位:像素}
//    dmPelsWidth: DWORD; {可见设备表面(屏幕或打印机)的宽度}
//    dmPelsHeight: DWORD;  {可见设备表面(屏幕或打印机)的高度}
//    dmDisplayFlags: DWORD; {设备的显示模式}
//    dmDisplayFrequency: DWORD; {显示设备在特定模式下的频率}
//    dmICMMethod: DWORD; {}
//    dmICMIntent: DWORD; {}
//    dmMediaType: DWORD; {}
//    dmDitherType: DWORD; {}
//    dmICCManufacturer: DWORD; {}
//    dmICCModel: DWORD; {}
//    dmPanningWidth: DWORD; {}
//    dmPanningHeight: DWORD; {}

设置完打印机首选项配置之后,就可以调用打印机进行打印了,我用的是Shell打印,这里不讲打印实现

另外,每台打印机首选项里面的属性配置值不一样,参数设置值不能通用,可以在调用函数DocumentProperties(输出打印机设置信息到pDevMode)的时候,通过pDevMode将默认的打印机设置信息记录下来,这个就是打印机首选里面参数;然后修改打印机首选项里面的配置,再通过DocumentProperties获取;反复如此,最终该打印机对应的属性值。

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Li_Zhi_Yao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值