/*********************************************************************** MODULE : WMFMETA.CPP FUNCTIONS : MetaEnumProc GetMetaFileAndEnum LoadParameterLB PlayMetaFileToDest RenderClipMeta RenderPlaceableMeta SetPlaceableExts SetClipMetaExts ProcessFile COMMENTS : ************************************************************************/ #include #include #include #include #include #include extern "C" { #include "mfdcod32.h" } extern "C" { extern BOOL bConvertToGdiPlus; extern BOOL bUseGdiPlusToPlay; } #include "GdiPlus.h" #include "MyData.hpp" #include "dibstream.hpp" #include "../gpinit.inc" #ifndef ASSERT #ifdef _DEBUG // poor man's assert #define ASSERT(cond) if (!(cond)) { int b = 0; b = 1 / b; } #else #define ASSERT(cond) #endif #endif // Check if a source is needed in a 3-way bitblt operation. // This works on both rop and rop3. We assume that a rop contains zero // in the high byte. // // This is tested by comparing the rop result bits with source (column A // below) vs. those without source (column B). If the two cases are // identical, then the effect of the rop does not depend on the source // and we don't need a source device. Recall the rop construction from // input (pattern, source, target --> result): // // P S T | R A B mask for A = 0CCh // ------+-------- mask for B = 33h // 0 0 0 | x 0 x // 0 0 1 | x 0 x // 0 1 0 | x x 0 // 0 1 1 | x x 0 // 1 0 0 | x 0 x // 1 0 1 | x 0 x // 1 1 0 | x x 0 // 1 1 1 | x x 0 #define ISSOURCEINROP3(rop3) \ (((rop3) & 0xCCCC0000) != (((rop3) << 2) & 0xCCCC0000)) #ifndef EMR_SETICMMODE #define EMR_SETICMMODE 98 #define EMR_CREATECOLORSPACE 99 #define EMR_SETCOLORSPACE 100 #define EMR_DELETECOLORSPACE 101 #define EMR_GLSRECORD 102 #define EMR_GLSBOUNDEDRECORD 103 #define EMR_PIXELFORMAT 104 #endif #ifndef EMR_DRAWESCAPE #define EMR_DRAWESCAPE 105 #define EMR_EXTESCAPE 106 #define EMR_STARTDOC 107 #define EMR_SMALLTEXTOUT 108 #define EMR_FORCEUFIMAPPING 109 #define EMR_NAMEDESCAPE 110 #define EMR_COLORCORRECTPALETTE 111 #define EMR_SETICMPROFILEA 112 #define EMR_SETICMPROFILEW 113 #define EMR_ALPHABLEND 114 #define EMR_SETLAYOUT 115 #define EMR_TRANSPARENTBLT 116 #define EMR_GRADIENTFILL 118 #define EMR_SETLINKEDUFIS 119 #define EMR_SETTEXTJUSTIFICATION 120 #define EMR_COLORMATCHTOTARGETW 121 #define EMR_CREATECOLORSPACEW 122 #endif #define TOREAL(i) (static_cast(i)) // // Wrap a GDI+ TextureBrush object around DIB data // class DibBrush { public: DibBrush(const BITMAPINFO* bmi, const BYTE* bits) : dibStream(bmi, bits), bitmap(&dibStream), brush(&bitmap) { } operator Gdiplus::TextureBrush*() { return &brush; } private: DibStream dibStream; Gdiplus::Bitmap bitmap; Gdiplus::TextureBrush brush; }; // //lookup table for EMF and WMF metafile records // EMFMETARECORDS emfMetaRecords[] = { "WmfSetBkColor" , Gdiplus::WmfRecordTypeSetBkColor , "WmfSetBkMode" , Gdiplus::WmfRecordTypeSetBkMode , "WmfSetMapMode" , Gdiplus::WmfRecordTypeSetMapMode , "WmfSetROP2" , Gdiplus::WmfRecordTypeSetROP2 , "WmfSetRelAbs" , Gdiplus::WmfRecordTypeSetRelAbs , "WmfSetPolyFillMode" , Gdiplus::WmfRecordTypeSetPolyFillMode , "WmfSetStretchBltMode" , Gdiplus::WmfRecordTypeSetStretchBltMode , "WmfSetTextCharExtra" , Gdiplus::WmfRecordTypeSetTextCharExtra , "WmfSetTextColor" , Gdiplus::WmfRecordTypeSetTextColor , "WmfSetTextJustification" , Gdiplus::WmfRecordTypeSetTextJustification , "WmfSetWindowOrg" , Gdiplus::WmfRecordTypeSetWindowOrg , "WmfSetWindowExt" , Gdiplus::WmfRecordTypeSetWindowExt , "WmfSetViewportOrg" , Gdiplus::WmfRecordTypeSetViewportOrg , "WmfSetViewportExt" , Gdiplus::WmfRecordTypeSetViewportExt , "WmfOffsetWindowOrg" , Gdiplus::WmfRecordTypeOffsetWindowOrg , "WmfScaleWindowExt" , Gdiplus::WmfRecordTypeScaleWindowExt , "WmfOffsetViewportOrg" , Gdiplus::WmfRecordTypeOffsetViewportOrg , "WmfScaleViewportExt" , Gdiplus::WmfRecordTypeScaleViewportExt , "WmfLineTo" , Gdiplus::WmfRecordTypeLineTo , "WmfMoveTo" , Gdiplus::WmfRecordTypeMoveTo , "WmfExcludeClipRect" , Gdiplus::WmfRecordTypeExcludeClipRect , "WmfIntersectClipRect" , Gdiplus::WmfRecordTypeIntersectClipRect , "WmfArc" , Gdiplus::WmfRecordTypeArc , "WmfEllipse" , Gdiplus::WmfRecordTypeEllipse , "WmfFloodFill" , Gdiplus::WmfRecordTypeFloodFill , "WmfPie" , Gdiplus::WmfRecordTypePie , "WmfRectangle" , Gdiplus::WmfRecordTypeRectangle , "WmfRoundRect" , Gdiplus::WmfRecordTypeRoundRect , "WmfPatBlt" , Gdiplus::WmfRecordTypePatBlt , "WmfSaveDC" , Gdiplus::WmfRecordTypeSaveDC , "WmfSetPixel" , Gdiplus::WmfRecordTypeSetPixel , "WmfOffsetClipRgn" , Gdiplus::WmfRecordTypeOffsetClipRgn , "WmfTextOut" , Gdiplus::WmfRecordTypeTextOut , "WmfBitBlt" , Gdiplus::WmfRecordTypeBitBlt , "WmfStretchBlt" , Gdiplus::WmfRecordTypeStretchBlt , "WmfPolygon" , Gdiplus::WmfRecordTypePolygon , "WmfPolyline" , Gdiplus::WmfRecordTypePolyline , "WmfEscape" , Gdiplus::WmfRecordTypeEscape , "WmfRestoreDC" , Gdiplus::WmfRecordTypeRestoreDC , "WmfFillRegion" , Gdiplus::WmfRecordTypeFillRegion , "WmfFrameRegion" , Gdiplus::WmfRecordTypeFrameRegion , "WmfInvertRegion" , Gdiplus::WmfRecordTypeInvertRegion , "WmfPaintRegion" , Gdiplus::WmfRecordTypePaintRegion , "WmfSelectClipRegion" , Gdiplus::WmfRecordTypeSelectClipRegion , "WmfSelectObject" , Gdiplus::WmfRecordTypeSelectObject , "WmfSetTextAlign" , Gdiplus::WmfRecordTypeSetTextAlign , "WmfDrawText" , Gdiplus::WmfRecordTypeDrawText , "WmfChord" , Gdiplus::WmfRecordTypeChord , "WmfSetMapperFlags" , Gdiplus::WmfRecordTypeSetMapperFlags , "WmfExtTextOut" , Gdiplus::WmfRecordTypeExtTextOut , "WmfSetDIBToDev" , Gdiplus::WmfRecordTypeSetDIBToDev , "WmfSelectPalette" , Gdiplus::WmfRecordTypeSelectPalette , "WmfRealizePalette" , Gdiplus::WmfRecordTypeRealizePalette , "WmfAnimatePalette" , Gdiplus::WmfRecordTypeAnimatePalette , "WmfSetPalEntries" , Gdiplus::WmfRecordTypeSetPalEntries , "WmfPolyPolygon" , Gdiplus::WmfRecordTypePolyPolygon , "WmfResizePalette" , Gdiplus::WmfRecordTypeResizePalette , "WmfDIBBitBlt" , Gdiplus::WmfRecordTypeDIBBitBlt , "WmfDIBStretchBlt" , Gdiplus::WmfRecordTypeDIBStretchBlt , "WmfDIBCreatePatternBrush" , Gdiplus::WmfRecordTypeDIBCreatePatternBrush , "WmfStretchDIB" , Gdiplus::WmfRecordTypeStretchDIB , "WmfExtFloodFill" , Gdiplus::WmfRecordTypeExtFloodFill , "WmfSetLayout" , Gdiplus::WmfRecordTypeSetLayout , "WmfResetDC" , Gdiplus::WmfRecordTypeResetDC , "WmfStartDoc" , Gdiplus::WmfRecordTypeStartDoc , "WmfStartPage" , Gdiplus::WmfRecordTypeStartPage , "WmfEndPage" , Gdiplus::WmfRecordTypeEndPage , "WmfAbortDoc" , Gdiplus::WmfRecordTypeAbortDoc , "WmfEndDoc" , Gdiplus::WmfRecordTypeEndDoc , "WmfDeleteObject" , Gdiplus::WmfRecordTypeDeleteObject , "WmfCreatePalette" , Gdiplus::WmfRecordTypeCreatePalette , "WmfCreateBrush" , Gdiplus::WmfRecordTypeCreateBrush , "WmfCreatePatternBrush" , Gdiplus::WmfRecordTypeCreatePatternBrush , "WmfCreatePenIndirect" , Gdiplus::WmfRecordTypeCreatePenIndirect , "WmfCreateFontIndirect" , Gdiplus::WmfRecordTypeCreateFontIndirect , "WmfCreateBrushIndirect" , Gdiplus::WmfRecordTypeCreateBrushIndirect , "WmfCreateBitmapIndirect" , Gdiplus::WmfRecordTypeCreateBitmapIndirect , "WmfCreateBitmap" , Gdiplus::WmfRecordTypeCreateBitmap , "WmfCreateRegion" , Gdiplus::WmfRecordTypeCreateRegion , "EmfHeader" , Gdiplus::EmfRecordTypeHeader , "EmfPolyBezier" , Gdiplus::EmfRecordTypePolyBezier , "EmfPolygon" , Gdiplus::EmfRecordTypePolygon , "EmfPolyline" , Gdiplus::EmfRecordTypePolyline , "EmfPolyBezierTo" , Gdiplus::EmfRecordTypePolyBezierTo , "EmfPolyLineTo" , Gdiplus::EmfRecordTypePolyLineTo , "EmfPolyPolyline" , Gdiplus::EmfRecordTypePolyPolyline , "EmfPolyPolygon" , Gdiplus::EmfRecordTypePolyPolygon , "EmfSetWindowExtEx" , Gdiplus::EmfRecordTypeSetWindowExtEx , "EmfSetWindowOrgEx" , Gdiplus::EmfRecordTypeSetWindowOrgEx , "EmfSetViewportExtEx" , Gdiplus::EmfRecordTypeSetViewportExtEx , "EmfSetViewportOrgEx" , Gdiplus::EmfRecordTypeSetViewportOrgEx , "EmfSetBrushOrgEx" , Gdiplus::EmfRecordTypeSetBrushOrgEx , "EmfEOF" , Gdiplus::EmfRecordTypeEOF , "EmfSetPixelV" , Gdiplus::EmfRecordTypeSetPixelV , "EmfSetMapperFlags" , Gdiplus::EmfRecordTypeSetMapperFlags , "EmfSetMapMode" , Gdiplus::EmfRecordTypeSetMapMode , "EmfSetBkMode" , Gdiplus::EmfRecordTypeSetBkMode , "EmfSetPolyFillMode" , Gdiplus::EmfRecordTypeSetPolyFillMode , "EmfSetROP2" , Gdiplus::EmfRecordTypeSetROP2 , "EmfSetStretchBltMode" , Gdiplus::EmfRecordTypeSetStretchBltMode , "EmfSetTextAlign" , Gdiplus::EmfRecordTypeSetTextAlign , "EmfSetColorAdjustment" , Gdiplus::EmfRecordTypeSetColorAdjustment , "EmfSetTextColor" , Gdiplus::EmfRecordTypeSetTextColor , "EmfSetBkColor" , Gdiplus::EmfRecordTypeSetBkColor , "EmfOffsetClipRgn" , Gdiplus::EmfRecordTypeOffsetClipRgn , "EmfMoveToEx" , Gdiplus::EmfRecordTypeMoveToEx , "EmfSetMetaRgn" , Gdiplus::EmfRecordTypeSetMetaRgn , "EmfExcludeClipRect" , Gdiplus::EmfRecordTypeExcludeClipRect , "EmfIntersectClipRect" , Gdiplus::EmfRecordTypeIntersectClipRect , "EmfScaleViewportExtEx" , Gdiplus::EmfRecordTypeScaleViewportExtEx , "EmfScaleWindowExtEx" , Gdiplus::EmfRecordTypeScaleWindowExtEx , "EmfSaveDC" , Gdiplus::EmfRecordTypeSaveDC , "EmfRestoreDC" , Gdiplus::EmfRecordTypeRestoreDC , "EmfSetWorldTransform" , Gdiplus::EmfRecordTypeSetWorldTransform , "EmfModifyWorldTransform" , Gdiplus::EmfRecordTypeModifyWorldTransform , "EmfSelectObject" , Gdiplus::EmfRecordTypeSelectObject , "EmfCreatePen" , Gdiplus::EmfRecordTypeCreatePen , "EmfCreateBrushIndirect" , Gdiplus::EmfRecordTypeCreateBrushIndirect , "EmfDeleteObject" , Gdiplus::EmfRecordTypeDeleteObject , "EmfAngleArc" , Gdiplus::EmfRecordTypeAngleArc , "EmfEllipse" , Gdiplus::EmfRecordTypeEllipse , "EmfRectangle" , Gdiplus::EmfRecordTypeRectangle , "EmfRoundRect" , Gdiplus::EmfRecordTypeRoundRect , "EmfArc" , Gdiplus::EmfRecordTypeArc , "EmfChord" , Gdiplus::EmfRecordTypeChord , "EmfPie" , Gdiplus::EmfRecordTypePie , "EmfSelectPalette" , Gdiplus::EmfRecordTypeSelectPalette , "EmfCreatePalette" , Gdiplus::EmfRecordTypeCreatePalette , "EmfSetPaletteEntries" , Gdiplus::EmfRecordTypeSetPaletteEntries , "EmfResizePalette" , Gdiplus::EmfRecordTypeResizePalette , "EmfRealizePalette" , Gdiplus::EmfRecordTypeRealizePalette , "EmfExtFloodFill" , Gdiplus::EmfRecordTypeExtFloodFill , "EmfLineTo" , Gdiplus::EmfRecordTypeLineTo , "EmfArcTo" , Gdiplus::EmfRecordTypeArcTo , "EmfPolyDraw" , Gdiplus::EmfRecordTypePolyDraw , "EmfSetArcDirection" , Gdiplus::EmfRecordTypeSetArcDirection , "EmfSetMiterLimit" , Gdiplus::EmfRecordTypeSetMiterLimit , "EmfBeginPath" , Gdiplus::EmfRecordTypeBeginPath , "EmfEndPath" , Gdiplus::EmfRecordTypeEndPath , "EmfCloseFigure" , Gdiplus::EmfRecordTypeCloseFigure , "EmfFillPath" , Gdiplus::EmfRecordTypeFillPath , "EmfStrokeAndFillPath" , Gdiplus::EmfRecordTypeStrokeAndFillPath , "EmfStrokePath" , Gdiplus::EmfRecordTypeStrokePath , "EmfFlattenPath" , Gdiplus::EmfRecordTypeFlattenPath , "EmfWidenPath" , Gdiplus::EmfRecordTypeWidenPath , "EmfSelectClipPath" , Gdiplus::EmfRecordTypeSelectClipPath , "EmfAbortPath" , Gdiplus::EmfRecordTypeAbortPath , "EmfReserved_069" , Gdiplus::EmfRecordTypeReserved_069 , "EmfGdiComment" , Gdiplus::EmfRecordTypeGdiComment , "EmfFillRgn" , Gdiplus::EmfRecordTypeFillRgn , "EmfFrameRgn" , Gdiplus::EmfRecordTypeFrameRgn , "EmfInvertRgn" , Gdiplus::EmfRecordTypeInvertRgn , "EmfPaintRgn" , Gdiplus::EmfRecordTypePaintRgn , "EmfExtSelectClipRgn" , Gdiplus::EmfRecordTypeExtSelectClipRgn , "EmfBitBlt" , Gdiplus::EmfRecordTypeBitBlt , "EmfStretchBlt" , Gdiplus::EmfRecordTypeStretchBlt , "EmfMaskBlt" , Gdiplus::EmfRecordTypeMaskBlt , "EmfPlgBlt" , Gdiplus::EmfRecordTypePlgBlt , "EmfSetDIBitsToDevice" , Gdiplus::EmfRecordTypeSetDIBitsToDevice , "EmfStretchDIBits" , Gdiplus::EmfRecordTypeStretchDIBits , "EmfExtCreateFontIndirect" , Gdiplus::EmfRecordTypeExtCreateFontIndirect , "EmfExtTextOutA" , Gdiplus::EmfRecordTypeExtTextOutA , "EmfExtTextOutW" , Gdiplus::EmfRecordTypeExtTextOutW , "EmfPolyBezier16" , Gdiplus::EmfRecordTypePolyBezier16 , "EmfPolygon16" , Gdiplus::EmfRecordTypePolygon16 , "EmfPolyline16" , Gdiplus::EmfRecordTypePolyline16 , "EmfPolyBezierTo16" , Gdiplus::EmfRecordTypePolyBezierTo16 , "EmfPolylineTo16" , Gdiplus::EmfRecordTypePolylineTo16 , "EmfPolyPolyline16" , Gdiplus::EmfRecordTypePolyPolyline16 , "EmfPolyPolygon16" , Gdiplus::EmfRecordTypePolyPolygon16 , "EmfPolyDraw16" , Gdiplus::EmfRecordTypePolyDraw16 , "EmfCreateMonoBrush" , Gdiplus::EmfRecordTypeCreateMonoBrush , "EmfCreateDIBPatternBrushPt" , Gdiplus::EmfRecordTypeCreateDIBPatternBrushPt , "EmfExtCreatePen" , Gdiplus::EmfRecordTypeExtCreatePen , "EmfPolyTextOutA" , Gdiplus::EmfRecordTypePolyTextOutA , "EmfPolyTextOutW" , Gdiplus::EmfRecordTypePolyTextOutW , "EmfSetICMMode" , Gdiplus::EmfRecordTypeSetICMMode , "EmfCreateColorSpace" , Gdiplus::EmfRecordTypeCreateColorSpace , "EmfSetColorSpace" , Gdiplus::EmfRecordTypeSetColorSpace , "EmfDeleteColorSpace" , Gdiplus::EmfRecordTypeDeleteColorSpace , "EmfGLSRecord" , Gdiplus::EmfRecordTypeGLSRecord , "EmfGLSBoundedRecord" , Gdiplus::EmfRecordTypeGLSBoundedRecord , "EmfPixelFormat" , Gdiplus::EmfRecordTypePixelFormat , "EmfDrawEscape" , Gdiplus::EmfRecordTypeDrawEscape , "EmfExtEscape" , Gdiplus::EmfRecordTypeExtEscape , "EmfStartDoc" , Gdiplus::EmfRecordTypeStartDoc , "EmfSmallTextOut" , Gdiplus::EmfRecordTypeSmallTextOut , "EmfForceUFIMapping" , Gdiplus::EmfRecordTypeForceUFIMapping , "EmfNamedEscape" , Gdiplus::EmfRecordTypeNamedEscape , "EmfColorCorrectPalette" , Gdiplus::EmfRecordTypeColorCorrectPalette , "EmfSetICMProfileA" , Gdiplus::EmfRecordTypeSetICMProfileA , "EmfSetICMProfileW" , Gdiplus::EmfRecordTypeSetICMProfileW , "EmfAlphaBlend" , Gdiplus::EmfRecordTypeAlphaBlend , "EmfSetLayout" , Gdiplus::EmfRecordTypeSetLayout , "EmfTransparentBlt" , Gdiplus::EmfRecordTypeTransparentBlt , "EmfReserved_117" , Gdiplus::EmfRecordTypeReserved_117 , "EmfGradientFill" , Gdiplus::EmfRecordTypeGradientFill , "EmfSetLinkedUFIs" , Gdiplus::EmfRecordTypeSetLinkedUFIs , "EmfSetTextJustification" , Gdiplus::EmfRecordTypeSetTextJustification , "EmfColorMatchToTargetW" , Gdiplus::EmfRecordTypeColorMatchToTargetW , "EmfCreateColorSpaceW" , Gdiplus::EmfRecordTypeCreateColorSpaceW , "EmfPlusHeader" , Gdiplus::EmfPlusRecordTypeHeader , "EmfPlusEndOfFile" , Gdiplus::EmfPlusRecordTypeEndOfFile , "EmfPlusComment" , Gdiplus::EmfPlusRecordTypeComment , "EmfPlusGetDC" , Gdiplus::EmfPlusRecordTypeGetDC , "EmfPlusMultiFormatStart" , Gdiplus::EmfPlusRecordTypeMultiFormatStart , "EmfPlusMultiFormatSection" , Gdiplus::EmfPlusRecordTypeMultiFormatSection , "EmfPlusMultiFormatEnd" , Gdiplus::EmfPlusRecordTypeMultiFormatEnd , "EmfPlusObject" , Gdiplus::EmfPlusRecordTypeObject , "EmfPlusClear" , Gdiplus::EmfPlusRecordTypeClear , "EmfPlusFillRects" , Gdiplus::EmfPlusRecordTypeFillRects , "EmfPlusDrawRects" , Gdiplus::EmfPlusRecordTypeDrawRects , "EmfPlusFillPolygon" , Gdiplus::EmfPlusRecordTypeFillPolygon , "EmfPlusDrawLines" , Gdiplus::EmfPlusRecordTypeDrawLines , "EmfPlusFillEllipse" , Gdiplus::EmfPlusRecordTypeFillEllipse , "EmfPlusDrawEllipse" , Gdiplus::EmfPlusRecordTypeDrawEllipse , "EmfPlusFillPie" , Gdiplus::EmfPlusRecordTypeFillPie , "EmfPlusDrawPie" , Gdiplus::EmfPlusRecordTypeDrawPie , "EmfPlusDrawArc" , Gdiplus::EmfPlusRecordTypeDrawArc , "EmfPlusFillRegion" , Gdiplus::EmfPlusRecordTypeFillRegion , "EmfPlusFillPath" , Gdiplus::EmfPlusRecordTypeFillPath , "EmfPlusDrawPath" , Gdiplus::EmfPlusRecordTypeDrawPath , "EmfPlusFillClosedCurve" , Gdiplus::EmfPlusRecordTypeFillClosedCurve , "EmfPlusDrawClosedCurve" , Gdiplus::EmfPlusRecordTypeDrawClosedCurve , "EmfPlusDrawCurve" , Gdiplus::EmfPlusRecordTypeDrawCurve , "EmfPlusDrawBeziers" , Gdiplus::EmfPlusRecordTypeDrawBeziers , "EmfPlusDrawImage" , Gdiplus::EmfPlusRecordTypeDrawImage , "EmfPlusDrawImagePoints" , Gdiplus::EmfPlusRecordTypeDrawImagePoints , "EmfPlusDrawString" , Gdiplus::EmfPlusRecordTypeDrawString , "EmfPlusSetRenderingOrigin" , Gdiplus::EmfPlusRecordTypeSetRenderingOrigin , "EmfPlusSetAntiAliasMode" , Gdiplus::EmfPlusRecordTypeSetAntiAliasMode , "EmfPlusSetTextRenderingHint" , Gdiplus::EmfPlusRecordTypeSetTextRenderingHint , "EmfPlusSetTextContrast" , Gdiplus::EmfPlusRecordTypeSetTextContrast , "EmfPlusSetInterpolationMode" , Gdiplus::EmfPlusRecordTypeSetInterpolationMode , "EmfPlusSetPixelOffsetMode" , Gdiplus::EmfPlusRecordTypeSetPixelOffsetMode , "EmfPlusSetCompositingMode" , Gdiplus::EmfPlusRecordTypeSetCompositingMode , "EmfPlusSetCompositingQuality" , Gdiplus::EmfPlusRecordTypeSetCompositingQuality , "EmfPlusSave" , Gdiplus::EmfPlusRecordTypeSave , "EmfPlusRestore" , Gdiplus::EmfPlusRecordTypeRestore , "EmfPlusBeginContainer" , Gdiplus::EmfPlusRecordTypeBeginContainer , "EmfPlusBeginContainerNoParams" , Gdiplus::EmfPlusRecordTypeBeginContainerNoParams , "EmfPlusEndContainer" , Gdiplus::EmfPlusRecordTypeEndContainer , "EmfPlusSetWorldTransform" , Gdiplus::EmfPlusRecordTypeSetWorldTransform , "EmfPlusResetWorldTransform" , Gdiplus::EmfPlusRecordTypeResetWorldTransform , "EmfPlusMultiplyWorldTransform" , Gdiplus::EmfPlusRecordTypeMultiplyWorldTransform , "EmfPlusTranslateWorldTransform" , Gdiplus::EmfPlusRecordTypeTranslateWorldTransform, "EmfPlusScaleWorldTransform" , Gdiplus::EmfPlusRecordTypeScaleWorldTransform , "EmfPlusRotateWorldTransform" , Gdiplus::EmfPlusRecordTypeRotateWorldTransform , "EmfPlusSetPageTransform" , Gdiplus::EmfPlusRecordTypeSetPageTransform , "EmfPlusResetClip" , Gdiplus::EmfPlusRecordTypeResetClip , "EmfPlusSetClipRect" , Gdiplus::EmfPlusRecordTypeSetClipRect , "EmfPlusSetClipPath" , Gdiplus::EmfPlusRecordTypeSetClipPath , "EmfPlusSetClipRegion" , Gdiplus::EmfPlusRecordTypeSetClipRegion , "EmfPlusOffsetClip" , Gdiplus::EmfPlusRecordTypeOffsetClip , "EmfPlusDrawDriverString" , Gdiplus::EmfPlusRecordTypeDrawDriverString , }; /* METAFUNCTIONS MetaFunctions[] = { "SETBKCOLOR", 0x0201, "SETBKMODE", 0x0102, "SETMAPMODE", 0x0103, "SETROP2", 0x0104, "SETRELABS", 0x0105, "SETPOLYFILLMODE", 0x0106, "SETSTRETCHBLTMODE", 0x0107, "SETTEXTCHAREXTRA", 0x0108, "SETTEXTCOLOR", 0x0209, "SETTEXTJUSTIFICATION", 0x020A, "SETWINDOWORG", 0x020B, "SETWINDOWEXT", 0x020C, "SETVIEWPORTORG", 0x020D, "SETVIEWPORTEXT", 0x020E, "OFFSETWINDOWORG", 0x020F, "SCALEWINDOWEXT", 0x0400, "OFFSETVIEWPORTORG", 0x0211, "SCALEVIEWPORTEXT", 0x0412, "LINETO", 0x0213, "MOVETO", 0x0214, "EXCLUDECLIPRECT", 0x0415, "INTERSECTCLIPRECT", 0x0416, "ARC", 0x0817, "ELLIPSE", 0x0418, "FLOODFILL", 0x0419, "PIE", 0x081A, "RECTANGLE", 0x041B, "ROUNDRECT", 0x061C, "PATBLT", 0x061D, "SAVEDC", 0x001E, "SETPIXEL", 0x041F, "OFFSETCLIPRGN", 0x0220, "TEXTOUT", 0x0521, "BITBLT", 0x0922, "STRETCHBLT", 0x0B23, "POLYGON", 0x0324, "POLYLINE", 0x0325, "ESCAPE", 0x0626, "RESTOREDC", 0x0127, "FILLREGION", 0x0228, "FRAMEREGION", 0x0429, "INVERTREGION", 0x012A, "PAINTREGION", 0x012B, "SELECTCLIPREGION", 0x012C, "SELECTOBJECT", 0x012D, "SETTEXTALIGN", 0x012E, "DRAWTEXT", 0x062F, "CHORD", 0x0830, "SETMAPPERFLAGS", 0x0231, "EXTTEXTOUT", 0x0a32, "SETDIBTODEV", 0x0d33, "SELECTPALETTE", 0x0234, "REALIZEPALETTE", 0x0035, "ANIMATEPALETTE", 0x0436, "SETPALENTRIES", 0x0037, "POLYPOLYGON", 0x0538, "RESIZEPALETTE", 0x0139, "DIBBITBLT", 0x0940, "DIBSTRETCHBLT", 0x0b41, "DIBCREATEPATTERNBRUSH",0x0142, "STRETCHDIB", 0x0f43, "DELETEOBJECT", 0x01f0, "CREATEPALETTE", 0x00f7, "CREATEBRUSH", 0x00F8, "CREATEPATTERNBRUSH", 0x01F9, "CREATEPENINDIRECT", 0x02FA, "CREATEFONTINDIRECT", 0x02FB, "CREATEBRUSHINDIRECT", 0x02FC, "CREATEBITMAPINDIRECT", 0x02FD, "CREATEBITMAP", 0x06FE, "CREATEREGION", 0x06FF, }; */ /*********************************************************************** FUNCTION : MetaEnumProc PARAMETERS : HDC hDC LPHANDLETABLE lpHTable LPMETARECORD lpMFR int nObj LPARAM lpClientData PURPOSE : callback for EnumMetaFile. CALLS : EnumMFIndirect() MESSAGES : none RETURNS : int COMMENTS : HISTORY : 1/16/91 - created - drc 5/6/93 - modified for Win32 - denniscr ************************************************************************/ int CALLBACK MetaEnumProc( HDC hDC, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, int nObj, LPARAM lpClientData) { return EnumMFIndirect(hDC, lpHTable, lpMFR, NULL, nObj, lpClientData); } /*********************************************************************** FUNCTION : LoadParameterLB PARAMETERS : HWND hDlg DWORD dwParams int nRadix - HEX to display contents in base 16 DEC to display contents in base 10 PURPOSE : display the parameters of the metafile record in the parameter listbox CALLS : WINDOWS GlobalLock GlobalUnlock SendDlgItemMessage wsprintf lstrlen MESSAGES : WM_SETREDRAW WM_RESETCONTENT LB_ADDSTRING RETURNS : BOOL COMMENTS : HISTORY : 1/16/91 - created - drc ************************************************************************/ BOOL LoadParameterLB( HWND hDlg, DWORD dwParams, int nRadix) { DWORD i; BYTE nHiByte, nLoByte; BYTE nHiByteHi, nLoByteHi; WORD wHiWord, wLoWord; char szBuffer[40]; char szDump[100]; int iValue = 0; DWORD dwValue = 0; switch (nRadix) /* if nRadix is not a valid value, return FALSE */ { case IDB_HEX: case IDB_DEC: case IDB_CHAR: case IDB_WORD: break; default : return FALSE; } // //init the strings // *szBuffer = '\0'; *szDump = '\0'; // //turn off redrawing of the listbox // SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, FALSE, 0L); // //reset the contents of the listbox // SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_RESETCONTENT, 0, 0L); // don't load an entire bitmap or other image into the dialog in hex if (dwParams > 1024) { dwParams = 1024; } if (bEnhMeta) { // //lock the memory where the parameters can be found // if (NULL == (lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem))) return (FALSE); // //loop through the metafile record parameters // for (i = 0; i < dwParams; i++) { /* get the high and low byte of the parameter word */ wHiWord = HIWORD(lpEMFParams[i]); wLoWord = LOWORD(lpEMFParams[i]); nLoByteHi = LOBYTE(wHiWord); nHiByteHi = HIBYTE(wHiWord); nLoByte = LOBYTE(wLoWord); nHiByte = HIBYTE(wLoWord); switch (nRadix) { case IDB_HEX: /* if we are to display as hexadecimal */ /* format the bytes for the hex part of dump */ wsprintf((LPSTR)szBuffer, (LPSTR)"%08x ", lpEMFParams[i]); break; case IDB_DEC: /* format the bytes for the decimal part of dump */ dwValue = lpEMFParams[i]; wsprintf((LPSTR)szBuffer, (LPSTR)"%lu ", dwValue ); break; case IDB_CHAR: wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c%c%c", (nLoByte > 0x20) ? nLoByte : 0x2E, (nHiByte > 0x20) ? nHiByte : 0x2E, (nLoByteHi > 0x20) ? nLoByteHi : 0x2E, (nHiByteHi > 0x20) ? nHiByteHi : 0x2E); break; case IDB_WORD: /* if we are to display as hexadecimal */ /* format the bytes for the hex part of dump */ wsprintf((LPSTR)szBuffer, (LPSTR)"%04x %04x ", wLoWord, wHiWord ); break; default : return FALSE; } /* concatenate it onto whatever we have already formatted */ lstrcat((LPSTR)szDump, (LPSTR)szBuffer); /* use every 8 words for hex/dec dump */ if (!((i + 1) % 4)) { /*add the string to the listbox */ SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump); /* re-init the hex/dec strings in preparation for next 8 words */ *szDump = '\0'; } } } else { /* lock the memory where the parameters can be found */ if (NULL == (lpMFParams = (LPPARAMETERS)GlobalLock(hMem))) return (FALSE); /* loop through the metafile record parameters */ for (i = 0; i < dwParams; i++) { /* get the high and low byte of the parameter word */ nHiByte = HIBYTE(lpMFParams[i]); nLoByte = LOBYTE(lpMFParams[i]); switch (nRadix) { case IDB_HEX: /* if we are to display as hexadecimal */ /* format the bytes for the hex part of dump */ wsprintf((LPSTR)szBuffer, (LPSTR)"%02x %02x ", nLoByte, nHiByte ); break; case IDB_DEC: /* format the bytes for the decimal part of dump */ iValue = lpMFParams[i]; wsprintf((LPSTR)szBuffer, (LPSTR)"%d ", iValue ); break; case IDB_CHAR: wsprintf((LPSTR)szBuffer, (LPSTR)"%c%c", (nLoByte > 0x20) ? nLoByte : 0x2E, (nHiByte > 0x20) ? nHiByte : 0x2E); break; case IDB_WORD: /* if we are to display as hexadecimal */ /* format the bytes for the hex part of dump */ wsprintf((LPSTR)szBuffer, (LPSTR)"%02x%02x ", nHiByte, nLoByte ); break; default : return FALSE; } /* concatenate it onto whatever we have already formatted */ lstrcat((LPSTR)szDump, (LPSTR)szBuffer); /* use every 8 words for hex/dec dump */ if (!((i + 1) % 8)) { /*add the string to the listbox */ SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump); /* re-init the hex/dec strings in preparation for next 8 words */ *szDump = '\0'; } } } //else // //dump any leftover hex/dec dump // if (lstrlen((LPSTR)szDump)) SendDlgItemMessage(hDlg, IDL_PARAMETERS, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szDump); // //enable redraw to the listbox // SendDlgItemMessage(hDlg, IDL_PARAMETERS, WM_SETREDRAW, TRUE, 0L); // //redraw it // InvalidateRect(GetDlgItem(hDlg,IDL_PARAMETERS), NULL, TRUE); // //unlock the memory used for the parameters // GlobalUnlock(hMem); return (TRUE); } extern "C" void GetMetaFileAndEnum( HWND hwnd, HDC hDC, int iAction); /*********************************************************************** FUNCTION : PlayMetaFileToDest PARAMETERS : HWND hWnd int nDest - DC to play metafile to DESTDISPLAY - play to the display DESTMETA - play into another metafile PURPOSE : begin the enumeration of the metafile to the user selected destination. Perform the housekeeping needs appropriate to that destination. CALLS : WINDOWS GetClientRect InvalidateRect GetDC SetMapMode OpenFileDialog MessageBox CreateMetaFile DeleteMetaFile CloseMetaFile APP WaitCursor SetClipMetaExts SetPlaceableExts GetMetaFileAndEnum MESSAGES : none RETURNS : int COMMENTS : HISTORY : 1/16/91 - created - drc ************************************************************************/ BOOL PlayMetaFileToDest( HWND hWnd, int nDest) { HDC hDC; RECT rect; int iSaveRet; // //if the file opened contained a valid metafile // if (bValidFile) { // //init the record count // iRecNum = 0; // //if we are stepping the metafile then clear the client area // if (!bPlayItAll) { GetClientRect(hWnd, (LPRECT)&rect); InvalidateRect(hWnd, (LPRECT)&rect, TRUE); } switch (nDest) { // //playing metafile to the display // case DESTDISPLAY: WaitCursor(TRUE); hDC = GetDC(hWnd); if (!bUseGdiPlusToPlay) { // //metafile read in from a clipboard file // if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta) SetClipMetaExts(hDC, lpMFP, lpOldMFP, WMFDISPLAY); // //Windows placeable metafile // if (bPlaceableMeta && !bEnhMeta) SetPlaceableExts(hDC, placeableWMFHeader, WMFDISPLAY); // //Windows metafile // if (!bMetaInRam && !bEnhMeta) { SetNonPlaceableExts(hDC, WMFDISPLAY); } } // //begin the enumeration of the metafile // DWORD start, end; DWORD renderTime; char tmpBuf[512]; start = GetTickCount(); GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP); end = GetTickCount(); renderTime = end - start; wsprintf(tmpBuf, "Time: %d", renderTime); SetWindowText(hWnd, tmpBuf); ReleaseDC(hWnd, hDC); WaitCursor(FALSE); break; case DESTMETA: // //get a name of a file to play the metafile into // iSaveRet = SaveFileDialog((LPSTR)SaveName, (LPSTR)gszSaveEMFFilter); // //if the file selected is this metafile then warn user // if (!lstrcmp((LPSTR)OpenName, (LPSTR)SaveName)) MessageBox(hWnd, (LPSTR)"Cannot overwrite the opened metafile!", (LPSTR)"Play to Metafile", MB_OK | MB_ICONEXCLAMATION); else // //the user didn't hit the cancel button // if (iSaveRet) { WaitCursor(TRUE); // //create a disk based metafile // hDC = (bEnhMeta) ? CreateEnhMetaFile(NULL, (LPSTR)SaveName, NULL, NULL) : CreateMetaFile((LPSTR)SaveName); // //begin the enumeration of the metafile // GetMetaFileAndEnum(hWnd, hDC, ENUMMFSTEP); // //done playing so close the metafile and delete the handle // if (bEnhMeta) DeleteEnhMetaFile(CloseEnhMetaFile(hDC)); else DeleteMetaFile(CloseMetaFile(hDC)); WaitCursor(FALSE); } break; case DESTDIB: { /* extents for the display DC */ GetClientRect(hWndMain, &rect); INT cx = rect.right - rect.left; INT cy = rect.bottom - rect.top; /* SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm)); SetViewportOrgEx(hDC, 0, 0, &lpPT); */ WaitCursor(TRUE); hDC = GetDC(hWnd); BITMAPINFOHEADER bmi; memset(&bmi, 0, sizeof(BITMAPINFOHEADER)); bmi.biSize = sizeof(BITMAPINFOHEADER); bmi.biBitCount = 24; bmi.biWidth = cx; bmi.biHeight = -cy; bmi.biPlanes = 1; VOID* bits = NULL; HBITMAP hBmp = CreateDIBSection(hDC, (BITMAPINFO*) &bmi, 0, &bits, NULL, 0); HDC hDCBmp = CreateCompatibleDC(hDC); ::SelectObject(hDCBmp, hBmp); FillRect(hDCBmp, &rect, (HBRUSH) ::GetStockObject(GRAY_BRUSH)); if (!bUseGdiPlusToPlay) { // //metafile read in from a clipboard file // if ( bMetaInRam && !bPlaceableMeta && !bEnhMeta) SetClipMetaExts(hDCBmp, lpMFP, lpOldMFP, WMFDISPLAY); // //Windows placeable metafile // if (bPlaceableMeta && !bEnhMeta) SetPlaceableExts(hDCBmp, placeableWMFHeader, WMFDISPLAY); // //Windows metafile // if (!bMetaInRam && !bEnhMeta) { SetNonPlaceableExts(hDCBmp, WMFDISPLAY); } } // //begin the enumeration of the metafile // start = GetTickCount(); GetMetaFileAndEnum(hWnd, hDCBmp, ENUMMFSTEP); end = GetTickCount(); renderTime = end - start; wsprintf(tmpBuf, "Time: %d", renderTime); SetWindowText(hWnd, tmpBuf); StretchDIBits(hDC, 0, 0, cx, cy, 0, 0, cx, cy, bits, (BITMAPINFO*)&bmi, 0, SRCCOPY); DeleteDC(hDCBmp); DeleteObject((HGDIOBJ) hBmp); ReleaseDC(hWnd, hDC); WaitCursor(FALSE); break; } case DESTPRN: { HDC hPr = (HDC)NULL; PRINTDLG pd; memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.Flags = PD_RETURNDC; pd.hwndOwner = hWndMain; // //get a DC for the printer // if (PrintDlg(&pd) != 0) hPr= pd.hDC; else break; // //if a DC could not be created then report the error and return // if (!hPr) { WaitCursor(FALSE); wsprintf((LPSTR)str, "Cannot print %s", (LPSTR)fnameext); MessageBox(hWndMain, (LPSTR)str, NULL, MB_OK | MB_ICONHAND); break; } // //define the abort function // SetAbortProc(hPr, AbortProc); // //Initialize the members of a DOCINFO structure. // DOCINFO di; memset(&di, 0, sizeof(di)); di.cbSize = sizeof(DOCINFO); di.lpszDocName = (bEnhMeta) ? "Print EMF" : "Print WMF"; di.lpszOutput = (LPTSTR) NULL; // //Begin a print job by calling the StartDoc //function. // if (SP_ERROR == (StartDoc(hPr, &di))) { //if (Escape(hPr, STARTDOC, 4, "Metafile", (LPSTR) NULL) < 0) { MessageBox(hWndMain, "Unable to start print job", NULL, MB_OK | MB_ICONHAND); DeleteDC(hPr); break; } // //clear the abort flag // bAbort = FALSE; // //Create the Abort dialog box (modeless) // hAbortDlgWnd = CreateDialog((HINSTANCE)hInst, "AbortDlg", hWndMain, AbortDlg); // //if the dialog was not created report the error // if (!hAbortDlgWnd) { WaitCursor(FALSE); MessageBox(hWndMain, "NULL Abort window handle", NULL, MB_OK | MB_ICONHAND); break; } // //show Abort dialog // ShowWindow (hAbortDlgWnd, SW_NORMAL); // //disable the main window to avoid reentrancy problems // EnableWindow(hWndMain, FALSE); WaitCursor(FALSE); // //if we are still committed to printing // if (!bUseGdiPlusToPlay) { // //if this is a placeable metafile then set its origins and extents // if (bPlaceableMeta) SetPlaceableExts(hPr, placeableWMFHeader, WMFPRINTER); // //if this is a metafile contained within a clipboard file then set //its origins and extents accordingly // if ( (bMetaInRam) && (!bPlaceableMeta) ) SetClipMetaExts(hPr, lpMFP, lpOldMFP, WMFPRINTER); } // //if this is a "traditional" windows metafile // RECT rc; rc.left = 0; rc.top = 0; rc.right = GetDeviceCaps(hPr, HORZRES); rc.bottom = GetDeviceCaps(hPr, VERTRES); POINT lpPT; SIZE lpSize; if (TRUE || !bMetaInRam) { SetMapMode(hPr, MM_TEXT); SetViewportOrgEx(hPr, 0, 0, &lpPT); // //set the extents to the driver supplied values for horizontal //and vertical resolution // SetViewportExtEx(hPr, rc.right, rc.bottom, &lpSize ); } // //play the metafile directly to the printer. //No enumeration involved here // GetMetaFileAndEnum(hWnd, hPr, ENUMMFSTEP); // //eject page and end the print job // Escape(hPr, NEWFRAME, 0, 0L, 0L); EndDoc(hPr); EnableWindow(hWndMain, TRUE); // //destroy the Abort dialog box // DestroyWindow(hAbortDlgWnd); DeleteDC(hPr); } default: break; } // //if playing list records then free the memory used for the list of //selected records // if (bPlayList) { GlobalUnlock(hSelMem); GlobalFree(hSelMem); bPlayList = FALSE; } // //success // return (TRUE); } else // //not a valid metafile // return (FALSE); } /*********************************************************************** FUNCTION : RenderClipMeta PARAMETERS : CLIPFILEFORMAT *ClipHeader int fh PURPOSE : read metafile bits, metafilepict and metafile header of the metafile contained within a clipboard file CALLS : WINDOWS GlobalAlloc GlobalLock GlobalUnlock GlobalFree MessageBox _llseek _lread _lclose SetMetaFileBits MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 1/16/91 - created - drc 5/23/93 - ported to NT. it must handle 3.1 clipboard as well as NT clipboard files - drc ************************************************************************/ BOOL RenderClipMeta(LPVOID lpvClipHeader, int fh, WORD ClipID) { int wBytesRead; long lBytesRead; long lSize; DWORD lOffset; DWORD dwSizeOfMetaFilePict; BOOL bEMF = FALSE; LPNTCLIPFILEFORMAT lpNTClp; LPCLIPFILEFORMAT lpClp; // //cast the void ptr to the clipfile header appropriately // if (bEnhMeta) { lpNTClp = (LPNTCLIPFILEFORMAT)lpvClipHeader; bEMF = TRUE; } else lpClp = (LPCLIPFILEFORMAT)lpvClipHeader; // //obtain the appropriate size of the metafilepict. win16 vs win32 // dwSizeOfMetaFilePict = (ClipID == CLP_ID) ? sizeof(OLDMETAFILEPICT) : sizeof(METAFILEPICT); // //free any memory already allocated for the METAFILEPICT // if (lpMFP != NULL || lpOldMFP != NULL) { GlobalFreePtr(lpMFP); lpMFP = NULL; } // //allocate enough memory to read the metafile bits into // if (!(lpMFBits = (char*)GlobalAllocPtr(GHND, ((bEMF) ? lpNTClp->DataLen : lpClp->DataLen - dwSizeOfMetaFilePict)))) return(FALSE); // //offset to the metafile bits // lOffset = ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset + dwSizeOfMetaFilePict ); // //size of metafile bits // lSize = (long)( ((bEMF) ? lpNTClp->DataLen : lpClp->DataLen - dwSizeOfMetaFilePict)); // //seek to the beginning of the metafile bits // _llseek(fh, lOffset, 0); // //read the metafile bits // lBytesRead = _hread(fh, lpMFBits, lSize); // //if unable to read the metafile bits bail out // if( lBytesRead == -1 || lBytesRead < lSize) { GlobalFreePtr(lpMFBits); MessageBox(hWndMain, "Unable to read metafile bits", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //return to beginning to read metafile header // _llseek(fh, lOffset, 0); // //read the metafile header // if (!bEMF) wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER)); else wBytesRead = _lread(fh, (LPSTR)&emfHeader, sizeof(ENHMETAHEADER)); // //if unable to read the header return // if( wBytesRead == -1 || (WORD)wBytesRead < ((bEMF) ? sizeof(ENHMETAHEADER) : sizeof(METAHEADER)) ) { MessageBox(hWndMain, "Unable to read metafile header", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //set the metafile bits to the memory allocated for that purpose // if (bEMF) // //win32 // hemf = SetEnhMetaFileBits(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits); else // //win16 // hMF = SetMetaFileBitsEx(GlobalSizePtr(lpMFBits), (const unsigned char *)lpMFBits); if ( NULL == ((bEMF) ? hemf : hMF)) { MessageBox(hWndMain, "Unable to set metafile bits", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //allocate memory for the metafile pict structure // if (!(hMFP = GlobalAlloc(GHND, dwSizeOfMetaFilePict))) { MessageBox(hWndMain, "Unable allocate memory for metafile pict", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //lock the memory // if (ClipID == CLP_ID) lpOldMFP = (LPOLDMETAFILEPICT)GlobalLock(hMFP); else lpMFP = (LPMETAFILEPICT)GlobalLock(hMFP); if (!lpMFP && !lpOldMFP) { MessageBox(hWndMain, "unable to lock metafile pict memory", NULL, MB_OK | MB_ICONHAND); GlobalFree(hMFP); return(FALSE); } // //reposition to the start of the METAFILEPICT header. // _llseek(fh, ((bEMF) ? lpNTClp->DataOffset : lpClp->DataOffset), 0); // //read the metafile pict structure // wBytesRead = _lread(fh, ((ClipID == CLP_ID) ? (LPVOID)lpOldMFP : (LPVOID)lpMFP), dwSizeOfMetaFilePict); // //if unable to read, return // if( wBytesRead == -1 || wBytesRead < (long)dwSizeOfMetaFilePict) { MessageBox(hWndMain, "Unable to read metafile pict", NULL, MB_OK | MB_ICONHAND); GlobalUnlock(hMFP); GlobalFree(hMFP); return(FALSE); } if (bEnhMeta) GetEMFCoolStuff(); //DENNIS - check this out.... /* update metafile handle */ if (ClipID == CLP_ID) lpOldMFP->hMF = (WORD)hMF; else lpMFP->hMF = (HMETAFILE)hemf; return(TRUE); } /*********************************************************************** FUNCTION : RenderPlaceableMeta PARAMETERS : int fh - filehandle to the placeable metafile PURPOSE : read the metafile bits, metafile header and placeable metafile header of a placeable metafile. CALLS : WINDOWS GlobalAlloc GlobalLock Global DeleteMetaFile SetMetaFileBits _llseek _lread _lclose MessageBox MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 1/16/91 - created - drc 7/1/93 - modified for win32 - denniscr ************************************************************************/ BOOL RenderPlaceableMeta( int fh) { int wBytesRead; long lBytesRead; DWORD dwSize; // //if there is currently a metafile loaded, get rid of it // if (bMetaInRam && hMF && !bEnhMeta) DeleteMetaFile((HMETAFILE)hMF); // //seek to beginning of file and read placeable header // _llseek(fh, 0, 0); // //read the placeable header // wBytesRead = _lread(fh, (LPSTR)&placeableWMFHeader, sizeof(PLACEABLEWMFHEADER)); // //if there is an error, return // if( wBytesRead == -1 || wBytesRead < sizeof(PLACEABLEWMFHEADER) ) { MessageBox(hWndMain, "Unable to read placeable header", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //return to read metafile header // _llseek(fh, sizeof(placeableWMFHeader), 0); // //read the metafile header // wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER)); // //if there is an error return // if( wBytesRead == -1 || wBytesRead < sizeof(METAHEADER) ) { MessageBox(hWndMain, "Unable to read metafile header", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //allocate memory for the metafile bits // if (!(lpMFBits = (char *)GlobalAllocPtr(GHND, (mfHeader.mtSize * 2L)))) { MessageBox(hWndMain, "Unable to allocate memory for metafile bits", NULL, MB_OK | MB_ICONHAND); return(FALSE); } // //seek to the metafile bits // _llseek(fh, sizeof(placeableWMFHeader), 0); // //read metafile bits // lBytesRead = _hread(fh, lpMFBits, mfHeader.mtSize * 2); // //if there was an error // if( lBytesRead == -1 ) { MessageBox(hWndMain, "Unable to read metafile bits", NULL, MB_OK | MB_ICONHAND); GlobalFreePtr(lpMFBits); return(FALSE); } // //set the metafile bits to the memory that we allocated // dwSize = GlobalSizePtr(lpMFBits); if (!(hMF = SetMetaFileBitsEx(dwSize, (const unsigned char *)lpMFBits))) return(FALSE); return(TRUE); } /*********************************************************************** FUNCTION : SetPlaceableExts PARAMETERS : HDC hDC PLACEABLEWMFHEADER phdr int nDest PURPOSE : set the origins and extents on the DC to correspond with the origins and extents specified within the placeable metafile header CALLS : WINDOWS GetClientRect SetMapMode SetWindowOrg SetWindowExt SetViewportOrg SetViewportExt C runtime labs MESSAGES : none RETURNS : void COMMENTS : HISTORY : 1/16/91 - created - drc ************************************************************************/ void SetPlaceableExts(HDC hDC, PLACEABLEWMFHEADER phdr, int nDest) { RECT rect; POINT lpPT; SIZE lpSize; /* if setting the extents on the display DC */ if (nDest != WMFPRINTER) GetClientRect(hWndMain, &rect); SetMapMode(hDC, MM_ANISOTROPIC); /* set the windows origin to correspond to the bounding box origin contained in the placeable header */ SetWindowOrgEx(hDC, phdr.bbox.left, phdr.bbox.top, &lpPT); /* set the window extents based on the abs value of the bbox coords */ SetWindowExtEx(hDC,phdr.bbox.right -phdr.bbox.left, phdr.bbox.bottom -phdr.bbox.top, &lpSize); /* set the viewport origin and extents */ if (nDest != WMFPRINTER) { SetViewportOrgEx(hDC, 0, 0, &lpPT); SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize); } else { SetViewportOrgEx(hPr, 0, 0, &lpPT); SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES), GetDeviceCaps(hPr, VERTRES), &lpSize); } } void SetNonPlaceableExts(HDC hDC, int nDest) { RECT rect; POINT lpPT; SIZE lpSize; /* if setting the extents on the display DC */ if (nDest != WMFPRINTER) GetClientRect(hWndMain, &rect); SetMapMode(hDC, MM_ANISOTROPIC); /* set the viewport origin and extents */ if (nDest != WMFPRINTER) { SetViewportOrgEx(hDC, 0, 0, &lpPT); SetViewportExtEx(hDC, rect.right, rect.bottom, &lpSize); } else { SetViewportOrgEx(hPr, 0, 0, &lpPT); SetViewportExtEx(hPr,GetDeviceCaps(hPr, HORZRES), GetDeviceCaps(hPr, VERTRES), &lpSize); } } /*********************************************************************** FUNCTION : SetClipMetaExts PARAMETERS : HDC hDC METAFILEPICT MFP int nDest PURPOSE : set the extents to the client rect for clipboard metafiles CALLS : WINDOWS GetClientRect IntersectClipRect SetMapMode SetViewportOrg SetViewportExt SetWindowExt MESSAGES : none RETURNS : void COMMENTS : this is not as robust as it could be. A more complete approach might be something like Petzold discusses in his Programming Windows book on page 793 in the function PrepareMetaFile(). HISTORY : 1/16/91 - created - drc ************************************************************************/ void SetClipMetaExts( HDC hDC, LPMETAFILEPICT lpMFP, LPOLDMETAFILEPICT lpOldMFP, int nDest) { int cx, cy; RECT rect; POINT lpPT; SIZE lpSize; long lmm; long lxExt; long lyExt; /* extents for the display DC */ if (nDest != WMFPRINTER) { GetClientRect(hWndMain, &rect); cx = rect.right - rect.left; cy = rect.bottom - rect.top; IntersectClipRect(hDC, rect.left, rect.top, rect.right, rect.bottom); } SetMapMode(hDC, ((lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm)); /* set physical origin to 0, 0 */ SetViewportOrgEx(hDC, 0, 0, &lpPT); /* given the mapping mode specified in the metafilepict */ lmm = (lpOldMFP != NULL) ? lpOldMFP->mm : lpMFP->mm; lxExt = (lpOldMFP != NULL) ? lpOldMFP->xExt : lpMFP->xExt; lyExt = (lpOldMFP != NULL) ? lpOldMFP->yExt : lpMFP->yExt; switch (lmm) { case MM_ISOTROPIC: if (lxExt && lyExt) SetWindowExtEx(hDC, lxExt, lyExt, &lpSize); /* fall through */ case MM_ANISOTROPIC: if (nDest != WMFPRINTER) SetViewportExtEx(hDC, cx, cy, &lpSize); else SetViewportExtEx(hDC, GetDeviceCaps(hDC, HORZRES), GetDeviceCaps(hDC, VERTRES), &lpSize ); break; default: break; } } /*********************************************************************** FUNCTION : ProcessFile PARAMETERS : HWND hWnd LPSTR lpFileName PURPOSE : open the metafile, determine if it contains a valid metafile, decide what type of metafile it is (wmf, clipboard, or placeable) and take care of some menu housekeeping tasks. CALLS : MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 1/16/91 - created - drc ************************************************************************/ BOOL ProcessFile( HWND hWnd, LPSTR lpFileName) { // //for openfiledialog // char drive[3]; char dir[MAX_PATH+1]; char fname[MAX_PATH+1]; char ext[5]; char * pchCorrectSir; // //initialize these global handles to metafiles // if (hMF && !bMetaInRam) { DeleteMetaFile((HMETAFILE)hMF); hMF = NULL; } if (hemf && !bMetaInRam) { DeleteEnhMetaFile(hemf); hemf = NULL; } if (lpMFBits) { GlobalFreePtr(lpMFBits); lpMFBits = NULL; hemf = NULL; hMF = NULL; } bEnhMeta = FALSE; // //split the fully qualified filename into its components // SplitPath( lpFileName, (LPSTR)drive, (LPSTR)dir, (LPSTR)fname, (LPSTR)ext); pchCorrectSir = _strupr( _strdup( ext ) ); // //if the memory for the emf header, desc string and palette //is still around then nuke it // if (EmfPtr.lpEMFHdr) { GlobalFreePtr(EmfPtr.lpEMFHdr); EmfPtr.lpEMFHdr = NULL ; } if (EmfPtr.lpDescStr) { GlobalFreePtr(EmfPtr.lpDescStr); EmfPtr.lpDescStr = NULL ; } if (EmfPtr.lpPal) { GlobalFreePtr(EmfPtr.lpPal); EmfPtr.lpPal = NULL ; } // //if the file is an enhanced metafile // if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"CLP") == 0) return ProcessCLP(hWnd, lpFileName); // //if the file is a Windows metafile or a Windows or placeable metafile //as per the normal naming conventions // if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"WMF") == 0) return ProcessWMF(hWnd, lpFileName); // //if the file is a clipboard file // if (lstrcmp((LPSTR)pchCorrectSir, (LPSTR)"EMF") == 0) return ProcessEMF(hWnd, lpFileName); return FALSE; } /*********************************************************************** FUNCTION : ProcessWMF PARAMETERS : HWND hWnd LPSTR lpFileName PURPOSE : open the metafile and determine if it is a Windows metafile or placeable metafile. Then take care of some menu housekeeping tasks. CALLS : MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 6/23/93 - created - drc ************************************************************************/ BOOL ProcessWMF(HWND hWnd, LPSTR lpFileName) { int fh; int wBytesRead; DWORD dwIsPlaceable; char szCaption[144]; /* for openfiledialog */ char drive[3]; char dir[MAX_PATH+1]; char fname[MAX_PATH+1]; char ext[5]; char * pchCorrectSir; // //split the fully qualified filename into its components // SplitPath( lpFileName, (LPSTR)drive, (LPSTR)dir, (LPSTR)fname, (LPSTR)ext); pchCorrectSir = _strupr( _strdup( ext ) ); // //try to open the file. It's existence has already been //checked by OpenFileDialog // fh = _lopen(lpFileName, OF_READ); // //if opened successfully // if (fh != -1) { // //always disable the clipboard and EMF header menu if we get here // EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED); // // read the first dword of the file to see if it is a placeable wmf // wBytesRead = _lread(fh,(LPSTR)&dwIsPlaceable, sizeof(dwIsPlaceable)); if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable)) { _lclose(fh); MessageBox(hWndMain, "unable to read file", NULL, MB_OK | MB_ICONEXCLAMATION); return (FALSE); } // // if this is windows metafile, not a placeable wmf // if (dwIsPlaceable != PLACEABLEKEY) { // if (!bMetaInRam) hMF = GetMetaFile((LPSTR)OpenName); // //disable placeable header menu item // EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED); // //seek to the beginning of the file // _llseek(fh, 0, 0); // //read the wmf header // wBytesRead = _lread(fh, (LPSTR)&mfHeader, sizeof(METAHEADER)); // //done with file so close it // _lclose(fh); // //if read failed // if (wBytesRead == -1 || wBytesRead < sizeof(dwIsPlaceable)) { MessageBox(hWndMain, "unable to read metafile header", NULL, MB_OK | MB_ICONEXCLAMATION); return (FALSE); } } // //this is a placeable metafile // else { // //enable the placeable header menu item // EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_ENABLED); // //convert the placeable format into something that can //be used with GDI metafile functions // RenderPlaceableMeta(fh); // //close the file // _lclose(fh); } // //at this point we have a metafile header regardless of whether //the metafile was a windows metafile or a placeable metafile //so check to see if it is valid. There is really no good //way to do this so just make sure that the mtType is either //1 or 2 (memory or disk file) // if ( (mfHeader.mtType != 1) && (mfHeader.mtType != 2) ) { // //set the program flags appropriately // bBadFile = TRUE; bMetaFileOpen = FALSE; bValidFile = FALSE; // //let the user know that this is an invalid metafile // MessageBox(hWndMain, "This file is not a valid metafile", NULL, MB_OK | MB_ICONEXCLAMATION); // //restore the caption text to the default // SetWindowText(hWnd, (LPSTR)APPNAME); // //disable menu items, indicating that a valid metafile has not been //loaded // EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED); // //refresh the menu bar to reflect above changes // DrawMenuBar(hWnd); } // //this is a valid metafile...at least based on the above criteria // else { // //modify and update the caption text // wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s", (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext); // //this could be used by the printing routines if unable to print // wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext); SetWindowText(hWnd, (LPSTR)szCaption); // //enable the appropriate menu items // EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED); // //refresh the menu bar to reflect above changes // DrawMenuBar(hWnd); // //set global flags appropriately // bValidFile = TRUE; bMetaFileOpen = TRUE; if (dwIsPlaceable != PLACEABLEKEY) { bPlaceableMeta = FALSE; bMetaInRam = FALSE; } else { bPlaceableMeta = TRUE; bMetaInRam = TRUE; } } return (TRUE); } //if fh != -1 else return (FALSE); } /*********************************************************************** FUNCTION : ProcessCLP PARAMETERS : HWND hWnd LPSTR lpFileName PURPOSE : open the metafile contained in the clipboard file and take care of some menu housekeeping tasks. CALLS : MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 6/23/93 - created - drc ************************************************************************/ BOOL ProcessCLP(HWND hWnd, LPSTR lpFileName) { WORD i; int fh; DWORD HeaderPos; DWORD nSizeOfClipHeader; DWORD nSizeOfClipFormat; NTCLIPFILEHEADER NTFileHeader; NTCLIPFILEFORMAT NTClipHeader; CLIPFILEHEADER FileHeader; CLIPFILEFORMAT ClipHeader; char szCaption[144]; WORD wFileID; BOOL bMetaFound = FALSE; LPVOID lpvAddressOfHdr; /* for openfiledialog */ char drive[3]; char dir[MAX_PATH+1]; char fname[MAX_PATH+1]; char ext[5]; char * pchCorrectSir; // //split the fully qualified filename into its components // SplitPath( lpFileName, (LPSTR)drive, (LPSTR)dir, (LPSTR)fname, (LPSTR)ext); pchCorrectSir = _strupr( _strdup( ext ) ); // //try to open the file. It's existence has already been //checked by OpenFileDialog fh = _lopen(lpFileName, OF_READ); // //if opened successfully if (fh != -1 ) { // // read the clipboard fileidentifier // wFileID = 0; _lread(fh, (LPSTR)&wFileID, sizeof(WORD)); _llseek(fh, 0, 0); // //if this is not a valid clipboard file based on the file //identifier of the file header // if (wFileID != CLP_ID && wFileID != CLP_NT_ID && wFileID != CLPBK_NT_ID) { _lclose(fh); MessageBox(hWndMain, "This file is not a valid clipboard file", NULL, MB_OK | MB_ICONEXCLAMATION); return (FALSE); } switch (wFileID) { case CLP_ID: _lread(fh, (LPSTR)&FileHeader, sizeof(CLIPFILEHEADER)); nSizeOfClipHeader = sizeof(CLIPFILEHEADER); nSizeOfClipFormat = sizeof(CLIPFILEFORMAT); HeaderPos = nSizeOfClipHeader; break; case CLP_NT_ID: case CLPBK_NT_ID: NTFileHeader.FormatCount = 0; _lread(fh, (LPSTR)&NTFileHeader, sizeof(NTCLIPFILEHEADER)); nSizeOfClipHeader = sizeof(NTCLIPFILEHEADER); nSizeOfClipFormat = sizeof(NTCLIPFILEFORMAT); HeaderPos = nSizeOfClipHeader; break; default: break; } // //search the formats contained within the clipboard file looking //for a metafile. Break if and when it is found // for (i=0; i < ((wFileID == CLP_ID) ? FileHeader.FormatCount : NTFileHeader.FormatCount); i++) { _llseek(fh, HeaderPos, 0); // //read the clipboard header found at current position // lpvAddressOfHdr = (wFileID == CLP_ID) ? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader; if(_lread(fh, (LPSTR)lpvAddressOfHdr, nSizeOfClipFormat) < nSizeOfClipFormat) //if(_lread(fh, (LPSTR)&ClipHeader, nSizeOfClipHeader) < nSizeOfClipHeader) { _lclose(fh); MessageBox(hWndMain, "read of clipboard header failed", NULL, MB_OK | MB_ICONEXCLAMATION); return (FALSE); } // //increment the file offset to data // HeaderPos += nSizeOfClipFormat; // //if a metafile was found break... //this break assumes that CF_METAFILEPICT formats are always written before CF_ENHMETAFILE //formats. // if (wFileID == CLP_ID && ClipHeader.FormatID == CF_METAFILEPICT) { bMetaFound = TRUE; break; } if (wFileID == CLP_NT_ID || wFileID == CLPBK_NT_ID) { if (NTClipHeader.FormatID == CF_ENHMETAFILE) // HeaderPos += NTClipHeader.DataLen; //else { bMetaFound = TRUE; break; } } } //for i < formatcount if (bMetaFound) { // //if there is currently a metafile loaded delete it. // if (wFileID == CLP_ID) { if ((bMetaInRam) && (hMF)) { DeleteMetaFile((HMETAFILE)hMF); hMF = NULL; } } else { if ((bMetaInRam) && (hemf)) { DeleteEnhMetaFile(hemf); hemf = NULL; } } // //modify and update the caption text // wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s", (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext); // //this could be used by the printing routines if unable to print // wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext); SetWindowText(hWnd, (LPSTR)szCaption); // //enable the appropriate menu items // if (wFileID == CLP_ID) { EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_DISABLED | MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_ENABLED); } else { EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED); } EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED); // //refresh the menu bar // DrawMenuBar(hWnd); // //set the program flags appropriately // bValidFile = TRUE; bMetaFileOpen = TRUE; bMetaInRam = TRUE; bPlaceableMeta = FALSE; bEnhMeta = (wFileID == CLP_ID) ? FALSE : TRUE; // //convert the metafile contained within the clipboard file into //a format useable with GDI metafile functions // if (!RenderClipMeta(((wFileID == CLP_ID)? (LPVOID)&ClipHeader : (LPVOID)&NTClipHeader), fh, FileHeader.FileIdentifier)) MessageBox(hWndMain, "Unable to render format", NULL, MB_OK | MB_ICONEXCLAMATION); _lclose(fh); } // //a metafile was not found within the clipboard file // else { bBadFile = TRUE; bMetaFileOpen = FALSE; bValidFile = FALSE; bEnhMeta = FALSE; // //let the user know // MessageBox(hWndMain, "This CLP file doesn't contain a valid metafile", NULL, MB_OK | MB_ICONEXCLAMATION); // //restore the caption text to default // SetWindowText(hWnd, (LPSTR)APPNAME); // //disable previously enabled menu items // EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED); // //refresh the menu bar to reflect these changes // DrawMenuBar(hWnd); _lclose(fh); } return (TRUE); } else return (FALSE); } /*********************************************************************** FUNCTION : ProcessEMF PARAMETERS : HWND hWnd LPSTR lpFileName PURPOSE : open the metafile contained in the clipboard file and take care of some menu housekeeping tasks. CALLS : MESSAGES : none RETURNS : BOOL COMMENTS : HISTORY : 6/23/93 - created - drc ************************************************************************/ BOOL ProcessEMF(HWND hWnd, LPSTR lpFileName) { char szCaption[144]; /* for openfiledialog */ char drive[3]; char dir[MAX_PATH+1]; char fname[MAX_PATH+1]; char ext[5]; char * pchCorrectSir; bEnhMeta = FALSE; // //split the fully qualified filename into its components // SplitPath( lpFileName, (LPSTR)drive, (LPSTR)dir, (LPSTR)fname, (LPSTR)ext); pchCorrectSir = _strupr( _strdup( ext ) ); // //always disable the clipboard, WMF and Placeable header menu if we get here // EnableMenuItem(GetMenu(hWnd), IDM_CLIPHDR, MF_DISABLED | MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_HEADER, MF_DISABLED | MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_PLACEABLEHDR, MF_DISABLED|MF_GRAYED); // //if emf was successfully opened // if (!hemf) hemf = GetEnhMetaFile(lpFileName); if (hemf) { GetEMFCoolStuff(); // //modify and update the caption text // wsprintf((LPSTR)szCaption, (LPSTR)"%s - %s.%s", (LPSTR)APPNAME, (LPSTR)fname, (LPSTR)ext); // //this could be used by the printing routines if unable to print // wsprintf((LPSTR)fnameext, (LPSTR)"%s.%s", (LPSTR)fname, (LPSTR)ext); SetWindowText(hWnd, (LPSTR)szCaption); // //enable the appropriate menu items // EnableMenuItem(GetMenu(hWnd), IDM_ENHHEADER, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_ENABLED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_ENABLED); // //refresh the menu bar // DrawMenuBar(hWnd); // //set the program flags appropriately // bValidFile = TRUE; bMetaFileOpen = TRUE; bEnhMeta = TRUE; bMetaInRam = FALSE; bPlaceableMeta = FALSE; } // DeleteEnhMetaFile(hemf); else { bEnhMeta = FALSE; bValidFile = FALSE; bBadFile = TRUE; bMetaFileOpen = FALSE; // //let the user know // MessageBox(hWndMain, "This EMF file doesn't contain a valid metafile", NULL, MB_OK | MB_ICONEXCLAMATION); // //restore the caption text to default // SetWindowText(hWnd, (LPSTR)APPNAME); // //disable previously enabled menu items // EnableMenuItem(GetMenu(hWnd), IDM_VIEW, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PLAY, MF_DISABLED|MF_GRAYED|MF_BYPOSITION); EnableMenuItem(GetMenu(hWnd), IDM_PRINT, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_PRINTDLG, MF_DISABLED|MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_SAVEAS, MF_DISABLED|MF_GRAYED); // //refresh the menu bar to reflect these changes // DrawMenuBar(hWnd); } return TRUE; } /*********************************************************************** FUNCTION : GetEMFCoolStuff PARAMETERS : PURPOSE : CALLS : MESSAGES : RETURNS : COMMENTS : HISTORY : created 7/8/93 - denniscr ************************************************************************/ BOOL GetEMFCoolStuff() { // //init these ptrs // EmfPtr.lpEMFHdr = NULL; EmfPtr.lpDescStr = NULL; EmfPtr.lpPal = NULL; if (hemf) { // //obtain the sizes of the emf header, description string and palette // UINT uiHdrSize = GetEnhMetaFileHeader(hemf, 0, NULL); UINT uiDescStrSize = GetEnhMetaFileDescription(hemf, 0, NULL); UINT uiPalEntries = GetEnhMetaFilePaletteEntries(hemf, 0, NULL); // //if these are lengths > 0 then allocate memory to store them // if (uiHdrSize) EmfPtr.lpEMFHdr = (LPENHMETAHEADER)GlobalAllocPtr(GHND, uiHdrSize); if (uiDescStrSize) EmfPtr.lpDescStr = (LPTSTR)GlobalAllocPtr(GHND, uiDescStrSize); if (uiPalEntries) EmfPtr.lpPal = (LPPALETTEENTRY)GlobalAllocPtr(GHND, uiPalEntries * sizeof(PALETTEENTRY)); // //so far the emf seems to be valid so continue // if (uiHdrSize) { // //get the actual emf header and description string // if (!GetEnhMetaFileHeader(hemf, uiHdrSize, EmfPtr.lpEMFHdr)) { MessageBox(hWndMain, "unable to read enhanced metafile header", NULL, MB_OK | MB_ICONEXCLAMATION); bValidFile = FALSE; return (FALSE); } else { // //get the description string if it exists // if (uiDescStrSize) GetEnhMetaFileDescription(hemf, uiDescStrSize, EmfPtr.lpDescStr); // //get the palette if it exists // if (uiPalEntries) { GetEnhMetaFilePaletteEntries(hemf, uiPalEntries, EmfPtr.lpPal); EmfPtr.palNumEntries = (WORD)uiPalEntries; } } } } return (TRUE); } float NormalizeAngle (double angle) { if (angle >= 0) { while (angle >= 360) { angle -= 360; } } else { while (angle < 0) { angle += 360; } } return static_cast(angle); } #define PI 3.1415926535897932384626433832795 #define RADIANS_TO_DEGREES (180.0 / PI) float PointToAngle(float x, float y, float w, float h, float xVector, float yVector) { BOOL bScale = TRUE; if (w == h) { if (w == 0) { return 0; } bScale = FALSE; } float horRadius = w / 2; float verRadius = h / 2; float xOrigin = x + horRadius; float yOrigin = y + verRadius; if (horRadius == 0) { double dAngle = asin(((double)(yVector - yOrigin)) / verRadius); if (xOrigin > xVector) { dAngle = PI - dAngle; } return NormalizeAngle(dAngle * RADIANS_TO_DEGREES); } else if (verRadius == 0) { double dAngle = acos(((double)(xVector - xOrigin)) / horRadius); if (yOrigin > yVector) { dAngle = -dAngle; } return NormalizeAngle(dAngle * RADIANS_TO_DEGREES); } if (yOrigin == yVector) { return static_cast((xOrigin <= xVector) ? 0 : 180); } if (xOrigin == xVector) { return static_cast((yOrigin < yVector) ? 90 : 270);; } if (bScale) { xVector = (float)(xOrigin + ((xVector - xOrigin) * ((double)verRadius / horRadius))); } return NormalizeAngle(atan2(yVector - yOrigin, xVector - xOrigin) * RADIANS_TO_DEGREES); } #define HS_DDI_MAX 6 typedef struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2]; } HATCHBRUSHINFO; HATCHBRUSHINFO hatchBrushInfo = { { sizeof(BITMAPINFOHEADER), 8, 8, 1, 1, BI_RGB, 32, 0, 0, 2, 0 }, { { 255, 255, 255, 0 }, { 0, 0, 0, 0 } } }; ULONG HatchPatterns[HS_DDI_MAX][8] = { // Scans have to be DWORD aligned: { 0x00, // ........ HS_HORIZONTAL 0 0x00, // ........ 0x00, // ........ 0xff, // ******** 0x00, // ........ 0x00, // ........ 0x00, // ........ 0x00 }, // ........ { 0x08, // ....*... HS_VERTICAL 1 0x08, // ....*... 0x08, // ....*... 0x08, // ....*... 0x08, // ....*... 0x08, // ....*... 0x08, // ....*... 0x08 }, // ....*... { 0x80, // *....... HS_FDIAGONAL 2 0x40, // .*...... 0x20, // ..*..... 0x10, // ...*.... 0x08, // ....*... 0x04, // .....*.. 0x02, // ......*. 0x01 }, // .......* { 0x01, // .......* HS_BDIAGONAL 3 0x02, // ......*. 0x04, // .....*.. 0x08, // ....*... 0x10, // ...*.... 0x20, // ..*..... 0x40, // .*...... 0x80 }, // *....... { 0x08, // ....*... HS_CROSS 4 0x08, // ....*... 0x08, // ....*... 0xff, // ******** 0x08, // ....*... 0x08, // ....*... 0x08, // ....*... 0x08 }, // ....*... { 0x81, // *......* HS_DIAGCROSS 5 0x42, // .*....*. 0x24, // ..*..*.. 0x18, // ...**... 0x18, // ...**... 0x24, // ..*..*.. 0x42, // .*....*. 0x81 } // *......* }; /*********************************************************************** FUNCTION : EnhMetaFileEnumProc PARAMETERS : HDC hDC LPHANDLETABLE lpHTable LPMETARECORD lpMFR int nObj LPARAM lpData PURPOSE : callback for EnumEnhMetaFile. CALLS : EnumMFIndirect() MESSAGES : none RETURNS : int COMMENTS : HISTORY : created 6/30/93 - denniscr ************************************************************************/ int CALLBACK EnhMetaFileEnumProc(HDC hDC, LPHANDLETABLE lpHTable, LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData) { return EnumMFIndirect(hDC, lpHTable, NULL, lpEMFR, nObj, lpData); } void GetPixelSize (Gdiplus::Graphics * g, float * cx, float * cy) { Gdiplus::PointF points[2]; points[0].X = points[0].Y = 0; points[1].X = points[1].Y = 1; g->TransformPoints(Gdiplus::CoordinateSpaceWorld, Gdiplus::CoordinateSpaceDevice, points, 2); *cx = points[1].X - points[0].X; *cy = points[1].Y - points[0].Y; } void GpPlayEnhMetaFileRecord(HDC hDC, LPHANDLETABLE lpHTable, LPENHMETARECORD lpEMFR, UINT nObj, LPARAM lpData) { if (!lpData) return; MYDATA * myData = (MYDATA *)lpData; Gdiplus::Graphics * g = myData->g; myData->recordNum++; XFORM xForm; GetWorldTransform(hDC, &xForm); INT mapMode = GetMapMode(hDC); POINT org; SIZE size; GetViewportOrgEx(hDC, &org); GetViewportExtEx(hDC, &size); GetWindowOrgEx(hDC, &org); GetWindowExtEx(hDC, &size); switch (lpEMFR->iType) { case EMR_HEADER: { PENHMETAHEADER pHeader = (PENHMETAHEADER)lpEMFR; RECT clientRect; myData->recordNum = 1; myData->pObjects = new MYOBJECTS[pHeader->nHandles]; myData->numObjects = pHeader->nHandles; GetClientRect(myData->hwnd, &clientRect); int clientWidth = clientRect.right - clientRect.left; int clientHeight = clientRect.bottom - clientRect.top; myData->windowExtent.cx = clientWidth; myData->windowExtent.cy = clientHeight; myData->viewportExtent.cx = clientWidth; myData->viewportExtent.cy = clientHeight; float dstX = TOREAL(clientRect.left); float dstY = TOREAL(clientRect.top); float dstWidth = TOREAL(clientWidth); float dstHeight = TOREAL(clientHeight); float srcWidth = TOREAL(pHeader->rclFrame.right - pHeader->rclFrame.left); float srcHeight = TOREAL(pHeader->rclFrame.bottom - pHeader->rclFrame.top); #if 0 if (srcHeight * dstWidth >= dstHeight * srcWidth) { float oldDstWidth = dstWidth; dstWidth = srcWidth * dstHeight / srcHeight; dstX += (oldDstWidth - dstWidth) / 2; } else { float oldDstHeight = dstHeight; dstHeight = srcHeight * dstWidth / srcWidth; dstY += (oldDstHeight - dstHeight) / 2; } #endif g->SetPageUnit(Gdiplus::UnitPixel); using Gdiplus::RectF; RectF dstRect(dstX, dstY, dstWidth, dstHeight); int deviceLeft = pHeader->rclBounds.left; int deviceRight = pHeader->rclBounds.right; int deviceTop = pHeader->rclBounds.top; int deviceBottom = pHeader->rclBounds.bottom; // if ((deviceLeft > deviceRight) || // (deviceTop > deviceBottom)) { SIZEL deviceSize = pHeader->szlDevice; SIZEL mmSize = pHeader->szlMillimeters; if ((deviceSize.cx <= 0) || (deviceSize.cy <= 0) || (mmSize.cx <= 0) || (mmSize.cy <= 0)) { ASSERT(0); // Take a wild guess deviceSize.cx = 1024; deviceSize.cy = 768; mmSize.cx = 320; mmSize.cy = 240; } deviceLeft = MulDiv(pHeader->rclFrame.left, deviceSize.cx, (mmSize.cx * 100)); deviceRight = MulDiv(pHeader->rclFrame.right, deviceSize.cx, (mmSize.cx * 100)); deviceTop = MulDiv(pHeader->rclFrame.top, deviceSize.cy, (mmSize.cy * 100)); deviceBottom = MulDiv(pHeader->rclFrame.bottom, deviceSize.cy, (mmSize.cy * 100)); } RectF srcRect(TOREAL(deviceLeft), TOREAL(deviceTop), TOREAL(deviceRight - deviceLeft), TOREAL(deviceBottom - deviceTop)); myData->containerId = g->BeginContainer(dstRect, srcRect, Gdiplus::UnitPixel); g->SetPageUnit(Gdiplus::UnitPixel); // Assume MM_TEXT } break; case EMR_POLYBEZIER: { PEMRPOLYBEZIER pBezier = (PEMRPOLYBEZIER)lpEMFR; if (pBezier->cptl > 0) { int i = pBezier->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = TOREAL(pBezier->aptl[i].x); points[i].Y = TOREAL(pBezier->aptl[i].y); } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawBeziers(&pen, points, pBezier->cptl); } } else { myData->path->AddBeziers(points, pBezier->cptl); } delete [] points; } } break; case EMR_POLYGON: { PEMRPOLYGON pPolygon = (PEMRPOLYGON)lpEMFR; if (pPolygon->cptl > 0) { int i = pPolygon->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = TOREAL(pPolygon->aptl[i].x); points[i].Y = TOREAL(pPolygon->aptl[i].y); } while (i > 0); if (!myData->pathOpen) { Gdiplus::GraphicsPath path(myData->fillMode); path.AddPolygon(points, pPolygon->cptl); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } else { myData->path->AddPolygon(points, pPolygon->cptl); } delete [] points; } } break; case EMR_POLYLINE: { PEMRPOLYLINE pPolyline = (PEMRPOLYLINE)lpEMFR; if (pPolyline->cptl > 0) { int i = pPolyline->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = TOREAL(pPolyline->aptl[i].x); points[i].Y = TOREAL(pPolyline->aptl[i].y); } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawLines(&pen, points, pPolyline->cptl); } } else { myData->path->AddLines(points, pPolyline->cptl); } delete [] points; } } break; case EMR_POLYBEZIERTO: { PEMRPOLYBEZIERTO pBezier = (PEMRPOLYBEZIERTO)lpEMFR; if (pBezier->cptl > 0) { int i = pBezier->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i+1]; do { points[i].X = TOREAL(pBezier->aptl[i-1].x); points[i].Y = TOREAL(pBezier->aptl[i-1].y); i--; } while (i > 0); points[0] = myData->curPos; myData->curPos = points[pBezier->cptl]; if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawBeziers(&pen, points, pBezier->cptl+1); } } else { myData->path->AddBeziers(points, pBezier->cptl+1); } delete [] points; } } break; case EMR_POLYLINETO: { PEMRPOLYLINETO pPolyline = (PEMRPOLYLINETO)lpEMFR; if (pPolyline->cptl > 0) { int i = pPolyline->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i+1]; do { points[i].X = TOREAL(pPolyline->aptl[i-1].x); points[i].Y = TOREAL(pPolyline->aptl[i-1].y); i--; } while (i > 0); points[0] = myData->curPos; myData->curPos = points[pPolyline->cptl]; if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawLines(&pen, points, pPolyline->cptl+1); } } else { myData->path->AddLines(points, pPolyline->cptl+1); } delete [] points; } } break; case EMR_POLYPOLYLINE: { PEMRPOLYPOLYLINE pPolyline = (PEMRPOLYPOLYLINE)lpEMFR; if ((pPolyline->cptl > 0) && (pPolyline->nPolys > 0)) { int i = pPolyline->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i]; POINTL * metaPoints = (POINTL *)(pPolyline->aPolyCounts + pPolyline->nPolys); do { i--; points[i].X = TOREAL(metaPoints[i].x); points[i].Y = TOREAL(metaPoints[i].y); } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); i = 0; Gdiplus::PointF * tmpPoints = points; DWORD count; do { count = pPolyline->aPolyCounts[i]; g->DrawLines(&pen, tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolyline->nPolys); } } else { i = 0; Gdiplus::PointF * tmpPoints = points; DWORD count; do { count = pPolyline->aPolyCounts[i]; myData->path->AddLines(tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolyline->nPolys); } delete [] points; } } break; case EMR_POLYPOLYGON: { PEMRPOLYPOLYGON pPolygon = (PEMRPOLYPOLYGON)lpEMFR; if ((pPolygon->cptl > 0) && (pPolygon->nPolys > 0)) { int i = pPolygon->cptl; Gdiplus::PointF * points = new Gdiplus::PointF[i]; POINTL * metaPoints = (POINTL *)(pPolygon->aPolyCounts + pPolygon->nPolys); do { i--; points[i].X = TOREAL(metaPoints[i].x); points[i].Y = TOREAL(metaPoints[i].y); } while (i > 0); Gdiplus::GraphicsPath path(myData->fillMode); Gdiplus::GraphicsPath * tmpPath = &path; if (myData->pathOpen) { tmpPath = myData->path; } Gdiplus::PointF * tmpPoints = points; DWORD count; i = 0; do { count = pPolygon->aPolyCounts[i]; tmpPath->StartFigure(); tmpPath->AddPolygon(tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolygon->nPolys); if (myData->path == NULL) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } delete [] points; } } break; case EMR_SETWINDOWEXTEX: { PEMRSETWINDOWEXTEX pWindowExt = (PEMRSETWINDOWEXTEX)lpEMFR; if (((myData->mapMode == MM_ANISOTROPIC) || (myData->mapMode == MM_ISOTROPIC)) && (pWindowExt->szlExtent.cx != 0) && // Note: Can be < 0!!! (pWindowExt->szlExtent.cy != 0) && (pWindowExt->szlExtent.cx != myData->windowExtent.cx) && (pWindowExt->szlExtent.cy != myData->windowExtent.cy)) { myData->windowExtent = pWindowExt->szlExtent; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; if (myData->mapMode == MM_ISOTROPIC) { if (sX < sY) { sY = sX; } else { sX = sY; } } myData->scaleX = sX; myData->scaleY = sY; myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(sX, sY); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SETWINDOWORGEX: { PEMRSETWINDOWORGEX pWindowOrg = (PEMRSETWINDOWORGEX)lpEMFR; if ((pWindowOrg->ptlOrigin.x != myData->windowOrg.x) && (pWindowOrg->ptlOrigin.y != myData->windowOrg.y)) { myData->windowOrg = pWindowOrg->ptlOrigin; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(oldSx, oldSy); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SETVIEWPORTEXTEX: { PEMRSETVIEWPORTEXTEX pViewportExt = (PEMRSETVIEWPORTEXTEX)lpEMFR; if (((myData->mapMode == MM_ANISOTROPIC) || (myData->mapMode == MM_ISOTROPIC)) && (pViewportExt->szlExtent.cx > 0) && (pViewportExt->szlExtent.cy > 0) && (pViewportExt->szlExtent.cx != myData->viewportExtent.cx) && (pViewportExt->szlExtent.cy != myData->viewportExtent.cy)) { myData->viewportExtent = pViewportExt->szlExtent; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; if (myData->mapMode == MM_ISOTROPIC) { if (sX < sY) { sY = sX; } else { sX = sY; } } myData->scaleX = sX; myData->scaleY = sY; myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(sX, sY); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SETVIEWPORTORGEX: { PEMRSETVIEWPORTORGEX pViewportOrg = (PEMRSETVIEWPORTORGEX)lpEMFR; if ((pViewportOrg->ptlOrigin.x != myData->viewportOrg.x) && (pViewportOrg->ptlOrigin.y != myData->viewportOrg.y)) { myData->viewportOrg = pViewportOrg->ptlOrigin; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; myData->dx = (myData->viewportOrg.x / oldSx) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / oldSy) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(oldSx, oldSy); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SETBRUSHORGEX: break; case EMR_EOF: g->EndContainer(myData->containerId); break; case EMR_SETPIXELV: { PEMRSETPIXELV pSetPixel = (PEMRSETPIXELV)lpEMFR; COLORREF cRef = pSetPixel->crColor; ASSERT((cRef & 0x01000000) == 0); Gdiplus::SolidBrush brush(Gdiplus::Color(Gdiplus::Color::MakeARGB(0xff, GetRValue(cRef), GetGValue(cRef), GetBValue(cRef)))); g->FillRectangle(&brush, TOREAL(pSetPixel->ptlPixel.x), TOREAL(pSetPixel->ptlPixel.y), TOREAL(1), TOREAL(1)); } break; case EMR_SETMAPPERFLAGS: // for font mapping break; case EMR_SETMAPMODE: { PEMRSETMAPMODE pMapMode = (PEMRSETMAPMODE)lpEMFR; if (myData->mapMode != pMapMode->iMode) { float sX, sY; myData->mapMode = pMapMode->iMode; switch (pMapMode->iMode) { case MM_TEXT: g->SetPageUnit(Gdiplus::UnitPixel); sX = sY = 1; break; case MM_LOMETRIC: g->SetPageUnit(Gdiplus::UnitMillimeter); g->SetPageScale(TOREAL(.1)); sX = sY = 1; break; case MM_HIMETRIC: g->SetPageUnit(Gdiplus::UnitMillimeter); g->SetPageScale(TOREAL(.01)); sX = sY = 1; break; case MM_LOENGLISH: g->SetPageUnit(Gdiplus::UnitInch); g->SetPageScale(TOREAL(.01)); sX = sY = 1; break; case MM_HIENGLISH: g->SetPageUnit(Gdiplus::UnitInch); g->SetPageScale(TOREAL(.001)); sX = sY = 1; break; case MM_TWIPS: g->SetPageUnit(Gdiplus::UnitPoint); g->SetPageScale(TOREAL(.05)); sX = sY = 1; break; case MM_ISOTROPIC: g->SetPageUnit(Gdiplus::UnitPixel); sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; if (sX < sY) { sY = sX; } else { sX = sY; } break; case MM_ANISOTROPIC: g->SetPageUnit(Gdiplus::UnitPixel); sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; break; } float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; myData->scaleX = sX; myData->scaleY = sY; myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(sX, sY); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SETBKMODE: break; case EMR_SETPOLYFILLMODE: { PEMRSETPOLYFILLMODE pPolyfillMode = (PEMRSETPOLYFILLMODE)lpEMFR; myData->fillMode = (pPolyfillMode->iMode == ALTERNATE) ? Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding; } break; case EMR_SETROP2: break; case EMR_SETSTRETCHBLTMODE: #ifdef _DEBUG { PEMRSETSTRETCHBLTMODE pStretchBltMode = (PEMRSETSTRETCHBLTMODE)lpEMFR; int mode; switch (pStretchBltMode->iMode) { case BLACKONWHITE: mode = 1; break; case WHITEONBLACK: mode = 2; break; case COLORONCOLOR: mode = 3; break; case HALFTONE: mode = 4; break; } } #endif break; case EMR_SETTEXTALIGN: break; case EMR_SETCOLORADJUSTMENT: break; case EMR_SETTEXTCOLOR: break; case EMR_SETBKCOLOR: break; case EMR_OFFSETCLIPRGN: { PEMROFFSETCLIPRGN pOffsetClipRgn = (PEMROFFSETCLIPRGN)lpEMFR; g->TranslateClip(TOREAL(pOffsetClipRgn->ptlOffset.x), TOREAL(pOffsetClipRgn->ptlOffset.y)); } break; case EMR_MOVETOEX: { PEMRMOVETOEX pMoveTo = (PEMRMOVETOEX)lpEMFR; myData->curPos.X = TOREAL(pMoveTo->ptl.x); myData->curPos.Y = TOREAL(pMoveTo->ptl.y); } break; case EMR_SETMETARGN: break; case EMR_EXCLUDECLIPRECT: { PEMREXCLUDECLIPRECT pExcludeClipRect = (PEMREXCLUDECLIPRECT)lpEMFR; Gdiplus::RectF clipRect(TOREAL(pExcludeClipRect->rclClip.left), TOREAL(pExcludeClipRect->rclClip.top), TOREAL(pExcludeClipRect->rclClip.right - pExcludeClipRect->rclClip.left), TOREAL(pExcludeClipRect->rclClip.bottom - pExcludeClipRect->rclClip.top)); g->ExcludeClip(clipRect); } break; case EMR_INTERSECTCLIPRECT: { PEMRINTERSECTCLIPRECT pIntersectClipRect = (PEMRINTERSECTCLIPRECT)lpEMFR; Gdiplus::RectF eRect; eRect.X = TOREAL(pIntersectClipRect->rclClip.left); eRect.Y = TOREAL(pIntersectClipRect->rclClip.top); eRect.Width = TOREAL(pIntersectClipRect->rclClip.right - pIntersectClipRect->rclClip.left); eRect.Height = TOREAL(pIntersectClipRect->rclClip.bottom - pIntersectClipRect->rclClip.top); g->IntersectClip(eRect); } break; case EMR_SCALEVIEWPORTEXTEX: { PEMRSCALEVIEWPORTEXTEX pViewportExt = (PEMRSCALEVIEWPORTEXTEX)lpEMFR; if (((myData->mapMode == MM_ANISOTROPIC) || (myData->mapMode == MM_ISOTROPIC)) && (pViewportExt->xNum != 0) && (pViewportExt->yNum != 0) && (pViewportExt->xDenom != 0) && (pViewportExt->yDenom != 0)) { myData->viewportExtent.cx = (myData->viewportExtent.cx * pViewportExt->xNum) / pViewportExt->xDenom; myData->viewportExtent.cy = (myData->viewportExtent.cy * pViewportExt->yNum) / pViewportExt->yDenom; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; if (myData->mapMode == MM_ISOTROPIC) { if (sX < sY) { sY = sX; } else { sX = sY; } } myData->scaleX = sX; myData->scaleY = sY; myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(sX, sY); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SCALEWINDOWEXTEX: { PEMRSCALEWINDOWEXTEX pWindowExt = (PEMRSCALEWINDOWEXTEX)lpEMFR; if (((myData->mapMode == MM_ANISOTROPIC) || (myData->mapMode == MM_ISOTROPIC)) && (pWindowExt->xNum != 0) && (pWindowExt->yNum != 0) && (pWindowExt->xDenom != 0) && (pWindowExt->yDenom != 0)) { myData->windowExtent.cx = (myData->windowExtent.cx * pWindowExt->xNum) / pWindowExt->xDenom; myData->windowExtent.cy = (myData->windowExtent.cy * pWindowExt->yNum) / pWindowExt->yDenom; float oldDx = myData->dx; float oldDy = myData->dy; float oldSx = myData->scaleX; float oldSy = myData->scaleY; float sX = (float)myData->viewportExtent.cx / myData->windowExtent.cx; float sY = (float)myData->viewportExtent.cy / myData->windowExtent.cy; if (myData->mapMode == MM_ISOTROPIC) { if (sX < sY) { sY = sX; } else { sX = sY; } } myData->scaleX = sX; myData->scaleY = sY; myData->dx = (myData->viewportOrg.x / sX) - myData->windowOrg.x; myData->dy = (myData->viewportOrg.y / sY) - myData->windowOrg.y; Gdiplus::Matrix matrix; matrix.Scale(sX, sY); matrix.Translate(myData->dx, myData->dy); matrix.Translate(-oldDx, -oldDy); matrix.Scale(1 / oldSx, 1 / oldSy); g->MultiplyTransform(&matrix, Gdiplus::MatrixOrderAppend); } } break; case EMR_SAVEDC: { myData->PushId(g->Save()); } break; case EMR_RESTOREDC: { g->Restore(myData->PopId()); } break; case EMR_SETWORLDTRANSFORM: { PEMRSETWORLDTRANSFORM pXform = (PEMRSETWORLDTRANSFORM)lpEMFR; Gdiplus::Matrix newMatrix(pXform->xform.eM11, pXform->xform.eM12, pXform->xform.eM21, pXform->xform.eM22, pXform->xform.eDx, pXform->xform.eDy); if (newMatrix.IsInvertible()) { myData->matrix.Invert(); myData->matrix.Multiply(&newMatrix); g->MultiplyTransform(&(myData->matrix)); myData->matrix.SetElements(pXform->xform.eM11, pXform->xform.eM12, pXform->xform.eM21, pXform->xform.eM22, pXform->xform.eDx, pXform->xform.eDy); } } break; case EMR_MODIFYWORLDTRANSFORM: { PEMRMODIFYWORLDTRANSFORM pXform = (PEMRMODIFYWORLDTRANSFORM)lpEMFR; switch (pXform->iMode) { case MWT_IDENTITY: default: { myData->matrix.Invert(); g->MultiplyTransform(&(myData->matrix)); myData->matrix.Reset(); } break; case MWT_LEFTMULTIPLY: { Gdiplus::Matrix newMatrix(pXform->xform.eM11, pXform->xform.eM12, pXform->xform.eM21, pXform->xform.eM22, pXform->xform.eDx, pXform->xform.eDy); if (newMatrix.IsInvertible()) { myData->matrix.Multiply(&newMatrix); g->MultiplyTransform(&newMatrix); } } break; case MWT_RIGHTMULTIPLY: { Gdiplus::Matrix newMatrix(pXform->xform.eM11, pXform->xform.eM12, pXform->xform.eM21, pXform->xform.eM22, pXform->xform.eDx, pXform->xform.eDy); if (newMatrix.IsInvertible()) { Gdiplus::Matrix * inverse = myData->matrix.Clone(); inverse->Invert(); myData->matrix.Multiply(&newMatrix, Gdiplus::MatrixOrderAppend); inverse->Multiply(&(myData->matrix)); g->MultiplyTransform(inverse); delete inverse; } } break; } } break; case EMR_SELECTOBJECT: { PEMRSELECTOBJECT pObject = (PEMRSELECTOBJECT)lpEMFR; int objectIndex = pObject->ihObject; if ((objectIndex & ENHMETA_STOCK_OBJECT) != 0) { switch (objectIndex & (~ENHMETA_STOCK_OBJECT)) { case WHITE_BRUSH: myData->curBrush = 0xFFFFFFFF; break; case LTGRAY_BRUSH: myData->curBrush = 0xFFC0C0C0; break; case GRAY_BRUSH: myData->curBrush = 0xFF808080; break; case DKGRAY_BRUSH: myData->curBrush = 0xFF404040; break; case BLACK_BRUSH: myData->curBrush = 0xFF000000; break; case NULL_BRUSH: myData->curBrush = 0x00000000; break; case WHITE_PEN: myData->curPen = 0xFFFFFFFF; break; case BLACK_PEN: myData->curPen = 0xFF000000; break; case NULL_PEN: myData->curPen = 0x00000000; break; } } else { ASSERT(objectIndex < myData->numObjects); if (myData->pObjects[objectIndex].type == MYOBJECTS::PenObjectType) { myData->curPen = myData->pObjects[objectIndex].color; myData->curPenWidth = myData->pObjects[objectIndex].penWidth; } else if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType) { myData->curBrush = myData->pObjects[objectIndex].color; myData->curBrushPattern = myData->pObjects[objectIndex].brushPattern; #if 1 myData->curPatIndex = myData->pObjects[objectIndex].patIndex; #else static dodo = 0; myData->curPatIndex = dodo++ % 6; #endif } } } break; case EMR_CREATEPEN: { PEMRCREATEPEN pPen = (PEMRCREATEPEN)lpEMFR; COLORREF cRef = pPen->lopn.lopnColor; ASSERT((cRef & 0x01000000) == 0); ASSERT(pPen->ihPen < myData->numObjects); delete myData->pObjects[pPen->ihPen].brushPattern; myData->pObjects[pPen->ihPen].brushPattern = NULL; myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType; myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff, GetRValue(cRef), GetGValue(cRef), GetBValue(cRef)); myData->pObjects[pPen->ihPen].penWidth = pPen->lopn.lopnWidth.x; } break; case EMR_CREATEBRUSHINDIRECT: { PEMRCREATEBRUSHINDIRECT pBrush = (PEMRCREATEBRUSHINDIRECT)lpEMFR; COLORREF cRef = pBrush->lb.lbColor; ASSERT((cRef & 0x01000000) == 0); ASSERT(pBrush->ihBrush < myData->numObjects); myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType; myData->pObjects[pBrush->ihBrush].patIndex = -1; delete myData->pObjects[pBrush->ihBrush].brushPattern; myData->pObjects[pBrush->ihBrush].brushPattern = NULL; if (pBrush->lb.lbStyle == BS_NULL) { myData->pObjects[pBrush->ihBrush].color = 0x00000000; } else { // Hatch Styles if (pBrush->lb.lbStyle == BS_HATCHED) { switch (pBrush->lb.lbHatch) { case HS_HORIZONTAL: /* ----- */ case HS_VERTICAL: /* ||||| */ case HS_FDIAGONAL: /* \\\\\ */ case HS_BDIAGONAL: /* ///// */ case HS_CROSS: /* +++++ */ case HS_DIAGCROSS: /* xxxxx */ myData->pObjects[pBrush->ihBrush].patIndex = pBrush->lb.lbHatch; break; } } myData->pObjects[pBrush->ihBrush].color = Gdiplus::Color::MakeARGB(0xff, GetRValue(cRef), GetGValue(cRef), GetBValue(cRef)); } } break; case EMR_DELETEOBJECT: { #if 0 PEMRDELETEOBJECT pObject = (PEMRDELETEOBJECT)lpEMFR; int objectIndex = pObject->ihObject; ASSERT(objectIndex < myData->numObjects); if (myData->pObjects[objectIndex].type == MYOBJECTS::BrushObjectType) { if (myData->curBrushPattern != myData->pObjects[objectIndex].brushPattern) { delete myData->pObjects[objectIndex].brushPattern; myData->pObjects[objectIndex].brushPattern = NULL; } } #endif } break; case EMR_ANGLEARC: break; case EMR_ELLIPSE: { PEMRELLIPSE pEllipse = (PEMRELLIPSE)lpEMFR; float x = TOREAL(pEllipse->rclBox.left); float y = TOREAL(pEllipse->rclBox.top); float w = TOREAL(pEllipse->rclBox.right - x); float h = TOREAL(pEllipse->rclBox.bottom - y); if (!myData->pathOpen) { Gdiplus::GraphicsPath path(myData->fillMode); path.AddEllipse(x, y, w, h); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } else { myData->path->AddEllipse(x, y, w, h); } } break; case EMR_RECTANGLE: { PEMRRECTANGLE pRect = (PEMRRECTANGLE)lpEMFR; float x = TOREAL(pRect->rclBox.left); float y = TOREAL(pRect->rclBox.top); float w = TOREAL(pRect->rclBox.right - x); float h = TOREAL(pRect->rclBox.bottom - y); if (!myData->pathOpen) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillRectangle(&brush, x, y, w, h); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillRectangle(brush, x, y, w, h); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillRectangle(brush, x, y, w, h); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawRectangle(&pen, x, y, w, h); } } else { myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h)); } } break; case EMR_ROUNDRECT: // for now, ignore the szlCorner param of round corners { PEMRROUNDRECT pRect = (PEMRROUNDRECT)lpEMFR; float x = TOREAL(pRect->rclBox.left); float y = TOREAL(pRect->rclBox.top); float w = TOREAL(pRect->rclBox.right - x); float h = TOREAL(pRect->rclBox.bottom - y); if (!myData->pathOpen) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillRectangle(&brush, x, y, w, h); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillRectangle(brush, x, y, w, h); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillRectangle(brush, x, y, w, h); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawRectangle(&pen, x, y, w, h); } } else { myData->path->AddRectangle(Gdiplus::RectF(x, y, w, h)); } } break; case EMR_ARC: { PEMRARC pArc = (PEMRARC)lpEMFR; float x = TOREAL(pArc->rclBox.left); float y = TOREAL(pArc->rclBox.top); float w = TOREAL(pArc->rclBox.right - x); float h = TOREAL(pArc->rclBox.bottom - y); float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y)); float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y)); if (endAngle <= startAngle) { endAngle += 360; } float sweepAngle = endAngle - startAngle; if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360)) { sweepAngle = 360 - sweepAngle; } if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle); } } else { myData->path->AddArc(x, y, w, h, startAngle, sweepAngle); } } break; case EMR_CHORD: break; case EMR_PIE: { PEMRARC pPie = (PEMRARC)lpEMFR; float x = TOREAL(pPie->rclBox.left); float y = TOREAL(pPie->rclBox.top); float w = TOREAL(pPie->rclBox.right - x); float h = TOREAL(pPie->rclBox.bottom - y); float startAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlStart.x), TOREAL(pPie->ptlStart.y)); float endAngle = PointToAngle(x, y, w, h, TOREAL(pPie->ptlEnd.x), TOREAL(pPie->ptlEnd.y)); if (endAngle <= startAngle) { endAngle += 360; } float sweepAngle = endAngle - startAngle; if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360)) { sweepAngle = 360 - sweepAngle; } if (!myData->pathOpen) { Gdiplus::GraphicsPath path(myData->fillMode); path.AddPie(x, y, w, h, startAngle, sweepAngle); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } else { myData->path->AddPie(x, y, w, h, startAngle, sweepAngle); } } break; case EMR_SELECTPALETTE: break; case EMR_CREATEPALETTE: break; case EMR_SETPALETTEENTRIES: break; case EMR_RESIZEPALETTE: break; case EMR_REALIZEPALETTE: break; case EMR_EXTFLOODFILL: break; case EMR_LINETO: { PEMRMOVETOEX pLineTo = (PEMRMOVETOEX)lpEMFR; float x = TOREAL(pLineTo->ptl.x); float y = TOREAL(pLineTo->ptl.y); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawLine(&pen, (float)myData->curPos.X, (float)myData->curPos.Y, x, y); } } else { myData->path->AddLine((float)myData->curPos.X, (float)myData->curPos.Y, x, y); } myData->curPos.X = x; myData->curPos.Y = y; } break; case EMR_ARCTO: { // !!! Set and use current position PEMRARCTO pArc = (PEMRARCTO)lpEMFR; float x = TOREAL(pArc->rclBox.left); float y = TOREAL(pArc->rclBox.top); float w = TOREAL(pArc->rclBox.right - x); float h = TOREAL(pArc->rclBox.bottom - y); float startAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlStart.x), TOREAL(pArc->ptlStart.y)); float endAngle = PointToAngle(x, y, w, h, TOREAL(pArc->ptlEnd.x), TOREAL(pArc->ptlEnd.y)); if (endAngle <= startAngle) { endAngle += 360; } float sweepAngle = endAngle - startAngle; if ((myData->arcDirection != AD_COUNTERCLOCKWISE) && (sweepAngle < 360)) { sweepAngle = 360 - sweepAngle; } if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawArc(&pen, x, y, w, h, startAngle, sweepAngle); } } else { myData->path->AddArc(x, y, w, h, startAngle, sweepAngle); } } break; case EMR_POLYDRAW: break; case EMR_SETARCDIRECTION: { PEMRSETARCDIRECTION pArcDirection = (PEMRSETARCDIRECTION)lpEMFR; myData->arcDirection = pArcDirection->iArcDirection; } break; case EMR_SETMITERLIMIT: { PEMRSETMITERLIMIT pMiterLimit = (PEMRSETMITERLIMIT)lpEMFR; myData->miterLimit = pMiterLimit->eMiterLimit; } break; case EMR_BEGINPATH: { delete myData->path; myData->path = new Gdiplus::GraphicsPath (myData->fillMode); myData->pathOpen = (myData->path != NULL); } break; case EMR_ENDPATH: myData->pathOpen = FALSE; break; case EMR_CLOSEFIGURE: { if (myData->pathOpen) { myData->path->CloseFigure(); } } break; case EMR_FILLPATH: { if (myData->path != NULL) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, myData->path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, myData->path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, myData->path); } } delete myData->path; myData->path = NULL; myData->pathOpen = FALSE; } } break; case EMR_STROKEANDFILLPATH: { if (myData->path != NULL) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, myData->path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, myData->path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, myData->path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, myData->path); } delete myData->path; myData->path = NULL; myData->pathOpen = FALSE; } } break; case EMR_STROKEPATH: { if (myData->path != NULL) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, myData->path); } delete myData->path; myData->path = NULL; myData->pathOpen = FALSE; } } break; case EMR_FLATTENPATH: { if (myData->path != NULL) { myData->path->Flatten(NULL); } } break; case EMR_WIDENPATH: { if (myData->path != NULL) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); myData->path->Widen(&pen); } } break; case EMR_SELECTCLIPPATH: { if (myData->path != NULL) { PEMRSELECTCLIPPATH pSetClipPath = (PEMRSELECTCLIPPATH)lpEMFR; switch (pSetClipPath->iMode) { case RGN_COPY: default: g->SetClip(myData->path); break; case RGN_AND: { Gdiplus::Region region(myData->path); g->IntersectClip(®ion); } break; case RGN_DIFF: { Gdiplus::Region region(myData->path); Gdiplus::Region curClip; g->GetClip(&curClip); curClip.Exclude(®ion); g->SetClip(&curClip); } break; case RGN_OR: { Gdiplus::Region region(myData->path); Gdiplus::Region curClip; g->GetClip(&curClip); curClip.Union(®ion); g->SetClip(&curClip); } break; case RGN_XOR: { Gdiplus::Region region(myData->path); Gdiplus::Region curClip; g->GetClip(&curClip); curClip.Xor(®ion); g->SetClip(&curClip); } break; } delete myData->path; myData->path = NULL; myData->pathOpen = FALSE; } } break; case EMR_ABORTPATH: { if (myData->path != NULL) { delete myData->path; myData->path = NULL; myData->pathOpen = FALSE; } } break; case EMR_GDICOMMENT: break; case EMR_FILLRGN: break; case EMR_FRAMERGN: break; case EMR_INVERTRGN: break; case EMR_PAINTRGN: break; case EMR_EXTSELECTCLIPRGN: break; case EMR_BITBLT: { PEMRBITBLT pBitBlt = (PEMRBITBLT)lpEMFR; switch (pBitBlt->dwRop) { case BLACKNESS: { Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000)); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy)); } return; case WHITENESS: { Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff)); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + 1), TOREAL(pBitBlt->cyDest + 1)); } return; default: if (!ISSOURCEINROP3(pBitBlt->dwRop)) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(&brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy)); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy)); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(brush, TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest + cx), TOREAL(pBitBlt->cyDest + cy)); } } return; } break; } // Else assume SRCCOPY BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pBitBlt) + pBitBlt->offBmiSrc); BYTE *bits = ((BYTE *)pBitBlt) + pBitBlt->offBitsSrc; DibStream dibStream(bmi, bits); Gdiplus::Bitmap gpBitmap(&dibStream); Gdiplus::RectF destRect(TOREAL(pBitBlt->xDest), TOREAL(pBitBlt->yDest), TOREAL(pBitBlt->cxDest), TOREAL(pBitBlt->cyDest)); g->DrawImage(&gpBitmap, destRect, TOREAL(pBitBlt->xSrc), TOREAL(pBitBlt->ySrc), TOREAL(pBitBlt->cxDest), TOREAL(pBitBlt->cyDest), Gdiplus::UnitPixel); } break; case EMR_STRETCHBLT: { PEMRSTRETCHBLT pStretchBlt = (PEMRSTRETCHBLT)lpEMFR; switch (pStretchBlt->dwRop) { case BLACKNESS: { Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000)); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } return; case WHITENESS: { Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff)); float cx, cy; GetPixelSize (g, &cx, &cy); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } return; default: if (!ISSOURCEINROP3(pStretchBlt->dwRop)) { float cx, cy; GetPixelSize (g, &cx, &cy); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } } return; } break; } // Else assume SRCCOPY BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc); BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc; DibStream dibStream(bmi, bits); Gdiplus::Bitmap gpBitmap(&dibStream); Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest), TOREAL(pStretchBlt->cyDest)); g->DrawImage(&gpBitmap, destRect, TOREAL(pStretchBlt->xSrc), TOREAL(pStretchBlt->ySrc), TOREAL(pStretchBlt->cxSrc), TOREAL(pStretchBlt->cySrc), Gdiplus::UnitPixel); } break; case EMR_MASKBLT: break; case EMR_PLGBLT: break; case EMR_SETDIBITSTODEVICE: break; #if 0 typedef struct tagEMRSETDIBITSTODEVICE { EMR emr; RECTL rclBounds; // Inclusive-inclusive bounds in device units LONG xDest; LONG yDest; LONG xSrc; LONG ySrc; LONG cxSrc; LONG cySrc; DWORD offBmiSrc; // Offset to the source BITMAPINFO structure DWORD cbBmiSrc; // Size of the source BITMAPINFO structure DWORD offBitsSrc; // Offset to the source bitmap bits DWORD cbBitsSrc; // Size of the source bitmap bits DWORD iUsageSrc; // Source bitmap info color table usage DWORD iStartScan; DWORD cScans; } EMRSETDIBITSTODEVICE, *PEMRSETDIBITSTODEVICE; #endif case EMR_STRETCHDIBITS: { PEMRSTRETCHDIBITS pStretchBlt = (PEMRSTRETCHDIBITS)lpEMFR; switch (pStretchBlt->dwRop) { case BLACKNESS: { float cx, cy; GetPixelSize (g, &cx, &cy); Gdiplus::SolidBrush brush(Gdiplus::Color(0xff000000)); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } return; case WHITENESS: { float cx, cy; GetPixelSize (g, &cx, &cy); Gdiplus::SolidBrush brush(Gdiplus::Color(0xffffffff)); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } return; default: if (!ISSOURCEINROP3(pStretchBlt->dwRop)) { float cx, cy; GetPixelSize (g, &cx, &cy); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillRectangle(&brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillRectangle(brush, TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest + cx), TOREAL(pStretchBlt->cyDest + cy)); } } return; } break; } // Else assume SRCCOPY BITMAPINFO *bmi = (BITMAPINFO *)(((BYTE *)pStretchBlt) + pStretchBlt->offBmiSrc); BYTE *bits = ((BYTE *)pStretchBlt) + pStretchBlt->offBitsSrc; DibStream dibStream(bmi, bits); Gdiplus::Bitmap gpBitmap(&dibStream); Gdiplus::RectF destRect(TOREAL(pStretchBlt->xDest), TOREAL(pStretchBlt->yDest), TOREAL(pStretchBlt->cxDest), TOREAL(pStretchBlt->cyDest)); g->DrawImage(&gpBitmap, destRect, TOREAL(pStretchBlt->xSrc), TOREAL(pStretchBlt->ySrc), TOREAL(pStretchBlt->cxSrc), TOREAL(pStretchBlt->cySrc), Gdiplus::UnitPixel); } break; case EMR_EXTCREATEFONTINDIRECTW: break; case EMR_EXTTEXTOUTA: break; case EMR_EXTTEXTOUTW: break; case EMR_POLYBEZIER16: { PEMRPOLYBEZIER16 pBezier = (PEMRPOLYBEZIER16)lpEMFR; if (pBezier->cpts > 0) { int i = pBezier->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = pBezier->apts[i].x; points[i].Y = pBezier->apts[i].y; } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawBeziers(&pen, points, pBezier->cpts); } } else { myData->path->AddBeziers(points, pBezier->cpts); } delete [] points; } } break; case EMR_POLYGON16: { PEMRPOLYGON16 pPolygon = (PEMRPOLYGON16)lpEMFR; if (pPolygon->cpts > 0) { int i = pPolygon->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = pPolygon->apts[i].x; points[i].Y = pPolygon->apts[i].y; } while (i > 0); if (!myData->pathOpen) { Gdiplus::GraphicsPath path(myData->fillMode); path.AddPolygon(points, pPolygon->cpts); if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } else { myData->path->AddPolygon(points, pPolygon->cpts); } delete [] points; } } break; case EMR_POLYLINE16: { PEMRPOLYLINE16 pPolyline = (PEMRPOLYLINE16)lpEMFR; if (pPolyline->cpts > 0) { int i = pPolyline->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i]; do { i--; points[i].X = pPolyline->apts[i].x; points[i].Y = pPolyline->apts[i].y; } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawLines(&pen, points, pPolyline->cpts); } } else { myData->path->AddLines(points, pPolyline->cpts); } delete [] points; } } break; case EMR_POLYBEZIERTO16: { PEMRPOLYBEZIERTO16 pBezier = (PEMRPOLYBEZIERTO16)lpEMFR; if (pBezier->cpts > 0) { int i = pBezier->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i+1]; do { points[i].X = pBezier->apts[i-1].x; points[i].Y = pBezier->apts[i-1].y; i--; } while (i > 0); points[0] = myData->curPos; myData->curPos = points[pBezier->cpts]; if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawBeziers(&pen, points, pBezier->cpts+1); } } else { myData->path->AddBeziers(points, pBezier->cpts+1); } delete [] points; } } break; case EMR_POLYLINETO16: { PEMRPOLYLINETO16 pPolyline = (PEMRPOLYLINETO16)lpEMFR; if (pPolyline->cpts > 0) { int i = pPolyline->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i+1]; do { points[i].X = pPolyline->apts[i-1].x; points[i].Y = pPolyline->apts[i-1].y; i--; } while (i > 0); points[0] = myData->curPos; myData->curPos = points[pPolyline->cpts]; if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawLines(&pen, points, pPolyline->cpts+1); } } else { myData->path->AddLines(points, pPolyline->cpts+1); } delete [] points; } } break; case EMR_POLYPOLYLINE16: { PEMRPOLYPOLYLINE16 pPolyline = (PEMRPOLYPOLYLINE16)lpEMFR; if ((pPolyline->cpts > 0) && (pPolyline->nPolys > 0)) { int i = pPolyline->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i]; POINTS * metaPoints = (POINTS *)(pPolyline->aPolyCounts + pPolyline->nPolys); do { i--; points[i].X = metaPoints[i].x; points[i].Y = metaPoints[i].y; } while (i > 0); if (!myData->pathOpen) { if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); i = 0; Gdiplus::PointF * tmpPoints = points; DWORD count; do { count = pPolyline->aPolyCounts[i]; g->DrawLines(&pen, tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolyline->nPolys); } } else { i = 0; Gdiplus::PointF * tmpPoints = points; DWORD count; do { count = pPolyline->aPolyCounts[i]; myData->path->AddLines(tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolyline->nPolys); } delete [] points; } } break; case EMR_POLYPOLYGON16: { PEMRPOLYPOLYGON16 pPolygon = (PEMRPOLYPOLYGON16)lpEMFR; if ((pPolygon->cpts > 0) && (pPolygon->nPolys > 0)) { int i = pPolygon->cpts; Gdiplus::PointF * points = new Gdiplus::PointF[i]; POINTS * metaPoints = (POINTS *)(pPolygon->aPolyCounts + pPolygon->nPolys); do { i--; points[i].X = metaPoints[i].x; points[i].Y = metaPoints[i].y; } while (i > 0); Gdiplus::GraphicsPath path(myData->fillMode); Gdiplus::GraphicsPath * tmpPath = &path; if (myData->pathOpen) { tmpPath = myData->path; } Gdiplus::PointF * tmpPoints = points; DWORD count; i = 0; do { count = pPolygon->aPolyCounts[i]; tmpPath->StartFigure(); tmpPath->AddPolygon(tmpPoints, count); tmpPoints += count; } while ((UINT)++i < pPolygon->nPolys); if (!myData->pathOpen) { if (myData->curBrush != 0) { if (myData->curPatIndex < 0) { if (myData->curBrushPattern == NULL) { Gdiplus::SolidBrush brush(Gdiplus::Color(myData->curBrush)); g->FillPath(&brush, &path); } else { BITMAPINFO * bmi = (BITMAPINFO *)myData->curBrushPattern->bmi; BYTE * bits = ((BYTE *)bmi) + myData->curBrushPattern->bitsOffset; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } else { BITMAPINFO * bmi = (BITMAPINFO *)&hatchBrushInfo; BYTE * bits = (BYTE *)HatchPatterns[myData->curPatIndex]; bmi->bmiColors[1].rgbRed = (myData->curBrush & Gdiplus::Color::RedMask) >> Gdiplus::Color::RedShift; bmi->bmiColors[1].rgbGreen = (myData->curBrush & Gdiplus::Color::GreenMask) >> Gdiplus::Color::GreenShift; bmi->bmiColors[1].rgbBlue = (myData->curBrush & Gdiplus::Color::BlueMask) >> Gdiplus::Color::BlueShift; DibBrush brush(bmi, bits); g->FillPath(brush, &path); } } if (myData->curPen != 0) { Gdiplus::Pen pen(Gdiplus::Color(myData->curPen), TOREAL(myData->curPenWidth)); pen.SetMiterLimit(myData->miterLimit); g->DrawPath(&pen, &path); } } delete [] points; } } break; case EMR_POLYDRAW16: break; case EMR_CREATEMONOBRUSH: break; case EMR_CREATEDIBPATTERNBRUSHPT: { PEMRCREATEDIBPATTERNBRUSHPT pBrush = (PEMRCREATEDIBPATTERNBRUSHPT)lpEMFR; ASSERT(pBrush->ihBrush < myData->numObjects); myData->pObjects[pBrush->ihBrush].type = MYOBJECTS::BrushObjectType; myData->pObjects[pBrush->ihBrush].color = 0xFF808080; myData->pObjects[pBrush->ihBrush].patIndex = -1; delete myData->pObjects[pBrush->ihBrush].brushPattern; myData->pObjects[pBrush->ihBrush].brushPattern = new MYPATTERNBRUSH(); if (myData->pObjects[pBrush->ihBrush].brushPattern != NULL) { BYTE * data = new BYTE[pBrush->cbBmi + pBrush->cbBits]; if (data != NULL) { memcpy(data, ((BYTE *)pBrush) + pBrush->offBmi, pBrush->cbBmi); memcpy(data + pBrush->cbBmi, ((BYTE *)pBrush) + pBrush->offBits, pBrush->cbBits); myData->pObjects[pBrush->ihBrush].brushPattern->bmi = (BITMAPINFO *)data; myData->pObjects[pBrush->ihBrush].brushPattern->bitsOffset = pBrush->cbBmi; } else { delete myData->pObjects[pBrush->ihBrush].brushPattern; myData->pObjects[pBrush->ihBrush].brushPattern = NULL; } } } break; case EMR_EXTCREATEPEN: { PEMREXTCREATEPEN pPen = (PEMREXTCREATEPEN)lpEMFR; COLORREF cRef = pPen->elp.elpColor; ASSERT((cRef & 0x01000000) == 0); ASSERT(pPen->ihPen < myData->numObjects); delete myData->pObjects[pPen->ihPen].brushPattern; myData->pObjects[pPen->ihPen].brushPattern = NULL; myData->pObjects[pPen->ihPen].type = MYOBJECTS::PenObjectType; myData->pObjects[pPen->ihPen].color = Gdiplus::Color::MakeARGB(0xff, GetRValue(cRef), GetGValue(cRef), GetBValue(cRef)); myData->pObjects[pPen->ihPen].penWidth = pPen->elp.elpWidth; } break; case EMR_POLYTEXTOUTA: break; case EMR_POLYTEXTOUTW: break; case EMR_SETICMMODE: case EMR_CREATECOLORSPACE: case EMR_SETCOLORSPACE: case EMR_DELETECOLORSPACE: case EMR_GLSRECORD: case EMR_GLSBOUNDEDRECORD: case EMR_PIXELFORMAT: break; case EMR_DRAWESCAPE: case EMR_EXTESCAPE: case EMR_STARTDOC: case EMR_SMALLTEXTOUT: case EMR_FORCEUFIMAPPING: case EMR_NAMEDESCAPE: case EMR_COLORCORRECTPALETTE: case EMR_SETICMPROFILEA: case EMR_SETICMPROFILEW: case EMR_ALPHABLEND: case EMR_SETLAYOUT: case EMR_TRANSPARENTBLT: case EMR_GRADIENTFILL: case EMR_SETLINKEDUFIS: case EMR_SETTEXTJUSTIFICATION: case EMR_COLORMATCHTOTARGETW: case EMR_CREATECOLORSPACEW: break; } } BOOL StepRecord( Gdiplus::EmfPlusRecordType recordType, UINT recordFlags, UINT recordDataSize, const BYTE * recordData, VOID * callbackData, HDC hDC = NULL, LPHANDLETABLE lpHTable = NULL, LPMETARECORD lpMFR = NULL, LPENHMETARECORD lpEMFR = NULL, int nObj = 0 ); VOID ListRecord( Gdiplus::EmfPlusRecordType recordType ); /*********************************************************************** FUNCTION : EnumMFIndirect PARAMETERS : HDC hDC LPHANDLETABLE lpHTable LPMETARECORD lpMFR LPENHMETARECORD lpEMFR int nObj LPARAM lpData PURPOSE : called by EnumMetaFile and EnumEnhMetaFile. Handles the stepping of each metafile record. MESSAGES : none RETURNS : int COMMENTS : ENUMMFSTEP is used whenever records are to be played, regardless of whether you are playing records from the list, stepping all, or stepping a range. ENUMMFLIST is used when you need to add strings to a listbox that describe the type of reocrd. HISTORY : created 7/1/93 - denniscr ************************************************************************/ using Gdiplus::EmfPlusRecordType; int EnumMFIndirect(HDC hDC, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData) { BOOL DlgRet = TRUE; // // what is the enumeration action that we are taking? // switch (iEnumAction) { // //if the enumeration was entered ala the step metafile menu selection // case ENUMMFSTEP: if (bEnhMeta) { return StepRecord((EmfPlusRecordType)(lpEMFR->iType), 0, lpEMFR->nSize - sizeof(EMR), (BYTE *)lpEMFR->dParm, (VOID *)lpData, hDC, lpHTable, lpMFR, lpEMFR, nObj); } else { return StepRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction), 0, ((LONG)lpMFR->rdSize * 2) - 6, ((BYTE *)lpMFR) + 6, (VOID *)lpData, hDC, lpHTable, lpMFR, lpEMFR, nObj); } case ENUMMFLIST: if (bEnhMeta) { ListRecord((Gdiplus::EmfPlusRecordType)lpEMFR->iType); } else { ListRecord(GDIP_WMF_RECORD_TO_EMFPLUS(lpMFR->rdFunction)); } // //keep enumerating // return(1); } return 0; } /*********************************************************************** FUNCTION : ConvertEMFtoWMF PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile LPSTR lpszFileName - filename of disked based metafile PURPOSE : Convert an Windows metafile to an enhanced metafile MESSAGES : none RETURNS : int COMMENTS : HISTORY : created 7/22/93 - denniscr ************************************************************************/ BOOL ConvertWMFtoEMF(HMETAFILE hmf, LPSTR lpszFileName) { LPSTR lpWinMFBits; UINT uiSizeBuf; HENHMETAFILE hEnhMF; BOOL bRet = TRUE; // //get the size of the Windows metafile associated with hMF // if ((uiSizeBuf = GetMetaFileBitsEx((HMETAFILE)hMF, 0, NULL))) { // //allocate enough memory to hold metafile bits // lpWinMFBits = (char *)GlobalAllocPtr(GHND, uiSizeBuf); // //get the bits of the Windows metafile associated with hMF // if (lpWinMFBits && GetMetaFileBitsEx((HMETAFILE)hMF, uiSizeBuf, (LPVOID)lpWinMFBits)) { // //copy the bits into a memory based enhanced metafile // hEnhMF = SetWinMetaFileBits(uiSizeBuf, (LPBYTE)lpWinMFBits, NULL, NULL); // //copy the enhanced metafile to a disk based enhanced metafile // CopyEnhMetaFile(hEnhMF, lpszFileName); // //done with the memory base enhanced metafile so get rid of it // DeleteEnhMetaFile(hEnhMF); // //done with the actual memory used to store bits so nuke it // GlobalFreePtr(lpWinMFBits); } else bRet = FALSE; } else bRet = FALSE; return (bRet); } /*********************************************************************** FUNCTION : ConvertEMFtoWMF PARAMETERS : HENHMETAFILE hEMF - handle to enhanced metafile LPSTR lpszFileName - filename of disked based metafile PURPOSE : Convert an enhanced metafile to an Windows metafile MESSAGES : none RETURNS : int COMMENTS : HISTORY : created 7/22/93 - denniscr ************************************************************************/ BOOL ConvertEMFtoWMF(HDC hrefDC, HENHMETAFILE hEMF, LPSTR lpszFileName) { LPSTR lpEMFBits; UINT uiSizeBuf; HMETAFILE hWMF; BOOL bRet = TRUE; DWORD dwBytesWritten ; // //get the size of the Windows metafile associated with hMF // if ((uiSizeBuf = Gdiplus::Metafile::EmfToWmfBits(hemf, 0, NULL, MM_ANISOTROPIC, Gdiplus::EmfToWmfBitsFlagsIncludePlaceable))) { // //allocate enough memory to hold metafile bits // lpEMFBits = (LPSTR)GlobalAllocPtr(GHND, uiSizeBuf); // //get the bits of the enhanced metafile associated with hEMF // if (lpEMFBits && Gdiplus::Metafile::EmfToWmfBits(hEMF, uiSizeBuf,(LPBYTE)lpEMFBits, MM_ANISOTROPIC, Gdiplus::EmfToWmfBitsFlagsIncludePlaceable)) { // Create a file and dump the metafile bits into it HANDLE hFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if(hFile != INVALID_HANDLE_VALUE) { WriteFile( hFile, (LPCVOID) lpEMFBits, uiSizeBuf, &dwBytesWritten, NULL ) ; CloseHandle(hFile); } /* // //copy the bits into a memory based Windows metafile // hWMF = SetMetaFileBitsEx(uiSizeBuf, (LPBYTE)lpEMFBits); // //copy the Windows metafile to a disk based Windows metafile // CopyMetaFile(hWMF, lpszFileName); // //done with the memory base enhanced metafile so get rid of it // DeleteMetaFile((HMETAFILE)hMF); */ // //done with the actual memory used to store bits so nuke it // GlobalFreePtr(lpEMFBits); } else bRet = FALSE; } else bRet = FALSE; return (bRet); } BOOL StepRecord( Gdiplus::EmfPlusRecordType recordType, UINT recordFlags, UINT recordDataSize, const BYTE * recordData, VOID * callbackData, HDC hDC, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, LPENHMETARECORD lpEMFR, int nObj ) { // //keep track of the current metafile record number // iRecNum++; // //allocate memory for the record. this memory will be used by //other functions that need to use the contents of the record // hMem = GlobalAlloc(GPTR /*GHND*/, (bEnhMeta) ? sizeof(EMR) + recordDataSize : 6 + recordDataSize); // //if the memory was successfully allocated // if (hMem) { BOOL DlgRet = TRUE; if (bEnhMeta) { // //obtain a long pointer to this memory // if ((lpEMFParams = (LPEMFPARAMETERS)GlobalLock(hMem)) == NULL) { // //we were unable to allocate memory for the record // MessageBox(hWndMain, "Memory allocation failed", NULL, MB_OK | MB_ICONHAND); } else { // //copy the contents of the record to the global memory // emfMetaRec.nSize = sizeof(EMR) + recordDataSize; emfMetaRec.iType = recordType; unsigned long i; for (i = 0;(DWORD)i < recordDataSize / sizeof(DWORD); i++) { *lpEMFParams++ = ((DWORD *)recordData)[i]; } } } else { /* obtain a long pointer to this memory */ lpMFParams = (LPPARAMETERS)GlobalLock(hMem); /* copy the contents of the record to the global memory */ MetaRec.rdSize = (6 + recordDataSize) / 2; MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType); DWORD i; for (i = 0; (DWORD)i < (recordDataSize / 2); i++) { *lpMFParams++ = ((WORD *)recordData)[i]; } } GlobalUnlock(hMem); // //if STEPPING through metafile records that have been selected //by selecting the menu options Play - Step - All, Play - Step - //Range, or selecting records from the View - List listbox // if ( !bPlayItAll || ( bEnumRange && iRecNum >= (WORD)iStartRange && iRecNum <= (WORD)iEndRange ) || ( bPlayList && !bPlayItAll ) ) { // //if playing records selected from the View - List //listbox of records if (bPlayList) { // //if playing the selected records // if (bPlaySelList) { // //if done playing the selected records then stop the enumeration // if (iCount == iNumSel) { return(0); } // //if this is a selected record then play it // if ((WORD)lpSelMem[iCount] == iRecNum - 1) { // //initialize flag // bPlayRec = FALSE; // //increment the count // iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount; // //call the dialog box that lets you play or ignore this record */ // DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc); } else { // //initialize flag and do nothing else // bPlayRec = FALSE; } } // //playing the unselected records // else { // //if this is one of the selected records then increment //the record count and init a flag but do nothing else // if ((WORD)lpSelMem[iCount] == iRecNum - 1) { // //set count to next selected record in listbox // iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount; bPlayRec = FALSE; } // //this is not one of the selected records which is what we //want in this case. So, init a flag give the user the //opportunity to play the record // else { bPlayRec = FALSE; DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc); } } } //bPlayList // //stepping records from the Play - Step menu option // else { // //init a flag and show the record contents // bPlayRec = FALSE; iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount; DlgRet = (BOOL) DialogBox((HINSTANCE)hInst, (LPSTR)"WMFDLG", hWndMain, WMFRecDlgProc); } } //end of STEPPING the metafile // //bPlayItAll is TRUE. This is set when the user either //selects the menu option Play - All or pushes the GO button //in the view record dialog box // else { // //we were stepping records selected from the listbox and //the user pressed the GO button // //Don't bother returning 0 to stop enumeration. We need to //play to the end of the metafile in this case anyway // if (bPlayList) { // //we were playing the selected records // if (bPlaySelList) { // //if all of the selected records have been played then //stop the enumeration // if (iCount == iNumSel) { return(0); } // //set bPlayRec so the record will be played without user //interation and then update the record counter // if ((WORD)lpSelMem[iCount] == iRecNum - 1) { bPlayRec = TRUE; iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount; } else // //it wasn't one of the selected records so don't play // { bPlayRec = FALSE; } } // //we were playing the unselected records // else { // //if it is a selected record then set bPlayRec to FALSE //so the record is not played // if ((WORD)lpSelMem[iCount] == iRecNum - 1) { bPlayRec = FALSE; iCount = (iCount < iLBItemsInBuf) ? ++iCount : iCount; } else { // //play the record // bPlayRec = TRUE; } } } //bPlayList } //GO button pushed // //Stop the enumeration if you were stepping a range and have //finished playing that range OR the user selected pushed //the STOP button in the view record dialog box // if ( ((bEnumRange) && (iRecNum > (WORD)iEndRange)) || (!DlgRet) ) { bPlayRec = FALSE; // //stop enumeration // return(0); } } //if (hMem) else // //we were unable to allocate memory for the record // { MessageBox(hWndMain, "Memory allocation failed", NULL, MB_OK | MB_ICONHAND); } // //Regardless of the method the user elected to play the //records, check the flag. If it is set then play the //record // if (bPlayRec) { if (bUseGdiPlusToPlay) { ((MYDATA *)callbackData)->metafile->PlayRecord(recordType, recordFlags, recordDataSize, recordData); } else if (bEnhMeta) { if (bConvertToGdiPlus) { GpPlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj, (LPARAM)callbackData); } else { PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, (UINT)nObj); } } else if(!PlayMetaFileRecord(hDC, lpHTable, lpMFR, (UINT)nObj)) { ASSERT(FALSE); } } // //done with the record so get rid of it // GlobalFree(hMem); // //if we made it this far then continue the enumeration // return(1); } VOID ListRecord( Gdiplus::EmfPlusRecordType recordType ) { char szMetaFunction[100]; iRecNum++; // //format the listbox string // wsprintf((LPSTR)szMetaFunction, (LPSTR)"%d - ", iRecNum); // //get the function number contained in the record // if (bEnhMeta) emfMetaRec.iType = recordType; else MetaRec.rdFunction = GDIP_EMFPLUS_RECORD_TO_WMF(recordType); // //lookup the function number in the structure MetaFunctions // int i; if (bEnhMeta) { for (i = NUMMETAFUNCTIONS; i < NUMENHMETARECORDS; i++) { if (recordType == (INT)emfMetaRecords[i].iType) break; } } else // WMF { for (i = 0; i < NUMMETAFUNCTIONS; i++) { if (recordType == (INT)emfMetaRecords[i].iType) break; } } // //if the function number is not found then describe this record //as an "Unknown" type otherwise use the corresponding name //found in the lookup // if (recordType != (INT)emfMetaRecords[i].iType) lstrcat((LPSTR)szMetaFunction, (LPSTR)"Unknown"); else lstrcat((LPSTR)szMetaFunction,(LPSTR)emfMetaRecords[i].szRecordName); // //add the string to the listbox // SendDlgItemMessage((HWND)CurrenthDlg, IDL_LBREC, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szMetaFunction); } extern "C" BOOL CALLBACK PlayGdipMetafileRecordCallback( Gdiplus::EmfPlusRecordType recordType, UINT recordFlags, UINT recordDataSize, const BYTE * recordData, VOID * callbackData ) { switch (iEnumAction) { case ENUMMFSTEP: return StepRecord(recordType, recordFlags, recordDataSize, recordData, callbackData); case ENUMMFLIST: ListRecord(recordType); break; } return TRUE; } /*********************************************************************** FUNCTION : GetMetaFileAndEnum PARAMETERS : HDC hDC PURPOSE : load the metafile if it has not already been loaded and begin enumerating it CALLS : WINDOWS GetMetaFile MakeProcInstance EnumMetaFile FreeProcInstance DeleteMetaFile MessageBox MESSAGES : none RETURNS : void COMMENTS : HISTORY : 1/16/91 - created - drc 7/1/93 - modified to work with EMFs - denniscr ************************************************************************/ extern "C" void GetMetaFileAndEnum( HWND hwnd, HDC hDC, int iAction) { MYDATA myData(hwnd); iEnumAction = iAction; // //if this is an enhanced metafile (emf) // RECT rc; GetClientRect(hWndMain, &rc); HPALETTE hpal = NULL; if (bEnhMeta) { if (hemf) { LPLOGPALETTE lpLogPal; HPALETTE hPal; int i; // //allocate memory for the logical palette including the array of //palette entries // lpLogPal = (LPLOGPALETTE) GlobalAllocPtr( GHND, sizeof(LOGPALETTE) + (sizeof (PALETTEENTRY) * EmfPtr.palNumEntries)); if (lpLogPal) { // //proceed only if there is a valid ptr to logical palette //and a palette array obtained from the emf // if (EmfPtr.lpPal) { lpLogPal->palVersion = 0x300; lpLogPal->palNumEntries = EmfPtr.palNumEntries; // //copy palette entries into palentry array // for (i = 0; i < EmfPtr.palNumEntries; i++) lpLogPal->palPalEntry[i] = *EmfPtr.lpPal++; // //reposition the ptr back to the beginning should we call this //code again // EmfPtr.lpPal -= EmfPtr.palNumEntries; // //create, select and realize the palette // if ((hPal = CreatePalette((LPLOGPALETTE)lpLogPal))) { SelectPalette(hDC, hPal, FALSE); RealizePalette(hDC); } } if (bUseGdiPlusToPlay) { // Select in the halftone palette for 256-color display mode testing hpal = Gdiplus::Graphics::GetHalftonePalette(); SelectPalette(hDC, hpal, FALSE); RealizePalette(hDC); // Need to delete this before returning; myData.g = Gdiplus::Graphics::FromHDC(hDC); myData.g->SetPixelOffsetMode(Gdiplus::PixelOffsetModeHalf); myData.g->SetInterpolationMode(Gdiplus::InterpolationModeNearestNeighbor); } // //enumerate the EMF. this is a bit odd simply because PlayEnhMetaFile //really obviates the need for doing this (this cannot be said for WMFs). //this app does it simply because it may be stepping the metafile records. //Most apps are generally not concerned about doing this. // if (bUseGdiPlusToPlay && (myData.g != NULL)) { Gdiplus::Metafile m1(hemf); Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); myData.metafile = &m1; if(myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok) MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR); myData.metafile = NULL; } else { // the rect needs to be inclusive-inclusive!!! rc.right--; rc.bottom--; if(!EnumEnhMetaFile(hDC, hemf, (ENHMFENUMPROC)EnhMetaFileEnumProc, (void*)&myData, &rc)) MessageBox(NULL, "Error", "An Error Occured while playing this metafile", MB_OK | MB_ICONERROR); } // //free palette memory // GlobalFreePtr(lpLogPal); } } } else { // //if there is a valid handle to a metafile begin enumerating it // if (hMF) { if (bUseGdiPlusToPlay) { // Select in the halftone palette for 256-color display mode testing hpal = Gdiplus::Graphics::GetHalftonePalette(); SelectPalette(hDC, hpal, FALSE); RealizePalette(hDC); // Need to delete this before returning; myData.g = Gdiplus::Graphics::FromHDC(hDC); } if (bUseGdiPlusToPlay && (myData.g != NULL)) { Gdiplus::WmfPlaceableFileHeader * wmfPlaceableFileHeader = NULL; if (bPlaceableMeta) { wmfPlaceableFileHeader = (Gdiplus::WmfPlaceableFileHeader *)&placeableWMFHeader; } Gdiplus::Metafile m1((HMETAFILE)hMF, wmfPlaceableFileHeader); Gdiplus::Rect r1(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); myData.metafile = &m1; if (myData.g->EnumerateMetafile(&m1, r1, PlayGdipMetafileRecordCallback, &myData) != Gdiplus::Ok) MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR); myData.metafile = NULL; } else { if (!EnumMetaFile(hDC, (HMETAFILE)hMF, (MFENUMPROC) MetaEnumProc, (LPARAM) 0)) MessageBox(NULL, "An Error Occured while playing this metafile", "Error", MB_OK | MB_ICONERROR); } } else MessageBox(hWndMain, "Invalid metafile handle", NULL, MB_OK | MB_ICONHAND); } if (myData.g != NULL ) { SelectObject(hDC, GetStockObject(DEFAULT_PALETTE)); DeleteObject(hpal); myData.g->Flush(); delete myData.g; myData.g = NULL; } return; }