⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdiutils.cpp

📁 虚拟打印机
💻 CPP
字号:
/* * * gdiutils.cpp * *   Copyright (C) 2006 Michael H. Overlin   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA      Contact at poster_printer@yahoo.com */#include "gdiutils.h"#include "coordtrans.h"#include "image.h"#include "mathutils.h"#include "spoolutils.h"#include "utils.h"HDC CreateDC(PCDEVMODE pdm, BOOL bIC) {	HDC hdc = NULL;	PPRINTER_INFO_2 pinfo = ::GetPrinterInfo2(pdm->dmDeviceName);	if (pinfo != NULL) {		if (bIC) {			hdc = ::CreateIC(pinfo->pDriverName, pinfo->pPrinterName, NULL, pdm);		} else {			hdc = ::CreateDC(pinfo->pDriverName, pinfo->pPrinterName, NULL, pdm);		}		free(pinfo);	}	return hdc;}// THE METAFILE WILL BE SCALED PROPORTIONATELY ONTO A BITMAP WHOSE MAXIMUM DIMENSION IS dwDraftMaxDimension// AND THIS WILL BE DRAWN INTO A MEMORY METAFILE WHICH IS RETURNED// THE BITMAP WILL INITIALLY BE FILLED WITH THE SOLID COLOR clrBkg TO COVER PIXELS THAT THE METAFILE DOESN'T SETHENHMETAFILE CreateDraftMetaFile(HENHMETAFILE hMeta, COLORREF clrBkg, DWORD dwDraftMaxDimension) {	HENHMETAFILE hMetaDraft = NULL;	RECTD rdFrame;	BOOL bContinue = FALSE;	{		::ENHMETAHEADER enhMetaHeader;		UINT uiCode = ::GetEnhMetaFileHeader(hMeta, sizeof(enhMetaHeader), &enhMetaHeader);		if (uiCode != 0) {			RECTL& r = enhMetaHeader.rclFrame;			::SetRect(rdFrame, r.left, r.top, r.right, r.bottom);			bContinue = TRUE;		}	}	if (bContinue) {		HDC hdcRef = ::GetDC(NULL);		if (hdcRef != NULL) {			try {				::ImageFromEnhMetafile imgFromMetaTemp(					hMeta, FALSE, 					rdFrame,					TRUE, clrBkg					);				SIZE szTemp_Output_Pixels;				HBITMAP hbmpTemp = ::ExtractSelectionToBitmap(					imgFromMetaTemp, 					rdFrame,					hdcRef,					dwDraftMaxDimension,					szTemp_Output_Pixels					);				if (hbmpTemp != NULL) {					try {						// 'TRUE' IN CONSTRUCTOR MEANS CLASS WILL DELETE THE HBITMAP ; try / catch ENSURES						// THIS WILL ALWAYS BE DONE						::ImageFromBitmap imgFromBmpTemp(hbmpTemp, TRUE, &rdFrame);						hMetaDraft = ::ExtractSelectionToEnhMetafile(							imgFromBmpTemp,							rdFrame,							hdcRef,							NULL,							NULL,							szTemp_Output_Pixels							);					} catch(...) {						// IF OUR ATTEMPT TO CREATE A DRAFT METAFILE FAILED, WE DON'T CARE					}				} 				::ReleaseDC(NULL, hdcRef);			} catch(...) {				::ReleaseDC(NULL, hdcRef);			}		}	}	return hMetaDraft;}HRGN CreateEmptyRgn(void) {	return ::CreateRectRgn(0,0,0,0);}HRGN CreateRectRgn(const RECT& r) {	return ::CreateRectRgn(r.left, r.top, r.right, r.bottom);}int CombineRgn(HRGN hrgnDest, HRGN hrgnSrc1, const RECT& r, int fnCombineMode) {	HRGN hrgnTemp = ::CreateRectRgn(r);	int k = ::CombineRgn(hrgnDest, hrgnSrc1, hrgnTemp, fnCombineMode);	::DeleteObject(hrgnTemp);	return k;}void FillBkColor(OUT HDC hdc, const RECT& r) {	::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &r, NULL, 0, NULL);}BOOL FillSolidColor(OUT HDC hdc, const RECT& r, COLORREF clr) {	COLORREF clrBkOld = ::SetBkColor(hdc, clr);	BOOL bRetValue = ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &r, NULL, 0, NULL);	::SetBkColor(hdc, clrBkOld);	return bRetValue;}BOOL GetClipRgn(HDC hdc, HRGN hrgn, const RECT& rWindow) {	BOOL bRetValue = TRUE;	int k = ::GetClipRgn(hdc, hrgn);	if (k == 0) {		bRetValue = ::SetRectRgn(hrgn, rWindow.left, rWindow.top, rWindow.right, rWindow.bottom);	} else if (k == -1) {		bRetValue = FALSE;	}	return bRetValue;}#if 0// DEBUG - FIX -- I NOW THINK THE REF DC LIMITS THE MAX "RESOLUTION" OF THE METAFILE// BUT THE LOGICAL SIZE IS ARBITRARY.  WILL DO SOME TESTING// THE METAFILE SEEMS TO BE LIMITED IN SIZE BY THE REF DC'S RESOLUTOIN (SIZE IN PIXELS)// AND GDI WILL CLIP PORTIONS THAT EXTEND BEYOND THIS, IN DEVICE COORDS// THEREFORE IN EXTRACTING A METAFILE, IN ORDER TO GET THE MOST ACCURATE RELATIVE POSITIONING OF ELEMENTS,// I DRAW IT SCALED AS LARGE AS POSSIBLE WHILE FITTING WITHIN THE REFERENCE DC'S RESOLUTION// (SIZE INFO COULD BE CARRIED IN THE DESCRIPTION)HENHMETAFILE ExtractSelectionFromEnhMetafile(	IN HENHMETAFILE hMetaSrc,	IN const RECTD& rdSrcSelection_Inches,	IN const RECTD& rdSrcTotal_Inches,	IN HDC hdcDestRef,	IN LPTSTR lptstrDestFileName,	IN LPCTSTR lptstrDestDescription,	OUT SIZE& out_szDestSelection_Pixels) {	HENHMETAFILE hMetaRetValue = NULL;	//::ENHMETAHEADER emhSrc;	//if (::GetEnhMetaFileHeader(hMetaSrc, sizeof(emhSrc), &emhSrc) != 0) {		// "HM" INDICATES HIMETRIC OR 0.01 MILLIMETER UNITES		RECT rSrcTotal_HM = {			RoundToLong(rdSrcTotal_Inches.left * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcTotal_Inches.top * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcTotal_Inches.right * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcTotal_Inches.bottom * MICROMETERS_PER_INCH / 10)		};		RECT rSrcSelection_HM = {			RoundToLong(rdSrcSelection_Inches.left * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcSelection_Inches.top * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcSelection_Inches.right * MICROMETERS_PER_INCH / 10),			RoundToLong(rdSrcSelection_Inches.bottom * MICROMETERS_PER_INCH / 10)		};		SIZE szSrcSelection_HM = { RW(rSrcSelection_HM), RH(rSrcSelection_HM) };		SIZE szDestRefDC_Pixels = { ::GetDeviceCaps(hdcDestRef, HORZRES), ::GetDeviceCaps(hdcDestRef, VERTRES) };		SIZE szDestRefDC_HM = { ::GetDeviceCaps(hdcDestRef, HORZSIZE) * 100, 								::GetDeviceCaps(hdcDestRef, VERTSIZE) * 100 };		double dScale1, dScale2;		if (szSrcSelection_HM.cx * szDestRefDC_Pixels.cy > szSrcSelection_HM.cy * szDestRefDC_Pixels.cx) {			dScale1 = (double)  szDestRefDC_HM.cx / szSrcSelection_HM.cx;			dScale2 = (double)  szDestRefDC_Pixels.cx / szSrcSelection_HM.cx;		} else {			dScale1 = (double)  szDestRefDC_HM.cy / szSrcSelection_HM.cy;			dScale2 = (double)  szDestRefDC_Pixels.cy / szSrcSelection_HM.cy;		}		SIZE szDestFrame_HM;		SIZE szDestSelection_Pixels;		szDestFrame_HM.cx = RoundToLong( szSrcSelection_HM.cx * dScale1 );		szDestFrame_HM.cy = RoundToLong( szSrcSelection_HM.cy * dScale1 );		szDestSelection_Pixels.cx = RoundToLong( szSrcSelection_HM.cx * dScale2 );		szDestSelection_Pixels.cy = RoundToLong( szSrcSelection_HM.cy * dScale2 );		RECT rDestFrame_HM = { 0, 0, szDestFrame_HM.cx, szDestFrame_HM.cy };		RECT rDestSelection_Pixels = { 0, 0, szDestSelection_Pixels.cx, szDestSelection_Pixels.cy };		HDC hdcMeta = ::CreateEnhMetaFile(hdcDestRef, lptstrDestFileName, &rDestFrame_HM, lptstrDestDescription);		if (hdcMeta != NULL) {					::SetMapMode(hdcMeta, MM_ANISOTROPIC);			::SetWindowOrgEx(hdcMeta, rSrcSelection_HM.left, rSrcSelection_HM.top, NULL);			::SetWindowExtEx(hdcMeta, RW(rSrcSelection_HM), RH(rSrcSelection_HM), NULL);			::SetViewportOrgEx(hdcMeta, rDestSelection_Pixels.left, rDestSelection_Pixels.top, NULL);			::SetViewportExtEx(hdcMeta, RW(rDestSelection_Pixels), RH(rDestSelection_Pixels), NULL);			::SelectClipRgn(hdcMeta, NULL);			::IntersectClipRect(hdcMeta, 				rSrcSelection_HM.left, rSrcSelection_HM.top, rSrcSelection_HM.right, rSrcSelection_HM.bottom);			//RECT rFrameSrc = { emhSrc.rclFrame.left, emhSrc.rclFrame.top, 			//	emhSrc.rclFrame.right, emhSrc.rclFrame.bottom };			//::PlayEnhMetaFile(hdcMeta, hMetaSrc, &rFrameSrc);			::PlayEnhMetaFile(hdcMeta, hMetaSrc, &rSrcTotal_HM);			hMetaRetValue = ::CloseEnhMetaFile(hdcMeta);			if (hMetaRetValue != NULL) {				out_szDestSelection_Pixels = szDestSelection_Pixels;			}		}	//}	return hMetaRetValue;}#elseHENHMETAFILE ExtractSelectionFromEnhMetafile(	IN HENHMETAFILE hMetaSrc,	IN const RECTD& rdSrcSelection_Inches,	IN const RECTD& rdSrcTotal_Inches,	IN HDC hdcDestRef,	IN LPTSTR lptstrDestFileName,	IN LPCTSTR lptstrDestDescription,	OUT SIZE& out_szDestSelection_Pixels) {	// DON'T SET A BACKGROUND COLOR FOR THE METAFILE IMAGE	ImageFromEnhMetafile img(hMetaSrc, FALSE, rdSrcTotal_Inches, FALSE, RGB(0xff, 0xff, 0xff));	HENHMETAFILE hMetaRetValue = ExtractSelectionToEnhMetafile(img, rdSrcSelection_Inches, hdcDestRef, 		lptstrDestFileName, lptstrDestDescription, out_szDestSelection_Pixels);	return hMetaRetValue;}#endifHENHMETAFILE ExtractSelectionToEnhMetafile(	IN const Image& img,	IN const RECTD& rdSrcSelection,	IN HDC hdcRef,	IN LPTSTR lptstrDestFileName,	IN LPCTSTR lptstrDestDescription,	OUT SIZE& out_szDestSelection_Pixels) {	HENHMETAFILE hMetaRetValue = NULL;	SIZE szRefDC_Pixels = { ::GetDeviceCaps(hdcRef, HORZRES), ::GetDeviceCaps(hdcRef, VERTRES) };	SIZE szRefDC_HM = { ::GetDeviceCaps(hdcRef, HORZSIZE) * 100, ::GetDeviceCaps(hdcRef, VERTSIZE) * 100 };	POINTD ptdRefDC_HM_Per_Pixel = { (double) szRefDC_HM.cx / szRefDC_Pixels.cx, (double) szRefDC_HM.cy / szRefDC_Pixels.cy };	SIZED szdSrcSelection = { RW(rdSrcSelection), RH(rdSrcSelection) };	double dScale = 1;	{		SIZED szdFrameDest = { szRefDC_Pixels.cx, szRefDC_Pixels.cy };		dScale = ::GetMaxIsoScale(szdFrameDest, szdSrcSelection);	}	SIZE szdDest = { szdSrcSelection.cx * dScale, szdSrcSelection.cy * dScale };	RECT rDest = { 0, 0, RoundToLong(szdDest.cx), RoundToLong(szdDest.cy)};	RECT rFrameMetafile_HM = { 		0, 0, RoundToLong(szdDest.cx * ptdRefDC_HM_Per_Pixel.x), RoundToLong(szdDest.cy * ptdRefDC_HM_Per_Pixel.y)	};	HDC hdcMeta = ::CreateEnhMetaFile(hdcRef, lptstrDestFileName, &rFrameMetafile_HM, lptstrDestDescription);	if (hdcMeta != NULL) {		if (img.Draw(hdcMeta, rDest, rdSrcSelection)) {			hMetaRetValue = ::CloseEnhMetaFile(hdcMeta);			if (hMetaRetValue != NULL) {				out_szDestSelection_Pixels.cx = RW(rDest);				out_szDestSelection_Pixels.cy = RH(rDest);			}		} else {			// DRAW FAILED			HENHMETAFILE hMetaTemp = ::CloseEnhMetaFile(hdcMeta);			::DeleteEnhMetaFile(hMetaTemp);		}	}	return hMetaRetValue;}HBITMAP ExtractSelectionToBitmap(	IN const Image& img,	IN const RECTD& rdSrcSelection,	IN HDC hdcRef,	DWORD dwMaxDimension,	OUT SIZE& out_szDestSelection_Pixels) {	HBITMAP hbmpRetValue = NULL;	SIZED szdSrcSelection = { RW(rdSrcSelection), RH(rdSrcSelection) };	double dScale = 1;	{		SIZED szdTemp = { dwMaxDimension, dwMaxDimension };		dScale = ::GetMaxIsoScale(szdTemp, szdSrcSelection);	}	SIZE szdDest = { szdSrcSelection.cx * dScale, szdSrcSelection.cy * dScale };	SIZE szDest = { RoundToLong(szdDest.cx), RoundToLong(szdDest.cy) };	RECT rDest = { 0, 0, szDest.cx, szDest.cy };	hbmpRetValue = ::CreateCompatibleBitmap(hdcRef, szDest.cx, szDest.cy);	if (hbmpRetValue != NULL) {		BOOL bDrawOK = FALSE;		try {			HDC hdcMem = ::CreateCompatibleDC(hdcRef);			if (hdcMem != NULL) {				HBITMAP hbmpOld = (HBITMAP) ::SelectObject(hdcMem, hbmpRetValue);				if (hbmpOld != NULL) {					try {						bDrawOK = img.Draw(hdcMem, rDest, rdSrcSelection) ;					} catch(...) {					}					::SelectObject(hdcMem, hbmpOld);				}				::DeleteDC(hdcMem);			}		} catch (...) {		}		if (!bDrawOK) {			::DeleteObject(hbmpRetValue);			hbmpRetValue = NULL;		}	}	return hbmpRetValue;}int IntersectClipRect(OUT HDC hdc, IN const RECT& r) {	int k = IntersectClipRect(hdc, r.left, r.top, r.right, r.bottom);	return k;}PVOID MyGetEnhMetaFileBits(IN HENHMETAFILE hMeta, OUT DWORD& dwCbData) {	PVOID pvRetValue = NULL;	DWORD dwCbNeeded = ::GetEnhMetaFileBits(hMeta, 0, NULL);	if (dwCbNeeded != 0) {		pvRetValue = malloc(dwCbNeeded);		if (pvRetValue != NULL) {			DWORD dwCbMeta = ::GetEnhMetaFileBits(hMeta, dwCbNeeded, (LPBYTE) pvRetValue);			if (dwCbMeta == 0) {				free(pvRetValue);				pvRetValue = NULL;			} else {				dwCbData = dwCbMeta;			}		}	}	return pvRetValue;}void SetViewport(OUT HDC hdc, IN const RECT& rl) {	SetViewportOrgEx(hdc, rl.left, rl.top, NULL);	SetViewportExtEx(hdc, RW(rl), RH(rl), NULL);}void SetWindow(OUT HDC hdc, IN const RECT& rl) {	SetWindowOrgEx(hdc, rl.left, rl.top, NULL);	SetWindowExtEx(hdc, RW(rl), RH(rl), NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -