emfview.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 567 行
CPP
567 行
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : emfview.cpp //
// Description: KEMFView class //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define INITGUID
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
#define STRICT
#pragma pack(push, 4)
#include <windows.h>
#pragma pack(pop)
#include <tchar.h>
#include <assert.h>
#include <fstream.h>
#include <commctrl.h>
#include <fstream.h>
#include "..\..\include\win.h"
#include "..\..\include\canvas.h"
#include "..\..\include\mmfile.h"
#include "..\..\include\treeview.h"
#include "..\..\include\emf.h"
#include "..\..\include\filedialog.h"
#include "..\..\include\LogWindow.h"
#include "resource.h"
#include "EMFView.h"
#include "EmfDC.h"
int SimpleEnumerateEMF(HENHMETAFILE hEmf, ofstream & stream)
{
int size = GetEnhMetaFileBits(hEmf, 0, NULL);
if ( size<=0 )
return 0;
BYTE * pBuffer = new BYTE[size];
if ( pBuffer==NULL )
return 0;
GetEnhMetaFileBits(hEmf, size, pBuffer);
const EMR * emr = (const EMR *) pBuffer;
TCHAR mess[MAX_PATH];
int recno = 0;
// enumuerate all EMF records
while ( (emr->iType>=EMR_MIN) && (emr->iType<=EMR_MAX) )
{
recno ++;
wsprintf(mess, "%3d: EMR_%03d (%4d bytes)\n", recno, emr->iType, emr->nSize);
stream << mess;
if ( emr->iType== EMR_EOF )
break;
emr = (const EMR *) ( ( const char * ) emr + emr->nSize );
}
delete [] pBuffer;
return recno;
}
/////////////////////////////////////////////////////
class KTraceEMF : public KEnumEMF
{
int m_nSeq;
KEmfDC m_emfdc;
int m_value[32];
HGDIOBJ m_object[8];
FLOAT m_float[8];
// virtual function to process every EMF record, return 0 to terminate
virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
{
CompareDC(hDC);
m_pLog->Log("%4d: %08x %3d % 6d ", m_nSeq++, pEMFR, pEMFR->iType, pEMFR->nSize);
m_pLog->Log(m_emfdc.DecodeRecord((const EMR *) pEMFR));
m_pLog->Log("\r\n");
return PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
}
public:
KLogWindow * m_pLog;
void CompareDC(HDC hDC);
void Show(bool bShow)
{
m_pLog->ShowWindow(bShow);
}
KTraceEMF(HINSTANCE hInst)
{
m_pLog = new KLogWindow; // allocated here, deallocated in WM_NCDESTROY handling
m_pLog->Create(hInst, "EMF Trace");
m_nSeq = 1;
memset(m_value, 0xCD, sizeof(m_value));
memset(m_object, 0xCD, sizeof(m_object));
memset(m_float, 0xCD, sizeof(m_float));
}
};
#define Compare(value, exp, mess) if (value!=exp) { value = exp; m_pLog->Log(mess, value); }
void KTraceEMF::CompareDC(HDC hDC)
{
Compare(m_value[0], GetMapMode(hDC), "MapMode : %d\r\n");
Compare(m_value[1], GetGraphicsMode(hDC), "GraphicsMode : %d\r\n");
XFORM xm;
GetWorldTransform(hDC, & xm);
Compare(m_float[0], xm.eM11, "WT.eM11 : %8.5f\r\n");
Compare(m_float[1], xm.eM12, "WT.eM12 : %8.5f\r\n");
Compare(m_float[2], xm.eM21, "WT.eM21 : %8.5f\r\n");
Compare(m_float[3], xm.eM22, "WT.eM22 : %8.5f\r\n");
Compare(m_float[4], xm.eDx, "WT.eDx : %8.5f\r\n");
Compare(m_float[5], xm.eDy, "WT.eDy : %8.5f\r\n");
Compare(m_value[2], GetBkMode(hDC), "BkMode : %d\r\n");
Compare(m_value[3], GetROP2(hDC), "ROP2 : %d\r\n");
Compare(m_value[4], ((int)GetTextAlign(hDC)), "TextAlign : 0x%x\r\n");
Compare(m_object[0], GetCurrentObject(hDC, OBJ_PEN), "Pen : 0x%08x\r\n");
Compare(m_object[1], GetCurrentObject(hDC, OBJ_BRUSH), "Brush : 0x%08x\r\n");
Compare(m_object[2], GetCurrentObject(hDC, OBJ_FONT), "Font : 0x%08x\r\n");
Compare(m_object[3], GetCurrentObject(hDC, OBJ_PAL), "Palette : 0x%08x\r\n");
Compare(m_object[4], GetCurrentObject(hDC, OBJ_COLORSPACE), "ColorSpace : 0x%08x\r\n");
Compare(m_object[5], GetCurrentObject(hDC, OBJ_BITMAP), "Bitmap : 0x%08x\r\n");
}
/////////////////////////////////////////////////////////////////
inline void MaptoGray(COLORREF & cr)
{
if ( (cr & 0xFF000000) != PALETTEINDEX(0) ) // not paletteindex
{
BYTE gray = ( GetRValue(cr) * 77 + GetGValue(cr) * 150 + GetBValue(cr) * 29 + 128 ) / 256;
cr = (cr & 0xFF000000) | RGB(gray, gray, gray);
}
}
class KGrayEMF : public KEnumEMF
{
// virtual function to process every EMF record, return 0 to terminate
virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
{
int rslt;
switch ( pEMFR->iType )
{
case EMR_CREATEBRUSHINDIRECT:
{
EMRCREATEBRUSHINDIRECT cbi;
cbi = * (const EMRCREATEBRUSHINDIRECT *) pEMFR;
MaptoGray(cbi.lb.lbColor);
rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & cbi, nObj);
}
break;
case EMR_CREATEPEN:
{
EMRCREATEPEN cp;
cp = * (const EMRCREATEPEN *) pEMFR;
MaptoGray(cp.lopn.lopnColor);
rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & cp, nObj);
}
break;
case EMR_SETTEXTCOLOR:
case EMR_SETBKCOLOR:
{
EMRSETTEXTCOLOR stc;
stc = * (const EMRSETTEXTCOLOR *) pEMFR;
MaptoGray(stc.crColor);
rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & stc, nObj);
}
break;
case EMR_RESERVED_105:
case EMR_RESERVED_106:
case EMR_RESERVED_107:
case EMR_RESERVED_108:
case EMR_RESERVED_109:
case EMR_RESERVED_110:
case EMR_RESERVED_119:
case EMR_RESERVED_120:
rslt = PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
break;
default:
rslt = PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
}
return rslt;
}
};
/*
105 ESCAPE
106 ESCAPE
107 STARTDOC
108 SMALLTEXTOUT
109 FORCEUFIMAPPING
110 NAMEDESCAPE
111 COLORCORRECTPALETTE
112 SETICMPROFILE
113 RSETICMPROFILE
114 ALPHABLEND
115 SETLAYOUT
116 TRANSPARENTBLT
117 ?
118 GRADIENTFILL
119 SETLINKEDUFIS
120 MRSETTEXTJUSTIFICATION
121 COLORMATCHTOTARGET
122 CREATECOLORSPACEW
*/
//////////////////////////////////////////////////////////
class KDelayEMF : public KEnumEMF
{
int m_delay;
// virtual function to process every EMF record, return 0 to terminate
virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
{
Sleep(m_delay);
// MSG msg;
// while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
// {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
return PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
}
public:
KDelayEMF(int delay)
{
m_delay = delay;
}
};
///////////////////////////////////////////////////////////
void KEMFPanel::SetZoom(int newzoom, bool bForce)
{
if ( ! bForce )
{
if ( newzoom==m_zoom )
return;
m_zoom = newzoom;
}
InvalidateRect(m_hWnd, NULL, TRUE);
}
void KEMFPanel::OnDraw(HDC hDC)
{
HPALETTE hOld = NULL;
if ( m_hPalette )
{
hOld = SelectPalette(hDC, m_hPalette, FALSE);
int no = RealizePalette(hDC);
no ++;
}
switch ( m_mode )
{
case 1:
{
KDelayEMF delay(5);
DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & delay, true);
}
break;
case 2:
{
KGrayEMF gray;
DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & gray, true);
}
break;
case 3:
{
KTraceEMF trace((HINSTANCE) GetWindowLong(WindowFromDC(hDC), GWL_HINSTANCE));
trace.Show(false);
HPALETTE hPal = CreateHalftonePalette(hDC);
HPALETTE hOld = SelectPalette(hDC, hPal, TRUE);
trace.m_pLog->Log("/////////////// Before Drawing //////////////\r\n");
trace.CompareDC(hDC);
trace.m_pLog->Log("/////////////// Starting Drawing //////////////\r\n");
DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & trace, true);
trace.m_pLog->Log("/////////////// After Drawing //////////////\r\n");
trace.CompareDC(hDC);
SelectPalette(hDC, hOld, TRUE);
DeleteObject(hPal);
trace.Show(true);
}
break;
default:
DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, NULL, true);
}
m_mode = 0; // reset
if ( hOld )
SelectPalette(hDC, hOld, TRUE);
}
bool KEMFView::Initialize(HINSTANCE hInstance, KStatusWindow * pStatus, HWND hWndFrame,
HENHMETAFILE hEmf, const TCHAR * pFileName)
{
m_hFrame = hWndFrame;
m_hInst = hInstance;
m_pStatus = pStatus;
m_emfpanel.m_hEmf = hEmf;
if ( pFileName )
_tcscpy(m_FileName, pFileName);
RegisterClass(_T("EMFViewClass"), hInstance);
return true;
}
void Map10umToLogical(HDC hDC, RECT & rect)
{
POINT * pPoint = (POINT *) & rect;
// convert from 0.01 mm to pixels for current device
for (int i=0; i<2; i++)
{
int t = GetDeviceCaps(hDC, HORZSIZE) * 100;
pPoint[i].x = ( pPoint[i].x * GetDeviceCaps(hDC, HORZRES) + t/2 ) / t;
t = GetDeviceCaps(hDC, VERTSIZE) * 100;
pPoint[i].y = ( pPoint[i].y * GetDeviceCaps(hDC, VERTRES) + t/2 ) / t;
}
// convert to logical coordinate space
DPtoLP(hDC, pPoint, 2);
}
HENHMETAFILE FilterEMF(HENHMETAFILE hEmf, KEnumEMF & filter)
{
ENHMETAHEADER emh;
GetEnhMetaFileHeader(hEmf, sizeof(emh), & emh);
RECT rcFrame;
memcpy(& rcFrame, & emh.rclFrame, sizeof(RECT));
HDC hDC = QuerySaveEMFFile("Filtered EMF\0", & rcFrame, NULL);
if ( hDC==NULL )
return NULL;
Map10umToLogical(hDC, rcFrame);
filter.EnumEMF(hDC, hEmf, & rcFrame);
return CloseEnhMetaFile(hDC);
}
LRESULT KEMFView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch( uMsg )
{
case WM_CREATE:
m_hWnd = hWnd;
m_hViewMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_VIEWER));
{
RECT rect;
GetClientRect(m_hWnd, & rect);
m_emftree.Create(hWnd, 101, 0, 0, m_nDivision, rect.bottom, m_hInst);
m_emfpanel.CreateEx(WS_EX_CLIENTEDGE, "EMFPanel", NULL, WS_VISIBLE | WS_BORDER | WS_CHILD,
m_nDivision+3, 0, rect.right - m_nDivision+3, rect.bottom, hWnd, NULL, m_hInst);
{
KEmfDC emfdc;
if ( m_emfpanel.m_hEmf )
emfdc.DeCompile(NULL, m_emfpanel.m_hEmf, & m_emftree);
else
emfdc.DeCompile(NULL, m_FileName, & m_emftree, m_emfpanel.m_hEmf);
}
// palette message handling is in KWindow class, which needs m_hPalette to be set
{
HDC hDC = GetDC(hWnd);
m_hPalette = GetEMFPalette(m_emfpanel.m_hEmf, hDC);
m_emfpanel.m_hPalette = m_hPalette;
ReleaseDC(hWnd, hDC);
}
}
return 0;
case WM_SIZE:
MoveWindow( m_emftree.m_hWnd, 0, 0, m_nDivision, HIWORD(lParam), TRUE);
MoveWindow(m_emfpanel.m_hWnd, m_nDivision+3, 0, LOWORD(lParam)-m_nDivision+3, HIWORD(lParam), TRUE);
return 0;
case WM_MOUSEMOVE: // handle split window adjustment
if ( wParam & MK_LBUTTON )
{
if ( GetCapture() != hWnd )
SetCapture(hWnd);
RECT rect;
GetClientRect(hWnd, & rect);
m_nDivision = LOWORD(lParam);
SendMessage(hWnd, WM_SIZE, 0, MAKELONG(rect.right, rect.bottom));
}
else
if ( GetCapture() == hWnd )
ReleaseCapture();
return 0;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDM_FILE_SAVETEXT:
{
KFileDialog fd;
ofstream out;
if ( fd.GetSaveFileName(NULL, "txt", "Text Files") )
{
out.open(fd.m_TitleName);
SimpleEnumerateEMF(m_emfpanel.m_hEmf, out);
out.close();
}
return 0;
}
case IDM_FILE_DECOMPILE:
{
KFileDialog fd;
if ( fd.GetSaveFileName(NULL, "cpp", "C++ Programs") )
{
KEmfDC dc;
dc.DeCompile(fd.m_TitleName, m_emfpanel.m_hEmf, NULL);
}
}
return 0;
case IDM_FILE_FILTER:
{
KGrayEMF gray;
HENHMETAFILE hEmf = FilterEMF(m_emfpanel.m_hEmf, gray);
DeleteEnhMetaFile(hEmf);
}
break;
case IDM_VIEW_DELAY:
{
m_emfpanel.m_mode = 1;
m_emfpanel.SetZoom(0, true);
}
return 0;
case IDM_VIEW_GRAY:
{
m_emfpanel.m_mode = 2;
m_emfpanel.SetZoom(0, true);
}
return 0;
case IDM_VIEW_TRACE:
{
m_emfpanel.m_mode = 3;
m_emfpanel.SetZoom(0, true);
}
return 0;
case IDM_VIEW_ZOOM50:
m_emfpanel.SetZoom(50); return 0;
case IDM_VIEW_ZOOM100:
m_emfpanel.SetZoom(100); return 0;
case IDM_VIEW_ZOOM200:
m_emfpanel.SetZoom(200); return 0;
}
case WM_PALETTECHANGED:
return OnPaletteChanged(hWnd, wParam);
case WM_QUERYNEWPALETTE:
return OnQueryNewPalette();
default:
return CommonMDIChildProc(hWnd, uMsg, wParam, lParam, m_hViewMenu, 4);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?