📄 scemfinspectdlg.cpp
字号:
void CSCEMFInspectDlg::OnBtnStopbrk()
{
SCEnableGUI();
}
void CSCEMFInspectDlg::SCEnableGUI(BOOL bStop/*=TRUE*/)
{
m_bStopBrk = bStop;
SCEnableControl(IDC_BTN_STOPBRK, !bStop);
SCEnableControl(IDC_BTN_SAVERTF, bStop);
SCEnableControl(IDC_BTN_COPYALL, bStop);
SCEnableControl(IDCANCEL, bStop);
}
void CSCEMFInspectDlg::OnClose()
{
m_bStopBrk = TRUE;
if (m_bCracking)
return;
#if 0
// good for modal
CDialog::OnClose();
#else
CWnd* pWnd = ::AfxGetMainWnd();
pWnd->PostMessage(WM_COMMAND, ID_VIEW_EMF_ASTEXT, 0);
#endif
}
void CSCEMFInspectDlg::OnCancel()
{
m_bStopBrk = TRUE;
if (m_bCracking)
return;
#if 0
// good for modal
CDialog::OnCancel();
#else
CWnd* pWnd = ::AfxGetMainWnd();
pWnd->PostMessage(WM_COMMAND, ID_VIEW_EMF_ASTEXT, 0);
#endif
}
// Because we call SCYieldForAWhile in an enummetafile callback for GUI responsiveness,
// there are great dangers: the user may close CSCEMFInspectDlg in an uncontrolled manner
// (or even close the application), letting the enumeration process still running.
//
// We use a guardian thread to "wrap" the call to SCMetafile2Text, and
// until this function returns, in case CSCEMFInspectDlg is
// destroyed while GDI is deep in metafile enumeration.
//
// TODO: solve the case of application destruction while enumeration is on progress;
// for now, access violation will occur in GDI32 (inside EnumEnhMetaFile).
typedef struct tag_SCCrkInfo
{
HDC cri_hdc;
CSCEMF2Text* cri_pobj;
} SCCrkInfo, *PSCCrkInfo;
// this "wrapping" technique is not very classic; but we are using it to avoid calling
// inside this function an MFC object created in the main thread
DWORD WINAPI SCEMFcrkGuardian(LPVOID lpParam)
{
PSCCrkInfo pCrk = (PSCCrkInfo)lpParam;
WaitForSingleObject(g_hEmergencyQuit, INFINITE);
CancelDC(pCrk->cri_hdc);
pCrk->cri_pobj->SCSetStop(TRUE);
SCEMFDCDispose(pCrk->cri_hdc);
SetEvent(g_hCrackerDead);
return 0;
}
/////////////////////////////////////////////////////////////////////////
void CSCEMFInspectDlg::SCBeginCracking()
{
if (!m_hEmf)
return;
SetTimer(1, 1, NULL);
}
void CSCEMFInspectDlg::OnTimer(UINT nIDEvent)
{
KillTimer(nIDEvent);
m_EdEMFContent.SCSetEmpty();
m_Progress.ShowWindow(SW_SHOW);
m_Progress.SetRange32(0,0);
m_Progress.SetPos(0);
ENHMETAHEADER EmfHeader;
if (!::GetEnhMetaFileHeader(m_hEmf, sizeof(ENHMETAHEADER), &EmfHeader))
{
TRACE0("Failed to get EMF header\n");
return;
}
{// info
long lEmfDPIX = 0;
long lEmfDPIY = 0;
long lEmfPaperCx = 0;
long lEmfPaperCy = 0;
SCGetEMFInfos(m_hEmf, lEmfDPIX, lEmfDPIY, lEmfPaperCx, lEmfPaperCy);
m_strDPI.Format(_T("%d x %d dpi"), lEmfDPIX, lEmfDPIY);
m_strSize.Format(_T("%d x %d"), lEmfPaperCx, lEmfPaperCy);
UpdateData(FALSE);
}
HDC hNewEMFDC = NULL;
RECT rFrameRect;
CopyRect(&rFrameRect,(const RECT *)&(EmfHeader.rclFrame));
HDC hDc = ::GetWindowDC(m_EdEMFContent.m_hWnd);
hNewEMFDC = ::CreateEnhMetaFile(hDc, (LPCTSTR)NULL, (LPRECT)&(EmfHeader.rclFrame) , NULL);
::ReleaseDC(m_EdEMFContent.m_hWnd, hDc);
SCInitEMFDCForEnumeration(hNewEMFDC, EmfHeader, hDc);
CSCEMF2Text Cracker;
Cracker.SCSetBrkCallBack(this);
#if 0
// It is not harmful to activate it: high thresholds will reduce GUI responsiveness
if (EmfHeader.nRecords>10000)
Cracker.SCSetCallbackThreshold(EmfHeader.nRecords/100);
#endif
m_nMaxBrkPos = 0;
SCEnableGUI(FALSE);
m_bCracking = TRUE;
m_bDestroyed = FALSE;
#if 1
// Note: pointers to local variables are beeing passed to the guardian thread
DWORD dwThreadID;
SCCrkInfo CrkInfo;
CrkInfo.cri_hdc = hNewEMFDC;
CrkInfo.cri_pobj = &Cracker;
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SCEMFcrkGuardian, (LPVOID)&CrkInfo, 0, &dwThreadID);
CloseHandle(hThread);
SC_BRKRESULT brkError = Cracker.SCMetafile2Text(hNewEMFDC, m_hEmf,
NULL,
&rFrameRect,
TRUE);
if (m_bDestroyed)
return;
// force the guardian thread to stop
SetEvent(g_hEmergencyQuit);
WaitForSingleObject(g_hCrackerDead, INFINITE);
#else
SC_BRKRESULT brkError = Cracker.SCMetafile2Text(hNewEMFDC, m_hEmf,
NULL,
&rFrameRect,
TRUE);
SCEMFDCDispose(hNewEMFDC);
#endif
SCEnableGUI(TRUE);
SCCheckTextContent();
m_EdEMFContent.UpdateWindow();
m_Progress.SetPos(0);
m_bCracking = FALSE;
}
void CSCEMFInspectDlg::SCUpdateAllControls()
{
UpdateData(FALSE);
}
void CSCEMFInspectDlg::SCCheckBtnControl(UINT uCtl, BOOL bCheck)
{
CButton *pBtn = (CButton *)GetDlgItem(uCtl);
if (pBtn)
pBtn->SetCheck(bCheck);
}
void CSCEMFInspectDlg::SCShowControl(UINT uCtl, int nShow)
{
CWnd *pWnd = GetDlgItem(uCtl);
if (pWnd)
pWnd->ShowWindow(nShow);
}
void CSCEMFInspectDlg::SCUpdateControl(UINT uCtl)
{
CWnd *pWnd = GetDlgItem(uCtl);
if (pWnd)
pWnd->UpdateWindow();
}
static DWORD CALLBACK SCRTFSave(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb)
{
CFile* pFile = (CFile*)dwCookie;
try
{
pFile->Write(pbBuff, cb);
*pcb = cb;
}
catch (CFileException* pEx)
{
pEx->Delete();
return 1; // Failed so stop calling us.
}
return 0;
}
BOOL CSCEMFInspectDlg::SCSaveDocument(LPCTSTR lpszPathname, BOOL bRTF/*=FALSE*/)
{
if (m_bCracking)
return FALSE;
// Open the file for reading.
CFile outputFile;
CFileException ex;
if (!outputFile.Open(lpszPathname, CFile::modeCreate | CFile::modeWrite, &ex))
return FALSE;
// Read the text in
EDITSTREAM es;
es.dwError = 0;
es.pfnCallback = SCRTFSave;
es.dwCookie = (DWORD)&outputFile;
m_EdEMFContent.StreamOut(bRTF ? SF_RTF : SF_TEXT, es);
outputFile.Close();
return TRUE;
}
void CSCEMFInspectDlg::SCCopy(BOOL bCopyAll/*=FALSE*/)
{
if (m_bCracking)
return;
if (bCopyAll)
SCSelectAll();
m_EdEMFContent.Copy();
}
void CSCEMFInspectDlg::SCSelectAll()
{
if (m_bCracking)
return;
CHARRANGE cr;
cr.cpMin = 0;
cr.cpMax = -1;
m_EdEMFContent.SetSel(cr);
}
void CSCEMFInspectDlg::SCPrint(CDC* pDC, CPrintInfo* pInfo)
{
if (m_bCracking)
return;
FORMATRANGE fr;
fr.hdcTarget = pInfo->m_pPD->m_pd.hDC;
ASSERT(fr.hdcTarget == pDC->m_hAttribDC);
fr.hdc = pDC->m_hDC;
fr.chrg.cpMax = -1;
int nHorizRes = pDC->GetDeviceCaps(PHYSICALWIDTH);
int nVertRes = pDC->GetDeviceCaps(PHYSICALHEIGHT);
int nLogPixelsX = pDC->GetDeviceCaps(LOGPIXELSX);
int nLogPixelsY = pDC->GetDeviceCaps(LOGPIXELSY);
int nMargin = MulDiv(250, 1440, 254); // twips (2.5cm) all around
::CopyRect(&fr.rcPage, &pInfo->m_rectDraw);
SCRectToTwips(&fr.rcPage, nLogPixelsX, nLogPixelsY, pDC);
::CopyRect(&fr.rc, &pInfo->m_rectDraw);
SCRectToTwips(&fr.rc, nLogPixelsX, nLogPixelsY, pDC);
::InflateRect(&fr.rc, -nMargin, -nMargin);
if (pInfo->m_bPreview)
{
float fPreviewZoomRatio = (pInfo->m_lpUserData) ? *((float*)pInfo->m_lpUserData): 1;
// Prepare surface (scaling)
CPoint ptScrPageStart;
// get offset of the printing area in the page
ptScrPageStart.x = GetDeviceCaps(pDC->m_hDC, PHYSICALOFFSETX);
ptScrPageStart.y = GetDeviceCaps(pDC->m_hDC, PHYSICALOFFSETY);
//change window and viewport extent
int iScrDevResX = GetDeviceCaps(pDC->m_hDC, LOGPIXELSX);
int iScrDevResY = GetDeviceCaps(pDC->m_hDC, LOGPIXELSY);
SetMapMode(pDC->m_hDC, MM_ISOTROPIC);
SetWindowExtEx(pDC->m_hDC, iScrDevResX, iScrDevResY , NULL);
SetViewportExtEx(pDC->m_hDC, (int)(iScrDevResX * fPreviewZoomRatio), (int)(iScrDevResY * fPreviewZoomRatio) , NULL);
}
long lTextOut = 0;
fr.chrg.cpMin = lTextOut;
lTextOut = m_EdEMFContent.FormatRange(&fr, TRUE);
}
UINT CSCEMFInspectDlg::SCCountPages(CDC* pDC, CPrintInfo* pInfo)
{
// Setup paper
int nHorizRes;
int nVertRes;
int nMarginX = MulDiv(250, 1440, 254); // twips (2.5cm)
int nMarginY = nMarginX; // all around
// Check default printer
PRINTDLG pd = pInfo->m_pPD->m_pd;
HDC hdc = pd.hDC;
if (!pDC)
{
BOOL bExistPrinter = (AfxGetApp()->GetPrinterDeviceDefaults(&pd));
pd.lStructSize = sizeof (PRINTDLG);
pd.hwndOwner = m_EdEMFContent.m_hWnd;
pd.hDevMode = (HANDLE)NULL;
pd.hDevNames = (HANDLE)NULL;
pd.nFromPage = 0;
pd.nToPage = 0;
pd.nMinPage = 0;
pd.nMaxPage = 0;
pd.nCopies = 0;
pd.hInstance = (HINSTANCE)AfxGetApp()->m_hInstance;
pd.Flags = PD_RETURNDEFAULT|PD_RETURNDC;
pd.lpfnSetupHook = (LPSETUPHOOKPROC)(FARPROC)NULL;
pd.lpSetupTemplateName = (LPTSTR)NULL;
pd.lpfnPrintHook = (LPPRINTHOOKPROC)(FARPROC)NULL;
pd.lpPrintTemplateName = (LPTSTR)NULL;
if (bExistPrinter && (PrintDlg(&pd) == TRUE))
hdc = pd.hDC;
if (!hdc)
return (unsigned)-1;
pDC = CDC::FromHandle(hdc);
}
nHorizRes = GetDeviceCaps(hdc, PHYSICALWIDTH);
nVertRes = GetDeviceCaps(hdc, PHYSICALHEIGHT);
int nLogPixelsX = pDC->GetDeviceCaps(LOGPIXELSX);
int nLogPixelsY = pDC->GetDeviceCaps(LOGPIXELSY);
FORMATRANGE fr;
fr.hdcTarget = hdc;
fr.hdc = hdc;
fr.chrg.cpMax = -1;
::SetRect(&fr.rcPage, 0, 0, nHorizRes, nVertRes);
SCRectToTwips(&fr.rcPage, nLogPixelsX, nLogPixelsY, pDC);
::CopyRect(&fr.rc, &fr.rcPage);
::InflateRect(&fr.rc, -nMarginX, -nMarginY);
long lTextLen = m_EdEMFContent.GetTextLength();
long lTextOut = 0;
UINT uiNbPages = 0;
while (lTextOut<lTextLen)
{
fr.chrg.cpMin = lTextOut;
lTextOut = m_EdEMFContent.FormatRange(&fr, FALSE);
uiNbPages++;
}
// tell the control to release cached information
m_EdEMFContent.FormatRange(NULL, FALSE);
return uiNbPages;
}
void CSCEMFInspectDlg::OnBtnSaveRTF()
{
if (m_bCracking)
return;
CString sFilters(SC_BRKMODE_FILTERS);
CFileDialog dlg(FALSE, NULL, _T("*.rtf"),
OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT,
(LPCTSTR)sFilters);
if (dlg.DoModal() != IDOK)
return;
CString strPath = dlg.GetPathName();
SCAddPathExtFromFilterIndex(strPath, sFilters, dlg.m_ofn.nFilterIndex);
int iType = SC_FTYPE_UKN;
switch (dlg.m_ofn.nFilterIndex)
{
case 1: iType = SC_FILETYPE_RTF; break;
case 2: iType = SC_FILETYPE_TXT; break;
default:
ASSERT(0);
return;
}
SCSaveDocument(strPath, (SC_FILETYPE_RTF==iType));
}
void CSCEMFInspectDlg::OnBtnCopyAll()
{
SCCopy(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -