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

📄 scemfinspectdlg.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
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 + -