📄 scemfimage.cpp
字号:
// So save its state
int iState = SaveDC(hDC);
SCComputePageInfo(pInfo->m_nCurPage);
// scaling
int iPgIdx = pInfo->m_nCurPage - 1;
HENHMETAFILE hEMF = m_pEMFDoc->SCGetPageEMF(iPgIdx);
CPoint PageStart;
{
float iPrnDevResX = (float)GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSX);
long lEmfDPIX = 0;
long lEmfDPIY = 0;
SCGetEMFDPIs(hEMF, lEmfDPIX, lEmfDPIY);
m_DrawingAttributes.fPageScale = iPrnDevResX/lEmfDPIX;
// get offset of the printable area in device units an convert to logical
PageStart.x = GetDeviceCaps(pDC->m_hAttribDC, PHYSICALOFFSETX);
PageStart.y = GetDeviceCaps(pDC->m_hAttribDC, PHYSICALOFFSETY);
DPtoLP(pDC->m_hAttribDC, &PageStart, 1);
}
// Position of the EMF rectangle in world coordinates for playing
int iAngle = m_iAngle;
CSize sizeEMF;
float fScaleEMF=1.0;
SCGetEMFPlaySize(hEMF, sizeEMF, pDC->m_hAttribDC, &fScaleEMF);
CSize sizeEMFScaled((int)(m_DrawingAttributes.fPageScale*sizeEMF.cx - 2*PageStart.x),
(int)(m_DrawingAttributes.fPageScale*sizeEMF.cy - 2*PageStart.y));
int iWdt = sizeEMF.cx;
int iHgt = sizeEMF.cy;
int iImgCx = sizeEMFScaled.cx;
int iImgCy = sizeEMFScaled.cy;
int iPaperCx = rcPaper.Width();
int iPaperCy = rcPaper.Height();
if (bFit)
{
if (iImgCx > iPaperCx)
{
iWdt = (int)(iPaperCx/m_DrawingAttributes.fPageScale);
iHgt = MulDiv(iWdt, sizeEMF.cy, sizeEMF.cx);
} else
if (iImgCy > iPaperCy)
{
iHgt = (int)(iPaperCy/m_DrawingAttributes.fPageScale);
iWdt = MulDiv(iHgt, sizeEMF.cx, sizeEMF.cy);
}
}
else // attempt auto rotate
if (iImgCx > iImgCy)
{// landscape-like image
if (iPaperCx > iPaperCy)
{// landscape-like paper
if (iImgCx > iPaperCx)
{// x-fit
iWdt = (int)(iPaperCx/m_DrawingAttributes.fPageScale);
iHgt = MulDiv(iWdt, iImgCy, iImgCx);
} else
if (iImgCy > iPaperCy)
{// y-fit
iHgt = (int)(iPaperCy/m_DrawingAttributes.fPageScale);
iWdt = MulDiv(iHgt, iImgCx, iImgCy);
}
}
else
{// portrait-like paper
if (iImgCx > iPaperCx)
{// rotate and fit
iAngle = 270;
if (iImgCx > iPaperCy)
{// rotated x-fit
iWdt = (int)(iPaperCy/m_DrawingAttributes.fPageScale);
iHgt = MulDiv(iWdt, iImgCy, iImgCx);
} else
if (iImgCy > iPaperCx)
{// rotated y-fit
iHgt = (int)(iPaperCx/m_DrawingAttributes.fPageScale);
iWdt = MulDiv(iHgt, iImgCx, iImgCy);
}
} //else (iImgCy <= iPaperCy)
#ifdef _DEBUG
else
{
ASSERT((iImgCy <= iPaperCy));
}
#endif
}
}
else
{// portrait-like image
if (iPaperCx > iPaperCy)
{// landscape-like paper
if (iImgCy > iPaperCy)
{// rotate and fit
iAngle = 270;
if (iImgCy > iPaperCx)
{// rotated x-fit
iHgt = (int)(iPaperCx/m_DrawingAttributes.fPageScale);
iWdt = MulDiv(iHgt, iImgCx, iImgCy);
} else
if (iImgCx > iPaperCy)
{// rotated y-fit
iWdt = (int)(iPaperCy/m_DrawingAttributes.fPageScale);
iHgt = MulDiv(iWdt, iImgCy, iImgCx);
}
} // else iImgCx <= iPaperCx
#ifdef _DEBUG
else
{
ASSERT((iImgCx <= iPaperCx));
}
#endif
}
else
{// portrait-like paper
if (iImgCx > iPaperCx)
{// x-fit
iWdt = (int)(iPaperCx/m_DrawingAttributes.fPageScale);
iHgt = MulDiv(iWdt, iImgCy, iImgCx);
} else
if (iImgCy > iPaperCy)
{// y-fit
iHgt = (int)(iPaperCy/m_DrawingAttributes.fPageScale);
iWdt = MulDiv(iHgt, iImgCx, iImgCy);
}
}
}
// TODO: compute scale (in preview and actual printing)
iWdt = (int)(iWdt*m_DrawingAttributes.fPageScale);
iHgt = (int)(iHgt*m_DrawingAttributes.fPageScale);
m_DrawingAttributes.fPageScale = 1;
//
CRect rcPlay(xDest, yDest, xDest + iWdt, yDest + iHgt);
if (iAngle)
{// Position of the PAGE rectangle for rotation in world coordinates
CRect rcRotate(0, 0, sizeEMFScaled.cx, sizeEMFScaled.cy);
// Give the actual page rectangle for the rotation
// and the actual destination (xDest, yDest) for the translation
int iGrOldMode;
SCRotateDC(hDC, iAngle, rcRotate, xDest, yDest, iGrOldMode);
}
// Rasterize
#ifndef SC_RENDERER_CAN_DOROP
// In this version, GDI+ is not used for printing
BOOL bOK;
if (SCGdipGetEMFType(hEMF)!=EmfTypeEmfOnly)
bOK = SCGdipPlayMetafile(hDC, hEMF, rcPlay);
else
bOK = PlayEnhMetaFile(hDC, hEMF, (LPRECT)&rcPlay);
#else
BOOL bOK = SCRasterizeEMF(hDC, hEMF, rcPlay, TRUE);
#endif
// Comments
PSCEMFDocPage pDocPage = m_pEMFDoc->SCGetDocPage(iPgIdx);
ASSERT(pDocPage);
switch (iAngle)
{
case 90:
case 270:
pDocPage->SCDisplayPageComments(hDC, float(m_iCurZoom)/float(SC_ZOOM100),
xDest, yDest, iHgt, iWdt);
break;
default:
pDocPage->SCDisplayPageComments(hDC, float(m_iCurZoom)/float(SC_ZOOM100),
xDest, yDest, iWdt, iHgt);
}
// Restore DC state
RestoreDC(hDC, iState);
// Perform full rvideo
if (SCIsFullReverseVideo())
PatBlt(hDC, xDest-1, yDest-1, iWdt+2, iHgt+2, DSTINVERT);
}
void CSCEMFImage::SCInitConverter(SCEMFConverter& converter)
{
CRect rcClient;
GetClientRect(&rcClient);
converter.SCSetEMFDoc(m_pEMFDoc);
converter.SCSetCurZoom(m_iCurZoom);
converter.SCSetAngle(m_iAngle);
converter.SCSetMargins(m_rectMargins);
converter.SCSetReverseVideo(m_bReverseVideo);
converter.SCSetRasEngine(m_uiRasEngine);
converter.SCSetPaperColor(SCGetTranslatedPaperColor());
converter.SCSetRectClient(rcClient);
converter.SCSetFitMode(m_iFitMode);
converter.SCSetDrawingAttributes(m_DrawingAttributes);
}
void CSCEMFImage::SCSaveImageDiscardHandle(HANDLE hRes, LPCTSTR lpszPathname, int iType, int iSubType)
{
if (hRes)
{
switch (iType)
{
case SC_FTYPE_EMF:
case SC_FTYPE_WMF:
if (SC_FTYPE_EMF==iType)
SCWriteEMFtoDisk((HENHMETAFILE)hRes, lpszPathname);
else
SCConvertEMFtoWMF((HENHMETAFILE)hRes, lpszPathname);
::DeleteEnhMetaFile((HENHMETAFILE)hRes);
break;
case SC_FTYPE_IMG:
// TODO: for JPEGs ask quality level to user
SCGDIpSaveImage((HBITMAP)hRes, lpszPathname, iSubType);
::DeleteObject((HBITMAP)hRes);
break;
default:
ASSERT(0);
}
}
}
///
/// Save current EMF or all pages to disk
///
void CSCEMFImage::SCSaveDocument(LPCTSTR lpszPathname, int iType, BOOL bSaveAll/*=FALSE*/, BOOL bSaveAsIs/*=TRUE*/)
{
if (!m_pEMFDoc)
return;
int iNbPages=m_pEMFDoc->SCGetNbPages();
if (0==iNbPages)
return;
int iSubType = iType & SC_SUBTYPE_MASK;
iType &= SC_FTYPE_MASK;
SCEMFConverter converter;
SCInitConverter(converter);
CRect PaperRect;
if (bSaveAll)
{// save each page
CString strPrefix;
TCHAR szExt[_MAX_EXT];
{
TCHAR szDrive[SC_MAX_UNC_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFname[_MAX_FNAME];
SCSplitPath(lpszPathname, szDrive, szDir, szFname, szExt);
strPrefix.Format(_T("%s%s%s"), szDrive, szDir, szFname);
}
CString strName;
for (int iPage=0; (iPage<iNbPages); iPage++)
{
strName.Format(_T("%s%d%s"), strPrefix, iPage+1, szExt);
HANDLE hRes = converter.SCCopyPage(iPage+1, iType, iSubType, bSaveAsIs);
SCSaveImageDiscardHandle(hRes, strName, iType, iSubType);
}
} else
{
ASSERT(m_iCurPage);
HANDLE hRes = converter.SCCopyPage(m_iCurPage, iType, iSubType, bSaveAsIs);
SCSaveImageDiscardHandle(hRes, lpszPathname, iType, iSubType);
}
}
///
/// Copy the current page to cliboard in many formats.
/// (no partial copy is provided in this version; pSrcRect is not used)
///
BOOL CSCEMFImage::SCCopyToClipBoard(CRect* pSrcRect/*=NULL*/)
{
UNUSED(pSrcRect); // Zzzz!... let it sleep for now
if (!OpenClipboard())
return FALSE;
BOOL bOk = FALSE;
if (::EmptyClipboard())
{
HANDLE hCopied = NULL;
SCEMFConverter converter;
SCInitConverter(converter);
// EMF
HANDLE hData = converter.SCCopyPage(m_iCurPage, SC_FTYPE_EMF, SC_SUBTYPE_EMF_EMF, TRUE);
if (hData)
{
hCopied = ::SetClipboardData(CF_ENHMETAFILE, (HENHMETAFILE)hData);
if (!hCopied)
::DeleteEnhMetaFile((HENHMETAFILE)hData);
bOk = TRUE;
}
// Bitmap
hData = converter.SCCopyPage(m_iCurPage, SC_FTYPE_IMG, SC_SUBTYPE_IMG_BMP, TRUE);
if (hData)
{
hCopied = ::SetClipboardData(CF_BITMAP, (HBITMAP)hData);
if (!hCopied)
::DeleteObject((HBITMAP)hData);
bOk = TRUE;
}
}
::CloseClipboard();
return bOk;
}
///
/// Paste the clipboard content as a new full page
/// (no partial paste is provided in this version; pDestRect is not used)
///
BOOL CSCEMFImage::SCPasteFromClipBoard(CRect* pDestRect/*=NULL*/)
{
UNUSED(pDestRect); // Zzzz!... let it sleep for now
if (!m_pEMFDoc)
return FALSE;
if (!OpenClipboard())
return FALSE;
BOOL bOk = FALSE;
HEMFVECTOR vectHandles;
BeginWaitCursor();
// Check main vector formats
UINT uiFmt = 0;
while (uiFmt = EnumClipboardFormats(uiFmt))
{
if (uiFmt == CF_ENHMETAFILE)
{
HENHMETAFILE hEMF = (HENHMETAFILE)::GetClipboardData(CF_ENHMETAFILE);
if (hEMF)
{
hEMF = CopyEnhMetaFile(hEMF, NULL);
if (hEMF)
vectHandles.push_back(hEMF);
}
break;
} else
if (uiFmt == s_cfRTF)
{
HANDLE hMem = ::GetClipboardData(s_cfRTF);
SCConvertRTFtoEMF(hMem, vectHandles);
break;
}
}
// Check text formats
if (!vectHandles.size())
{
HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT);
if (hMem)
SCConvertRTFtoEMF(hMem, vectHandles, FALSE);
}
// Check bitmap formats
if (!vectHandles.size())
{
HENHMETAFILE hEMF = NULL;
HBITMAP hbm;
if (hbm = (HBITMAP)GetClipboardData(CF_BITMAP))
{
// Any palette in the clipboard at this time is assumed to be the one
// the bitmap is realized against.
HPALETTE hpal = (HPALETTE)GetClipboardData(CF_PALETTE);
if (!hpal)
hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
hEMF = SCGDIpConvertBitmaptoEMF(hbm, hpal);
} else
{
HANDLE hMem = NULL;
if (hMem = GetClipboardData(CF_TIFF))
hEMF = SCGDIpConvertImagetoEMF(hMem);
}
if (hEMF)
vectHandles.push_back(hEMF);
}
CloseClipboard();
// Add pages to the doc
if (vectHandles.size())
bOk = m_pEMFDoc->SCPasteEMFPages(vectHandles);
EndWaitCursor();
return bOk;
}
// Display context menu
void CSCEMFImage::OnRButtonDown(UINT nFlags, CPoint point)
{
if (m_hCtxMenu)
{
CMenu menu;
if (menu.Attach(m_hCtxMenu))
{
//convert client coordinates to screen coordinates
ClientToScreen(&point);
//show context menu
CWnd* pOwner = this;
if (m_pICtlOwner)
{
pOwner = m_pICtlOwner->SCGetMenuOwner();
if (!pOwner)
pOwner = this;
m_pICtlOwner->SCSetupCtxMenu(&menu);
}
menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, pOwner);
menu.Detach();
}
}
CWnd::OnRButtonDown(nFlags, point);
}
BOOL CSCEMFImage::OnCommand( WPARAM wParam, LPARAM lParam )
{
if (m_pICtlOwner)
m_pICtlOwner->SCOnCtxCommand(wParam, lParam);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -