1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| PrintDeviceInfo CPrintDemoDlg::GetDeviceInfo(CDC &printerDC) { PrintDeviceInfo info;
// 获取屏幕信息 HDC screenHDC = ::GetDC(NULL); CDC* screenDC = CDC::FromHandle(screenHDC);
// 获取屏幕的像素数(分辨率) info.ScreenPixelX = screenDC->GetDeviceCaps(HORZRES); info.ScreenPixelY = screenDC->GetDeviceCaps(VERTRES);
// 获取屏幕的PPI info.ScreenPPIX = screenDC->GetDeviceCaps(LOGPIXELSX); info.ScreenPPIY = screenDC->GetDeviceCaps(LOGPIXELSY);
DeleteDC(screenHDC);
// 获取打印机的像素数(分辨率) info.PrinterPixelX = printerDC.GetDeviceCaps(HORZRES); info.PrinterPixelY = printerDC.GetDeviceCaps(VERTRES);
// 获取打印机的PPI info.PrinterPPIX = printerDC.GetDeviceCaps(LOGPIXELSX); info.PrinterPPIY = printerDC.GetDeviceCaps(LOGPIXELSY);
// 计算PPI比例 double ratePPIX = info.PrinterPPIX; ratePPIX = ratePPIX / info.ScreenPPIX;
double ratePPIY = info.PrinterPPIY; ratePPIY = ratePPIY / info.ScreenPPIY;
// 计算出打印机实际支持的屏幕对照像素数 // 打印时一般遵循物理尺寸一致的“所见即所得”模式 // 因为打印机的PPI一般较高,因此需要用几个像素来对应屏幕的一个像素,换算下来之后,打印机的对照分辨率也就降低了 info.PrintRatePixelX = static_cast<int>(info.PrinterPixelX / ratePPIX); info.PrintRatePixelY = static_cast<int>(info.PrinterPixelY / ratePPIY);
return info; }
// 获取默认打印机DC void CPrintDemoDlg::GetDefaultPrinterCtx(CDC &printerDC, LPDEVMODE &printerDevMode) { // 设置打印对话框风格 DWORD dwflags = PD_PAGENUMS | PD_HIDEPRINTTOFILE | PD_RETURNDEFAULT; // 创建打印对话框 CPrintDialog printDlg(false, dwflags, NULL);
// 获取设备默认项 if (!printDlg.GetDefaults()) { return; }
if (printerDC.Attach(printDlg.GetPrinterDC())) { //获取DEVMODE printerDevMode = printDlg.GetDevMode(); } }
// 获取指定打印机的DEVMODE bool CPrintDemoDlg::GetTargetPrinterDevMode(CString strPrintName, LPDEVMODE &printerDevMode) { HANDLE hPrinter; if (!OpenPrinter(strPrintName.GetBuffer(0), &hPrinter, NULL)) return false;
DWORD dwBytesNeeded; dwBytesNeeded = DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
HGLOBAL lhDevMode = GlobalAlloc(GHND, dwBytesNeeded); printerDevMode = (LPDEVMODE)GlobalLock(lhDevMode);
DWORD dwRet = DocumentProperties(NULL, hPrinter, NULL, printerDevMode, NULL, DM_OUT_BUFFER); ASSERT(IDOK == dwRet);
ClosePrinter(hPrinter); return true; }
// 获取指定(名称)打印机的DC bool CPrintDemoDlg::GetTargetPrinterCtx(CString strPrintName, CDC &printerDC, LPDEVMODE &printerDevMode) { // 这里先取指定打印机的DEVMODE if (!GetTargetPrinterDevMode(strPrintName, printerDevMode)) { return false; }
// 设置纸张, nPaper 是打印机支持的纸张列表的序号 // 使用 DeviceCapabilities( strPrinterName, NULL, DC_PAPERNAMES, NULL, NULL ) 来获取打印机支持的所有纸张 // printerDevMode->dmPaperSize = nPaper;
// 设置纸张方向 // 使用 DeviceCapabilities( strPrinterName, NULL, DC_ORIENTATION, NULL, NULL ) 来判断打印机是否支持横向 // printerDevMode->dmOrientation = nOrientation
// 设置单双面 // 使用 DeviceCapabilities( strPrinterName, NULL, DC_DUPLEX, NULL, NULL ) 来判断打印机是否支持双面打印 // printerDevMode->dmDuplex = nDuplex;
//创建打印机DC ASSERT(printerDC.CreateDC(NULL, strPrintName, NULL, printerDevMode));
return true; }
// 打印图片至DC bool CPrintDemoDlg::PrintImage(CDC &printerDC, Image &image, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, int xDest, int yDest, int nDestWidth, int nDestHeight) { RectF destRC; destRC.X = xDest; destRC.Y = yDest; destRC.Width = nDestWidth; destRC.Height = nDestHeight;
// 修改映射模式 PrintDeviceInfo deviceInfo = GetDeviceInfo(printerDC);
printerDC.SetMapMode(MM_ANISOTROPIC); printerDC.SetWindowExt(deviceInfo.PrintRatePixelX, deviceInfo.PrintRatePixelY); /* 逻辑分辨率 */ printerDC.SetViewportExt(deviceInfo.PrinterPixelX, deviceInfo.PrinterPixelY); /* 物理分辨率 */
Graphics graphics(printerDC.m_hDC); graphics.SetPageUnit(Gdiplus::Unit::UnitPixel);
ASSERT(Gdiplus::Ok == graphics.GetLastStatus());
Status gdiResult = graphics.DrawImage(&image, destRC, xSrc, ySrc, nSrcWidth, nSrcHeight, UnitPixel);
ASSERT(Gdiplus::Ok == gdiResult);
return true; }
|