home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_16 / EMF / EMFView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-16  |  13.5 KB  |  567 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : emfview.cpp                                                         //
  10. //  Description: KEMFView class                                                         //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define INITGUID
  15. #define _WIN32_WINNT 0x0500
  16. #define WINVER         0x0500
  17. #define STRICT
  18.  
  19. #pragma pack(push, 4)
  20. #include <windows.h>
  21. #pragma pack(pop)
  22.  
  23. #include <tchar.h>
  24. #include <assert.h>
  25. #include <fstream.h>
  26. #include <commctrl.h>
  27. #include <fstream.h>
  28.  
  29. #include "..\..\include\win.h"
  30. #include "..\..\include\canvas.h"
  31. #include "..\..\include\mmfile.h"
  32. #include "..\..\include\treeview.h"
  33. #include "..\..\include\emf.h"
  34. #include "..\..\include\filedialog.h"
  35. #include "..\..\include\LogWindow.h"
  36.  
  37. #include "resource.h"
  38. #include "EMFView.h"
  39. #include "EmfDC.h"
  40.  
  41.  
  42. int SimpleEnumerateEMF(HENHMETAFILE hEmf, ofstream & stream)
  43. {
  44.     int size = GetEnhMetaFileBits(hEmf, 0, NULL);
  45.  
  46.     if ( size<=0 )
  47.         return 0;
  48.  
  49.     BYTE * pBuffer = new BYTE[size];
  50.  
  51.     if ( pBuffer==NULL )
  52.         return 0;
  53.  
  54.     GetEnhMetaFileBits(hEmf, size, pBuffer);
  55.  
  56.     const EMR * emr = (const EMR *) pBuffer;
  57.  
  58.     TCHAR mess[MAX_PATH];
  59.  
  60.     int recno = 0;
  61.  
  62.     // enumuerate all EMF records
  63.     while ( (emr->iType>=EMR_MIN) && (emr->iType<=EMR_MAX) )
  64.     {
  65.         recno ++;
  66.  
  67.         wsprintf(mess, "%3d: EMR_%03d (%4d bytes)\n", recno, emr->iType, emr->nSize);
  68.  
  69.         stream << mess;
  70.  
  71.         if ( emr->iType== EMR_EOF )
  72.             break;
  73.  
  74.         emr = (const EMR *) ( ( const char * ) emr + emr->nSize );
  75.     }
  76.  
  77.     delete [] pBuffer;
  78.  
  79.     return recno;
  80. }
  81.  
  82. /////////////////////////////////////////////////////
  83.  
  84. class KTraceEMF : public KEnumEMF
  85. {
  86.     int              m_nSeq;
  87.     KEmfDC          m_emfdc;
  88.  
  89.     int              m_value[32];
  90.     HGDIOBJ          m_object[8];
  91.     FLOAT          m_float[8];
  92.  
  93.     // virtual function to process every EMF record, return 0 to terminate
  94.     virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
  95.     {
  96.         CompareDC(hDC);
  97.  
  98.         m_pLog->Log("%4d: %08x %3d % 6d ", m_nSeq++, pEMFR, pEMFR->iType, pEMFR->nSize);
  99.  
  100.         m_pLog->Log(m_emfdc.DecodeRecord((const EMR *) pEMFR));
  101.         m_pLog->Log("\r\n");
  102.  
  103.         return PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
  104.     }
  105.  
  106. public:
  107.     KLogWindow  * m_pLog;
  108.  
  109.     void CompareDC(HDC hDC);
  110.  
  111.     void Show(bool bShow)
  112.     {
  113.         m_pLog->ShowWindow(bShow);
  114.     }
  115.  
  116.     KTraceEMF(HINSTANCE hInst)
  117.     {
  118.         m_pLog = new KLogWindow; // allocated here, deallocated in WM_NCDESTROY handling
  119.  
  120.         m_pLog->Create(hInst, "EMF Trace");
  121.  
  122.         m_nSeq = 1;
  123.  
  124.         memset(m_value,  0xCD, sizeof(m_value));
  125.         memset(m_object, 0xCD, sizeof(m_object));
  126.         memset(m_float,  0xCD, sizeof(m_float));
  127.     }
  128. };
  129.  
  130.  
  131. #define Compare(value, exp, mess) if (value!=exp) { value = exp; m_pLog->Log(mess, value); }
  132.  
  133. void KTraceEMF::CompareDC(HDC hDC)
  134. {
  135.     Compare(m_value[0],  GetMapMode(hDC),                        "MapMode      : %d\r\n");
  136.     Compare(m_value[1],  GetGraphicsMode(hDC),                    "GraphicsMode : %d\r\n");
  137.     
  138.     XFORM xm;
  139.     GetWorldTransform(hDC, & xm);
  140.     Compare(m_float[0],  xm.eM11,                                "WT.eM11      : %8.5f\r\n");
  141.     Compare(m_float[1],  xm.eM12,                                "WT.eM12      : %8.5f\r\n");
  142.     Compare(m_float[2],  xm.eM21,                                "WT.eM21      : %8.5f\r\n");
  143.     Compare(m_float[3],  xm.eM22,                                "WT.eM22      : %8.5f\r\n");
  144.     Compare(m_float[4],  xm.eDx,                                "WT.eDx       : %8.5f\r\n");
  145.     Compare(m_float[5],  xm.eDy,                                "WT.eDy       : %8.5f\r\n");
  146.  
  147.     Compare(m_value[2],  GetBkMode(hDC),                        "BkMode       : %d\r\n");
  148.     Compare(m_value[3],  GetROP2(hDC),                            "ROP2         : %d\r\n");
  149.     Compare(m_value[4],  ((int)GetTextAlign(hDC)),                "TextAlign    : 0x%x\r\n");
  150.  
  151.     Compare(m_object[0], GetCurrentObject(hDC, OBJ_PEN),        "Pen          : 0x%08x\r\n");
  152.     Compare(m_object[1], GetCurrentObject(hDC, OBJ_BRUSH),        "Brush        : 0x%08x\r\n");
  153.     Compare(m_object[2], GetCurrentObject(hDC, OBJ_FONT),        "Font         : 0x%08x\r\n");
  154.     Compare(m_object[3], GetCurrentObject(hDC, OBJ_PAL),        "Palette      : 0x%08x\r\n");
  155.     Compare(m_object[4], GetCurrentObject(hDC, OBJ_COLORSPACE),    "ColorSpace   : 0x%08x\r\n");
  156.     Compare(m_object[5], GetCurrentObject(hDC, OBJ_BITMAP),        "Bitmap       : 0x%08x\r\n");
  157. }
  158.  
  159.  
  160. /////////////////////////////////////////////////////////////////
  161. inline void MaptoGray(COLORREF & cr)
  162. {
  163.     if ( (cr & 0xFF000000) != PALETTEINDEX(0) ) // not paletteindex
  164.     {
  165.         BYTE gray = ( GetRValue(cr) * 77 + GetGValue(cr) * 150 + GetBValue(cr) * 29 + 128 ) / 256;
  166.     
  167.         cr = (cr & 0xFF000000) | RGB(gray, gray, gray);
  168.     }
  169. }
  170.  
  171.  
  172. class KGrayEMF : public KEnumEMF
  173. {
  174.     // virtual function to process every EMF record, return 0 to terminate
  175.     virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
  176.     {
  177.         int rslt;
  178.  
  179.         switch ( pEMFR->iType )
  180.         {
  181.             case EMR_CREATEBRUSHINDIRECT:
  182.                 {
  183.                     EMRCREATEBRUSHINDIRECT cbi;
  184.  
  185.                     cbi = * (const EMRCREATEBRUSHINDIRECT *) pEMFR;
  186.                     MaptoGray(cbi.lb.lbColor);
  187.                 
  188.                     rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & cbi, nObj);
  189.                 }
  190.                 break;
  191.  
  192.             case EMR_CREATEPEN:
  193.                 {
  194.                     EMRCREATEPEN cp;
  195.  
  196.                     cp = * (const EMRCREATEPEN *) pEMFR;
  197.                     MaptoGray(cp.lopn.lopnColor);
  198.  
  199.                     rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & cp, nObj);
  200.                 }
  201.                 break;
  202.  
  203.             case EMR_SETTEXTCOLOR:
  204.             case EMR_SETBKCOLOR:
  205.                 {
  206.                     EMRSETTEXTCOLOR stc;
  207.  
  208.                     stc = * (const EMRSETTEXTCOLOR *) pEMFR;
  209.                     MaptoGray(stc.crColor);
  210.                 
  211.                     rslt = PlayEnhMetaFileRecord(hDC, pHTable, (const ENHMETARECORD *) & stc, nObj);
  212.                 }
  213.                 break;
  214.             
  215.             case EMR_RESERVED_105:
  216.             case EMR_RESERVED_106:
  217.             case EMR_RESERVED_107:
  218.             case EMR_RESERVED_108:
  219.             case EMR_RESERVED_109:
  220.             case EMR_RESERVED_110:
  221.             case EMR_RESERVED_119:
  222.             case EMR_RESERVED_120:
  223.                 rslt = PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
  224.                 break;
  225.  
  226.             default:
  227.                 rslt = PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
  228.         }
  229.  
  230.         return rslt;
  231.     }
  232. };
  233.  
  234. /*
  235.  
  236. 105 ESCAPE
  237. 106 ESCAPE
  238. 107 STARTDOC
  239. 108 SMALLTEXTOUT
  240. 109 FORCEUFIMAPPING
  241. 110 NAMEDESCAPE
  242. 111 COLORCORRECTPALETTE
  243. 112 SETICMPROFILE
  244. 113 RSETICMPROFILE
  245. 114 ALPHABLEND
  246. 115 SETLAYOUT
  247. 116 TRANSPARENTBLT
  248. 117 ? 
  249. 118 GRADIENTFILL
  250. 119 SETLINKEDUFIS
  251. 120 MRSETTEXTJUSTIFICATION
  252. 121 COLORMATCHTOTARGET
  253. 122 CREATECOLORSPACEW
  254. */
  255.  
  256. //////////////////////////////////////////////////////////
  257.  
  258. class KDelayEMF : public KEnumEMF
  259. {
  260.     int m_delay;
  261.  
  262.     // virtual function to process every EMF record, return 0 to terminate
  263.     virtual int ProcessRecord(HDC hDC, HANDLETABLE * pHTable, const ENHMETARECORD * pEMFR, int nObj)
  264.     {
  265.         Sleep(m_delay);
  266.  
  267. //        MSG msg;
  268.  
  269. //        while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
  270. //        {
  271. //            TranslateMessage(&msg);
  272. //            DispatchMessage(&msg);
  273. //        }
  274.  
  275.         return PlayEnhMetaFileRecord(hDC, pHTable, pEMFR, nObj);
  276.     }
  277.  
  278. public:
  279.     KDelayEMF(int delay)
  280.     {
  281.         m_delay = delay;
  282.     }
  283. };
  284.  
  285.  
  286. ///////////////////////////////////////////////////////////
  287.  
  288. void KEMFPanel::SetZoom(int newzoom, bool bForce)
  289. {
  290.     if ( ! bForce )
  291.     {
  292.         if ( newzoom==m_zoom )
  293.             return;
  294.  
  295.         m_zoom = newzoom;
  296.     }
  297.  
  298.     InvalidateRect(m_hWnd, NULL, TRUE);
  299. }
  300.  
  301.  
  302. void KEMFPanel::OnDraw(HDC hDC)
  303. {
  304.     HPALETTE hOld = NULL;
  305.  
  306.     if ( m_hPalette )
  307.     {
  308.         hOld = SelectPalette(hDC, m_hPalette, FALSE);
  309.         int no = RealizePalette(hDC);
  310.  
  311.         no ++;
  312.     }
  313.  
  314.     switch ( m_mode )
  315.     {
  316.         case 1:
  317.             {
  318.                 KDelayEMF delay(5);
  319.  
  320.                 DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & delay, true);
  321.             }
  322.             break;
  323.  
  324.         case 2:
  325.             {
  326.                 KGrayEMF gray;
  327.  
  328.                 DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & gray, true);
  329.             }
  330.             break;
  331.  
  332.         case 3:
  333.             {
  334.                 KTraceEMF trace((HINSTANCE) GetWindowLong(WindowFromDC(hDC), GWL_HINSTANCE));
  335.  
  336.                 trace.Show(false);
  337.  
  338.                 HPALETTE hPal = CreateHalftonePalette(hDC);
  339.                 HPALETTE hOld = SelectPalette(hDC, hPal, TRUE);
  340.                 
  341.                 trace.m_pLog->Log("/////////////// Before Drawing //////////////\r\n");
  342.                 trace.CompareDC(hDC);
  343.  
  344.                 trace.m_pLog->Log("/////////////// Starting Drawing //////////////\r\n");
  345.                 DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, & trace, true);
  346.  
  347.                 trace.m_pLog->Log("/////////////// After Drawing //////////////\r\n");
  348.                 trace.CompareDC(hDC);
  349.                 
  350.                 SelectPalette(hDC, hOld, TRUE);
  351.                 DeleteObject(hPal);
  352.  
  353.                 trace.Show(true);
  354.             }
  355.             break;
  356.  
  357.         default:
  358.             DisplayEMF(hDC, m_hEmf, 5, 5, m_zoom, m_zoom, NULL, true);
  359.     }
  360.     m_mode = 0; // reset
  361.  
  362.     if ( hOld )
  363.         SelectPalette(hDC, hOld, TRUE);
  364. }
  365.  
  366.  
  367. bool KEMFView::Initialize(HINSTANCE hInstance, KStatusWindow * pStatus, HWND hWndFrame, 
  368.                           HENHMETAFILE hEmf, const TCHAR * pFileName)
  369. {
  370.     m_hFrame    = hWndFrame;
  371.     m_hInst     = hInstance;
  372.     m_pStatus   = pStatus;
  373.     
  374.     m_emfpanel.m_hEmf = hEmf;
  375.  
  376.     if ( pFileName )
  377.         _tcscpy(m_FileName, pFileName);
  378.  
  379.     RegisterClass(_T("EMFViewClass"), hInstance);
  380.         
  381.     return true;
  382. }
  383.  
  384.  
  385. void Map10umToLogical(HDC hDC, RECT & rect)
  386. {
  387.     POINT * pPoint = (POINT *) & rect;
  388.  
  389.     // convert from 0.01 mm to pixels for current device
  390.     for (int i=0; i<2; i++)
  391.     {    
  392.         int       t = GetDeviceCaps(hDC, HORZSIZE) * 100; 
  393.         pPoint[i].x = ( pPoint[i].x * GetDeviceCaps(hDC, HORZRES) + t/2 ) / t;
  394.  
  395.                      t = GetDeviceCaps(hDC, VERTSIZE) * 100;
  396.         pPoint[i].y = ( pPoint[i].y * GetDeviceCaps(hDC, VERTRES) + t/2 ) / t;
  397.     }
  398.  
  399.     // convert to logical coordinate space
  400.     DPtoLP(hDC, pPoint, 2);
  401. }
  402.  
  403.  
  404. HENHMETAFILE FilterEMF(HENHMETAFILE hEmf, KEnumEMF & filter)
  405. {
  406.     ENHMETAHEADER emh;
  407.  
  408.     GetEnhMetaFileHeader(hEmf, sizeof(emh), & emh);
  409.  
  410.     RECT rcFrame;
  411.     memcpy(& rcFrame, & emh.rclFrame, sizeof(RECT));
  412.  
  413.     HDC hDC = QuerySaveEMFFile("Filtered EMF\0", & rcFrame, NULL);
  414.  
  415.     if ( hDC==NULL )
  416.         return NULL;
  417.     
  418.     Map10umToLogical(hDC, rcFrame);
  419.  
  420.     filter.EnumEMF(hDC, hEmf, & rcFrame);
  421.         
  422.     return CloseEnhMetaFile(hDC);
  423. }
  424.  
  425.  
  426. LRESULT KEMFView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  427. {
  428.     switch( uMsg )
  429.     {
  430.         case WM_CREATE:
  431.             m_hWnd        = hWnd;
  432.             m_hViewMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_VIEWER));
  433.  
  434.             {
  435.                 RECT rect;
  436.  
  437.                 GetClientRect(m_hWnd, & rect);
  438.                  m_emftree.Create(hWnd, 101, 0, 0, m_nDivision, rect.bottom, m_hInst);
  439.  
  440.                 m_emfpanel.CreateEx(WS_EX_CLIENTEDGE, "EMFPanel", NULL, WS_VISIBLE | WS_BORDER | WS_CHILD, 
  441.                         m_nDivision+3, 0, rect.right - m_nDivision+3, rect.bottom, hWnd, NULL, m_hInst);
  442.  
  443.                 {
  444.                     KEmfDC emfdc;
  445.  
  446.                     if ( m_emfpanel.m_hEmf )
  447.                         emfdc.DeCompile(NULL, m_emfpanel.m_hEmf, & m_emftree);
  448.                     else
  449.                         emfdc.DeCompile(NULL, m_FileName, & m_emftree, m_emfpanel.m_hEmf);
  450.                 }
  451.  
  452.                 // palette message handling is in KWindow class, which needs m_hPalette to be set
  453.                 {
  454.                     HDC hDC = GetDC(hWnd);
  455.                     
  456.                     m_hPalette = GetEMFPalette(m_emfpanel.m_hEmf, hDC);
  457.  
  458.                     m_emfpanel.m_hPalette = m_hPalette;
  459.                     ReleaseDC(hWnd, hDC);
  460.                 }
  461.             }
  462.  
  463.             return 0;
  464.  
  465.         case WM_SIZE:
  466.             MoveWindow( m_emftree.m_hWnd,  0, 0, m_nDivision, HIWORD(lParam), TRUE);    
  467.             MoveWindow(m_emfpanel.m_hWnd, m_nDivision+3, 0, LOWORD(lParam)-m_nDivision+3, HIWORD(lParam), TRUE);    
  468.             return 0;
  469.  
  470.         case WM_MOUSEMOVE: // handle split window adjustment
  471.             if ( wParam & MK_LBUTTON )
  472.             {
  473.                 if ( GetCapture() != hWnd )
  474.                     SetCapture(hWnd);
  475.             
  476.                 RECT rect;
  477.                 GetClientRect(hWnd, & rect);
  478.  
  479.                 m_nDivision = LOWORD(lParam);
  480.                 SendMessage(hWnd, WM_SIZE, 0, MAKELONG(rect.right, rect.bottom));
  481.             }
  482.             else
  483.                 if ( GetCapture() == hWnd )
  484.                     ReleaseCapture();
  485.             return 0;
  486.  
  487.         case WM_COMMAND:
  488.             switch ( LOWORD(wParam) )
  489.             {
  490.                 case IDM_FILE_SAVETEXT:
  491.                     {
  492.                         KFileDialog fd;
  493.                         ofstream    out;
  494.  
  495.                         if ( fd.GetSaveFileName(NULL, "txt", "Text Files") )
  496.                         {
  497.                             out.open(fd.m_TitleName);
  498.                             SimpleEnumerateEMF(m_emfpanel.m_hEmf, out);
  499.                             out.close();
  500.                         }
  501.                         return 0;
  502.                     }
  503.  
  504.                 case IDM_FILE_DECOMPILE:
  505.                     {
  506.                         KFileDialog fd;
  507.  
  508.                         if ( fd.GetSaveFileName(NULL, "cpp", "C++ Programs") )
  509.                         {
  510.                             KEmfDC dc;
  511.                             dc.DeCompile(fd.m_TitleName, m_emfpanel.m_hEmf, NULL);
  512.                         }
  513.                     }
  514.                     return 0;
  515.  
  516.                 case IDM_FILE_FILTER:
  517.                     {
  518.                         KGrayEMF gray;
  519.  
  520.                         HENHMETAFILE hEmf = FilterEMF(m_emfpanel.m_hEmf, gray);
  521.                         DeleteEnhMetaFile(hEmf);
  522.                     }
  523.                     break;
  524.  
  525.                 case IDM_VIEW_DELAY:
  526.                     {
  527.                         m_emfpanel.m_mode = 1;
  528.                         m_emfpanel.SetZoom(0, true);
  529.                     }
  530.                     return 0;
  531.  
  532.  
  533.                 case IDM_VIEW_GRAY:
  534.                     {
  535.                         m_emfpanel.m_mode = 2;
  536.                         m_emfpanel.SetZoom(0, true);
  537.                     }
  538.                     return 0;
  539.  
  540.                 case IDM_VIEW_TRACE:
  541.                     {
  542.                         m_emfpanel.m_mode = 3;
  543.                         m_emfpanel.SetZoom(0, true);
  544.                     }
  545.                     return 0;
  546.  
  547.                 case IDM_VIEW_ZOOM50:
  548.                     m_emfpanel.SetZoom(50); return 0;
  549.  
  550.                 case IDM_VIEW_ZOOM100:
  551.                     m_emfpanel.SetZoom(100); return 0;
  552.  
  553.                 case IDM_VIEW_ZOOM200:
  554.                     m_emfpanel.SetZoom(200); return 0;
  555.             }
  556.  
  557.         case WM_PALETTECHANGED:
  558.             return OnPaletteChanged(hWnd, wParam);
  559.  
  560.         case WM_QUERYNEWPALETTE:
  561.             return OnQueryNewPalette();
  562.             
  563.         default:
  564.             return CommonMDIChildProc(hWnd, uMsg, wParam, lParam, m_hViewMenu, 4);
  565.     }
  566. }
  567.