📄 gdiutils.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 + -