home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / formats / msmeta / spec / winmeta.txt < prev   
Text File  |  1994-06-01  |  33KB  |  793 lines

  1. This summary comes from the Microsoft Developers Network CD:
  2.  
  3.  
  4. Enhanced Metafiles in Win32
  5.  
  6. Abstract
  7.  
  8. With the advent of the Microsoftr Win32╓ Application
  9. Programming Interface (API), a new metafile format called
  10. enhanced metafiles has been introduced. The overall design goal
  11. of the enhanced metafile was to describe a picture without any
  12. coding restrictions and to make a metafile easier to use.
  13. Enhanced metafiles have many advantages over the older
  14. Windows metafiles found in Microsoft Windows╓ version 3.1
  15. (Win16). Improvements found in the enhanced metafile include an
  16. expanded header, a description string, a metafile palette, and an
  17. increase in the number and type of graphics device interface
  18. (GDI) functions that may be recorded. In addition to these
  19. enhancements, the metafile record and playback code in Win32
  20. has been designed to remove all of the restrictions that applied to
  21. Windows metafiles with respect to scaling, clipping, embedding,
  22. and querying, among others. To top it off, enhanced metafiles
  23. may be played on any device in a device-independent manner.
  24. This article describes the differences between Windows metafiles
  25. and enhanced metafiles. Sample code that illustrates the basic
  26. concepts of creating and playing enhanced metafiles is provided
  27. at the end of this article.
  28.  
  29. Introduction
  30.  
  31. The tried-and-true Microsoftr Windows╓ metafile has been an
  32. invaluable aid to the development of numerous drawing and
  33. presentation applications for Windows. However, the "vanilla"
  34. Windows metafile did not address issues related to scalability 
  35. and device independence. Left on their own, developers 
  36. attempted to address this issue in various ways. Some 
  37. developers embedded application, location, or scaling comments
  38. in the metafiles. This resulted in extremely nonportable metafiles.
  39. Others added headers to the metafile that provided various
  40. application-specific information. The net result of most of these
  41. efforts was, once again, nonportable metafiles. However, one of
  42. these endeavorsplaceable metafilescaught on. Developed by
  43. Aldus Corporation, placeable metafiles include a 22-byte header
  44. that provides, among other things, mapping and measurement
  45. information that can be used to scale the metafile.
  46.  
  47. The proliferation of the placeable metafile, other homegrown
  48. formats, and the confusion of many developers regarding the use
  49. of metafiles led to a demand for a metafile format that addressed
  50. all of the development community's needs. Thus the Win32
  51. enhanced metafile was born. Developed by Microsoft, the
  52. enhanced metafile distinguishes itself from the Windows metafile
  53. in that it is device-independent and much easier to use.  Easier to
  54. use? You bet! Remember having to code two paths to deal with
  55. drawing? One code path drew to the screen; the second code
  56. path drew to metafiles. The only way to get around this was to
  57. use a subset of graphics device interface (GDI) functions that
  58. used logical coordinates. Although this permitted limited scaling
  59. capabilities, it restricted the use of many helpful GDI functions.
  60. You definitely couldn't query the metafile device context (DC) for
  61. information such as window origins and extents. With the advent
  62. of the enhanced metafile, those restrictions are unnecessary! A
  63. single code path is all that is required to draw to any DC,
  64. whether it be a metafile, screen, or printer DC.  Furthermore, you
  65. no longer need to use a subset of GDI; for example, you can now
  66. do the following:
  67.  
  68. DeleteObject(SelectObject(hdcMeta, hbrOldBrush));
  69.  
  70. Yes, the old object versus TRUE or FALSE is returned by
  71. SelectObject when used with a metafile DC. This was not
  72. possible with Windows metafiles and is a good indication of the
  73. potential for success of the enhanced metafile. Finally, in an
  74. enhanced metafile, you can query the current position in the client area.
  75. But what about all of those Windows metafiles? There are
  76. thousands of them in the marketplace. It would be a shame to
  77. see them go to waste. With this in mind, Win32 functions were
  78. written that convert Windows metafiles to enhanced metafiles.
  79. However, enhanced metafiles cannot be used in Win16. Figure 1
  80. illustrates the compatibility of the two metafile formats and
  81. environments.
  82.  
  83.  
  84. ED. NOTE: Figures are not available in this plain text version
  85. of the specification.
  86.  
  87.  
  88. Figure 1. Metafile compatibility in the Win16 and Win32 environments
  89.  
  90. This article discusses the differences between the Windows
  91. metafile and the enhanced metafile, the format of the enhanced
  92. metafile, its features, and techniques for its use.
  93.  
  94. Windows Metafiles vs. Enhanced Metafiles
  95.  
  96. A Windows metafile is used for applications written using the
  97. Windows version 3.x application programming interface (API).
  98. The format of a Windows metafile consists of a header and an
  99. array of metafile records. Windows metafiles are limited in their
  100. capabilities and should rarely be used in Win32-based
  101. applications. That being said, the Windows metafile functions are
  102. supported in Win32 to maintain backward compatibility with
  103. applications that use the older Windows metafiles.
  104.  
  105. An enhanced metafile is used in applications written using the
  106. Win32 API. (Win32s, however, does not implement enhanced
  107. metafiles.) The enhanced format consists of a header, a table of
  108. handles to GDI objects, a private palette, and an array of metafile
  109. records. Enhanced metafiles provide true device independence.
  110. You can think of the picture stored in an enhanced metafile as a
  111. snapshot of the video display taken at a particular moment.  This
  112. snapshot maintains its dimensions no matter where it appears:
  113. on a printer, a plotter, the desktop, or in the client area of any
  114. Win32-based application.
  115.  
  116. Metafile Structure
  117.  
  118. At first glance, Windows metafiles and enhanced metafiles share
  119. the same overall structure. They are an array of variable-length
  120. structures called metafile records. The first records in the
  121. metafile specify general information such as the resolution of the
  122. device on which the picture was created, the dimensions of the
  123. picture, and so on. The remaining records, which constitute the
  124. bulk of any metafile, correspond to the GDI functions required to
  125. draw the picture.
  126.  
  127. A closer inspection reveals a number of differences between
  128. them, as shown in Figure 2. Unlike the Windows metafile, the
  129. enhanced metafile has a different header and may include a
  130. description string and an optional palette stored in a special
  131. end-of-file record. The enhanced metafile also provides support
  132. for additional types of records.
  133.  
  134.  
  135. ED. NOTE:  Figure is not available in this plain text version
  136. of the spec.
  137.  
  138.  
  139. Figure 2. Structure of a Windows metafile and an enhanced metafile
  140.  
  141. Enhanced metafile header
  142.  
  143. The major difference between the Windows metafile header and
  144. the enhanced metafile header is that the Windows metafile
  145. header contains only size and version information, whereas the
  146. enhanced metafile header contains dimension and resolution
  147. information, as well as size and version information. The
  148. Windows metafile header has the following form:
  149.  
  150. typedef struct tagMETAHEADER {
  151.     WORD  mtType;
  152.     WORD  mtHeaderSize;
  153.     WORD  mtVersion;
  154.     DWORD mtSize;
  155.     WORD  mtNoObjects;
  156.     DWORD mtMaxRecord;
  157.     WORD  mtNoParameters;
  158. } METAHEADER;
  159.  
  160. In contrast, notice the added dimension and resolution
  161. information in the code for an enhanced metafile header below.
  162. This information is used by the metafile playback functions to
  163. achieve device independence:
  164.  
  165. typedef struct tagENHMETAHEADER
  166. {
  167.   DWORD   iType;           // Record type EMR_HEADER.
  168.   DWORD   nSize;           // Record size in bytes. This may be greater
  169.                            // than the sizeof(ENHMETAHEADER).
  170.   RECTL   rclBounds;       // Inclusive-inclusive bounds in device units.
  171.   RECTL   rclFrame;        // Inclusive-inclusive Picture Frame of
  172.                            // metafile in .01 mm units.
  173.   DWORD   dSignature;      // Signature.  Must be ENHMETA_SIGNATURE.
  174.  
  175.   DWORD   nVersion;        // Version number.
  176.   DWORD   nBytes;          // Size of the metafile in bytes.
  177.   DWORD   nRecords;        // Number of records in the metafile.
  178.   WORD    nHandles;        // Number of handles in the handle table.
  179.                            // Handle index zero is reserved.
  180.   WORD    sReserved;       // Reserved.  Must be zero.
  181.   DWORD   nDescription;    // Number of chars in the unicode description string.
  182.                            // This is 0 if there is no description string.
  183.  
  184.   DWORD   offDescription;  // Offset to the metafile description record.
  185.                            // This is 0 if there is no description string.
  186.   DWORD   nPalEntries;     // Number of entries in the metafile palette.
  187.   SIZEL   szlDevice;       // Size of the reference device in pixels.
  188.   SIZEL   szlMillimeters;  // Size of the reference device in millimeters.
  189. } ENHMETAHEADER;
  190.  
  191. A good question at this point might be, "How much of the header
  192. information in the enhanced metafile do I need to provide?" When
  193. you call CreateEnhMetafile, you provide a long pointer to a
  194. rectangle that specifies the picture frame, and you provide a DC
  195. that serves as a reference. The members szlDevice and
  196. szlMillimeters are derived from the reference DC. You can also
  197. provide a long pointer to a string that describes the metafile.
  198.  
  199. rclFrame
  200.  
  201. The picture frame is stored in the metafile header structure
  202. member rclFrame. When you create the metafile using
  203. CreateEnhMetaFile, a pointer to a RECT structure (lpRect) is
  204. among the parameters. It is this rectangle that specifies the
  205. picture frame. The left and top members of the RECT structure
  206. must be values less than the right and bottom members,
  207. respectively. Points along the edges of the rectangle are included
  208. in the picture. If lpRect is NULL, GDI computes the dimensions
  209. of the smallest rectangle that surrounds the picture. The lpRect
  210. parameter should be provided whenever possible.
  211.  
  212. nDescription and offDescription
  213.  
  214. Information regarding the description string is maintained in two
  215. structure members of the metafile header, nDescription and
  216. offDescription. This string is also specified when you create the
  217. metafile using CreateEnhMetaFile. The lpDescription parameter
  218. contains the address of the description string. When the metafile
  219. is created, the length of the description string is stored in the
  220. metafile header. When the metafile is closed, GDI writes the
  221. string to the metafile and updates offDescription in the
  222. header.
  223.  
  224. nPalEntries
  225.  
  226. As palettes are created and selected into a metafile DC, GDI
  227. accumulates the palette entries and places them in a "metafile
  228. palette." This palette is located in the EMR_EOF record. An
  229. application can store the palette in an enhanced metafile by
  230. calling either the CreatePalette or SetPaletteEntries function
  231. and the SelectPalette function before creating the picture.
  232. nPalEntries is updated as the palette is collected in the
  233. metafile palette.
  234.  
  235. Enhanced metafile records
  236.  
  237. The Windows metafile record and the enhanced metafile record
  238. are similar in structure and size (see code below). However,
  239. before breathing a sigh of relief, take a closer look at the record
  240. structure. The size and type members are reversed. This could
  241. be a potential pitfall when porting existing 16-bit Windows- based
  242. applications to Win32. Take note that the array of parameters is
  243. now an array of DWORD values to accommodate the 32-bit girth of GDI.
  244.  
  245. typedef struct tagMETARECORD
  246.   {
  247.     DWORD       rdSize;        // Record size in bytes
  248.     WORD        rdFunction;    // Record type META_XXX
  249.     WORD        rdParm[1];     // WORD array of parameters
  250.   } METARECORD;
  251.  
  252.  
  253.  
  254. typedef struct tagENHMETARECORD
  255. {
  256.     DWORD   iType;              // Record type EMR_XXX
  257.     DWORD   nSize;              // Record size in bytes
  258.     DWORD   dParm[1];           // DWORD Array of parameters
  259. } ENHMETARECORD;
  260.  
  261. Several new metafile records have been added to an already
  262. extensive list of records. Table 1 lists the records found in
  263. enhanced metafile records with their corresponding iType values,
  264. which can be found in WINGDI.H. Some of the records seem to
  265. be similar, for example, EMR_EXTTEXTOUTA and
  266. EMR_EXTTEXTOUTW. The A specifies that the text is based on
  267. ANSI and the W indicates that it is based on UNICODE.  Another
  268. similar pair is EMR_POLYLINE and EMR_POLYLINE16. The 16
  269. indicates that GDI has converted the points for PolyLine to 16
  270. bits for the purpose of saving space in the metafile.
  271.  
  272. Table 1. Enhanced Metafile Records
  273.  
  274. Record Value        Record Value
  275.  
  276. EMR_ABORTPATH        68
  277. EMR_POLYLINE        4
  278. EMR_ANGLEARC        41
  279. EMR_POLYLINE16        87
  280. EMR_ARC            45
  281. EMR_POLYLINETO        6
  282. EMR_ARCTO        55
  283. EMR_POLYLINETO16    89
  284. EMR_BEGINPATH        59
  285. EMR_POLYPOLYGON        8
  286. EMR_BITBLT        76
  287. EMR_POLYPOLYGON16    91
  288. EMR_CHORD        46
  289. EMR_POLYPOLYLINE    7
  290. EMR_CLOSEFIGURE        61
  291. EMR_POLYPOLYLINE16    90
  292. EMR_CREATEBRUSHINDIRECT    39
  293. EMR_POLYTEXTOUTA    96
  294. EMR_CREATEDIBPATTERNBRUSHPT 94
  295. EMR_POLYTEXTOUTW    97
  296. EMR_CREATEMONOBRUSH    93
  297. EMR_REALIZEPALETTE    52
  298. EMR_CREATEPALETTE    49
  299. EMR_RECTANGLE        43
  300.  
  301. EMR_CREATEPEN        38
  302. EMR_RESIZEPALETTE    51
  303. EMR_DELETEOBJECT    40
  304. EMR_RESTOREDC        34
  305. EMR_ELLIPSE        42
  306. EMR_ROUNDRECT        44
  307. EMR_ENDPATH        60
  308. EMR_SAVEDC        33
  309. EMR_EOF            14
  310. EMR_SCALEVIEWPORTEXTEX    31
  311. EMR_EXCLUDECLIPRECT    29
  312. EMR_SCALEWINDOWEXTEX    32
  313. EMR_EXTCREATEFONTINDIRECTW 82
  314. EMR_SELECTCLIPPATH    67
  315. EMR_EXTCREATEPEN    95
  316. EMR_SELECTOBJECT    37
  317. EMR_EXTFLOODFILL    53
  318. EMR_SELECTPALETTE    48
  319. EMR_EXTSELECTCLIPRGN    75
  320. EMR_SETARCDIRECTION    57
  321. EMR_EXTTEXTOUTA        83
  322. EMR_SETBKCOLOR        25
  323.  
  324. EMR_EXTTEXTOUTW        84
  325. EMR_SETBKMODE        18
  326. EMR_FILLPATH        62
  327. EMR_SETBRUSHORGEX    13
  328. EMR_FILLRGN        71
  329. EMR_SETCOLORADJUSTMENT    23
  330. EMR_FLATTENPATH        65
  331. EMR_SETDIBITSTODEVICE    80
  332. EMR_FRAMERGN        72
  333. EMR_SETMAPMODE        17
  334. EMR_GDICOMMENT        70
  335. EMR_SETMAPPERFLAGS    16
  336. EMR_HEADER        1
  337. EMR_SETMETARGN        28
  338. EMR_INTERSECTCLIPRECT    30
  339. EMR_SETMITERLIMIT    58
  340. EMR_INVERTRGN        73
  341. EMR_SETPALETTEENTRIES    50
  342. EMR_LINETO        54
  343. EMR_SETPIXELV        15
  344. EMR_MASKBLT        78
  345. EMR_SETPOLYFILLMODE    19
  346. EMR_MODIFYWORLDTRANSFORM 36
  347. EMR_SETROP2        20
  348.  
  349. EMR_MOVETOEX        27
  350. EMR_SETSTRETCHBLTMODE    21
  351. EMR_OFFSETCLIPRGN    26
  352. EMR_SETTEXTALIGN    22
  353. EMR_PAINTRGN        74
  354. EMR_SETTEXTCOLOR    24
  355. EMR_PIE            47
  356. EMR_SETVIEWPORTEXTEX    11
  357. EMR_PLGBLT        79
  358. EMR_SETVIEWPORTORGEX    12
  359. EMR_POLYBEZIER        2
  360. EMR_SETWINDOWEXTEX    9
  361. EMR_POLYBEZIER16    85
  362. EMR_SETWINDOWORGEX    10
  363. EMR_POLYBEZIERTO    5
  364. EMR_SETWORLDTRANSFORM    35
  365. EMR_POLYBEZIERTO16    88
  366. EMR_STRETCHBLT        77
  367. EMR_POLYDRAW        56
  368. EMR_STRETCHDIBITS    81
  369. EMR_POLYDRAW16        92
  370. EMR_STROKEANDFILLPATH    63
  371.  
  372. EMR_POLYGON        3
  373. EMR_STROKEPATH        64
  374. EMR_POLYGON16        86
  375. EMR_WIDENPATH        66
  376.  
  377. Of the records listed in Table 1, two are present in every
  378. enhanced metafile. The first record in any enhanced metafile is
  379. the metafile header. The value of this record is EMR_HEADER
  380. (1). The last record of an enhanced metafile is always the
  381. end-of-file record. The value of this record is EMR_EOF (14).
  382. In addition to the enhanced metafile header and metafile records,
  383. two additional pieces of data may be found in an enhanced
  384. metafile. The optional description string follows the enhanced
  385. metafile header. An optional color palette, if it exists, is
  386. contained in a special enhanced metafile record, the EMR_EOF
  387. record. The EMR_EOF is present even when a palette is not
  388. available.
  389.  
  390. Description string
  391.  
  392. Have you ever just wanted to know what was in a given metafile
  393. without having to decipher a cryptic filename or play back the
  394. entire metafile? The enhanced metafile provides an optional
  395. description string that provides exactly this information.  In
  396. addition to a descriptive name, the string specifies the name of
  397. the application that created the picture. The string must contain
  398. a null character between the application name and the picture
  399. name. It must terminate with two null characters; for example,
  400. "ACME Inc.\0Rocket Skates\0\0", where \0 represents the null
  401. character. If lpDescription is NULL, there is no corresponding
  402. entry in the header of the enhanced metafile. If the description
  403. string is present, it is found offDescription bytes from the
  404. beginning of the ENHMETAHEADER structure. The array found at
  405. that offset contains nDescription characters. A convenient way
  406. to obtain the description string is to use the function
  407. GetEnhMetaFileDescription.
  408.  
  409. Color palette
  410.  
  411. When a palette was required in a Windows metafile, you
  412. recorded a CreatePalette, SelectPalette, and RealizePalette
  413. sequence. When the Windows metafile was played back, the
  414. palette was selected as a foreground palette. The realization of
  415. the foreground palette typically resulted in odd screen behavior
  416. as the other palettes went to the background. With the enhanced
  417. metafiles, palette sequences may still be recorded, but they are
  418. never selected and realized as foreground palettes when they are
  419. subsequently played back. These palette functions serve only to
  420. build the metafile palette. Enhanced metafiles place this optional
  421. palette in the metafile end-of-file record (EMR_EOF).  Although
  422. the palette is optional, there are advantages to using it.  One
  423. palette may be generated and used for the duration of the
  424. playback, thus avoiding the problems associated with foreground
  425. and background palette changes. The optional palette also
  426. makes it easier for a palette-oriented application to examine the
  427. metafile colors and merge them with an existing palette. The
  428. easiest way to get the palette is to call
  429. GetEnhMetaFilePaletteEntries. However, you can locate the
  430. palette yourself if you wish. First, determine whether there is a
  431. palette. This is done by examining nPalEntries in the enhanced
  432. metafile header or in the last record of the metafile, the
  433. EMR_EOF record (see code below).
  434.  
  435. typedef struct tagEMREOF
  436. {
  437.     EMR     emr;            // Base enhanced metafile record.
  438.     DWORD   nPalEntries;    // Number of palette entries.
  439.     DWORD   offPalEntries;  // Offset to the palette entries.
  440.     DWORD   nSizeLast;      // Same as emr.nSize and must be the
  441.                             // last DWORD of the record.  The palette
  442.                             // entries, if they exist, precede this field.
  443. } EMREOF;
  444.  
  445. If this value is greater than zero, a palette is present.  The
  446. nSizeLast member of the EMR_EOF record indicates how many
  447. bytes to seek back to find the beginning of the EMR_EOF record.
  448. Seek forward from this point by offPalEntries and bingo! you
  449. have a palette location. After having used either method to obtain
  450. the palette, you can simply select the palette into the destination
  451. DC, realize it, and then play back the metafile.
  452.  
  453. Device Independence
  454.  
  455. Achieving device independence was very difficult, if not
  456. impossible, with Windows metafiles. The placeable variant of the
  457. Windows metafile provided the best shot at this. The additional
  458. header provided in the placeable metafile (see code below)
  459. provided an opportunity for an application to render these
  460. metafiles in a device-relative way.
  461.  
  462. typedef struct tagPLACEABLEMETAFILEHEADER {
  463.     DWORD   key;
  464.     HANDLE  hmf;
  465.     RECT    bbox;
  466.     WORD    inch;
  467.     DWORD   reserved;
  468.     WORD    checksum;
  469. } PLACEABLEMETAFILEHEADER;
  470.  
  471. Device independence was typically achieved by setting the
  472. mapping mode to anisotropic, setting the viewport extents to the
  473. physical dimensions of the device, and finally setting the
  474. windows extents to the product of the device's physical
  475. dimensions (in inches) and the metafile units per inch (contained
  476. in the inch member of the header structure). The biggest problem
  477. with this approach was that variants of the placeable Windows
  478. metafile began surfacing. Often the mapping mode and viewport
  479. extents were included in the metafile as records. This
  480. necessitated enumerating the metafile as a method of filtering
  481. out undesirable records. Unfortunately, the bounding box and
  482. metafile units per inch often did not match the environment being
  483. set by the undesirable metafile records! This led to the situation
  484. in which even the placeable metafiles were, once again,
  485. application-specific.
  486.  
  487. Device independence is a key feature of enhanced metafiles.  The
  488. Microsoft Win32 Software Development Kit (SDK) for Windows
  489. NT Programmer's Reference: Overviews states that "...when an
  490. application creates a picture measuring 2 inches by 4 inches on
  491. a VGA display and stores that picture in a metafile, it (the
  492. picture) will maintain those original dimensions when it is printed
  493. on a 300 dpi laser printer or copied over a network and displayed
  494. in another application that is running on an 8514/A video
  495. display." So, just how is this done? The key to achieving this
  496. device independence is the use of a reference device context,
  497. that is, the context of the device on which the picture was
  498. created. When a metafile is created, information regarding the
  499. reference DC is placed in the enhanced metafile header. More
  500. specifically, GDI calls GetDeviceCaps and assigns the
  501. HORZSIZE and VERTSIZE return values to szlMillimeters and
  502. assigns the HORZRES and VERTRES return values to szlDevice
  503. . The rclFrame member is assigned the bounding rectangle
  504. specified in the lpRect parameter of CreateEnhMetaFile. If
  505. lpRect is NULL, GDI determines the bounding rectangle and
  506. assigns it to rclFrame. This information is sufficient to
  507. enable
  508. the playback functions to provide device independence. When a
  509. metafile is played back, the picture undergoes a series of
  510. transformations that scale and translate the picture to the output
  511. rectangle that was specified in the call to the PlayEnhMetaFile
  512. or EnumEnhMetaFile playback functions. These
  513. transformations rely on the dimensions of the picture frame
  514. (
  515. rclFrame), the dimensions of the device upon which the metafile
  516. was created (szlMillimeters and szlDevice), and the
  517. world-to-page transform values currently set in the
  518. destination DC.
  519.  
  520. Compatibility
  521.  
  522. Although it is not recommended, Windows metafiles can be used
  523. with Win32-based applications. Unfortunately, enhanced
  524. metafiles cannot be used in Windows version 3.x. The Win32 API
  525. provides these familiar-sounding functions that manipulate
  526. Windows metafiles:
  527.  
  528. CloseMetaFile        Closes a Windows metafile DC.
  529. CopyMetaFile        Copies a Windows metafile.
  530. CreateMetaFile        Creates a Windows metafile DC.
  531. DeleteMetaFile        Invalidates Windows metafile handle.
  532. EnumMetaFile        Returns GDI calls within a Windows metafile.
  533. EnumMetaFileProc    Processes metafile data.
  534. GetMetaFile        Creates a Windows metafile.
  535. GetMetaFileBitsEx    Copies Windows metafile bits to a buffer.
  536. PlayMetaFile        Plays a Windows metafile to a DC.
  537.  
  538. PlayMetaFileRecord    Plays a Windows metafile record.
  539. SetMetaFileBitsEx    Creates a memory-based Windows metafile from data.
  540. GetMetaFileBits        Obsolete; use GetMetaFileBitsEx.
  541. SetMetaFileBits        Obsolete; use SetMetaFileBitsEx.
  542.  
  543. In addition to providing functions that enable the use of Windows
  544. metafiles, the Win32 API also provides functions to convert
  545. Windows metafiles into enhanced metafiles. These include the
  546. following functions:
  547.  
  548. GetWinMetaFileBits  Retrieves enhanced metafile contents in Windows format.
  549. SetWinMetaFileBits  Creates enhanced metafile from Windows metafile data.
  550.  
  551. Pulling It All Together
  552.  
  553. At this point, the differences between a Windows metafile and an
  554. enhanced metafile should be clear:
  555.  
  556. * The enhanced metafile header is larger and more complete
  557. than a Windows metafile.
  558.  
  559. * The enhanced metafile may contain a description string or a
  560. palette.
  561.  
  562. * The enhanced metafile achieves device independence by
  563. means of a reference DC and special transformations in the
  564. playback functions.
  565.  
  566. A quick look at the enhanced metafile functions and some
  567. example code should help clarify the features of enhanced
  568. metafiles.
  569.  
  570. Enhanced Metafile Functions
  571.  
  572. The following functions are very similar to the functions used for
  573. Windows metafiles. The differences that exist do so to
  574. accommodate new features of enhanced metafiles.
  575.  
  576. CloseEnhMetaFile    Closes an enhanced metafile DC.
  577. CopyEnhMetaFile     Copies an enhanced metafile.
  578. CreateEnhMetaFile   Creates an enhanced metafile DC.
  579. DeleteEnhMetaFile   Invalidates enhanced metafile handle.
  580. EnhMetaFileProc     Processes enhanced metafile data.
  581. EnumEnhMetaFile     Returns GDI calls within an enhanced metafile.
  582. GdiComment          Adds a comment to an enhanced metafile.
  583. GetEnhMetaFile      Creates an enhanced metafile.
  584.  
  585. GetEnhMetaFileBits  Copies enhanced metafile bits to a buffer.
  586. GetEnhMetaFileDescription     Returns creator and title for enhanced metafile.
  587. GetEnhMetaFileHeader          Returns enhanced metafile header.
  588. GetEnhMetaFilePaletteEntries  Returns enhanced metafile palette entries.
  589. PlayEnhMetaFile               Plays an enhanced metafile to a DC.
  590. PlayEnhMetaFileRecord         Plays an enhanced metafile record.
  591. SetEnhMetaFileBits  Creates a memory-based enhanced metafile from data.
  592.  
  593. GdiComment
  594.  
  595. GdiComment deserves a little elaboration. When a comment
  596. was needed in a Windows metafile, the MFCOMMENT printer
  597. escape was used. These comments were restricted to private
  598. data only. The MFCOMMENT printer escape cannot be used in
  599. enhanced metafiles. Escapes, in general, cannot be used in
  600. enhanced metafiles because they would introduce device
  601. dependence, which is in direct opposition to the goal of device
  602. independence. Realizing that there is still a place for private data
  603. in metafiles, the architects of the Win32 API made GdiComment
  604. available for embedding private information in enhanced
  605. metafiles. But GdiComment is more than simply an alternative
  606. to MFCOMMENT. It was designed to enable public comments as
  607. well. The currently supported public comments include:
  608.  
  609.      GDICOMMENT_WINDOWS_METAFILE
  610.      GDICOMMENT_BEGINGROUP
  611.      GDICOMMENT_ENDGROUP
  612.      GDICOMMENT_MULTIFORMATS
  613.  
  614. The use of public comment permits embedding of other metafiles
  615. and encapsulated PostScript (EPS) files within the metafile.  The
  616. multiformat public comment is the most exciting of the
  617. comments. (I must be losing touch with reality!) If an EPS file is
  618. embedded in an enhanced metafile and subsequently played
  619. back, GDI will select the best format for the device!
  620. Transparently! When I first heard about the multiformat comment,
  621. I was sure that I was going to be expending a great deal of effort
  622. writing code for rendering EPS files. I was relieved to find
  623. out how wrong I was!
  624.  
  625. Coding Examples
  626.  
  627. The example code in the following sections demonstrates the
  628. creation and playback of an enhanced metafile, illustrating how
  629. some of these functions are used. (These examples are
  630. pared-down versions of examples in the Win32 documentation.)
  631.  
  632. Creating an enhanced metafile
  633.  
  634. Creating an enhanced metafile is similar to creating a Windows
  635. metafile. The code that follows demonstrates the creation of an
  636. enhanced metafile that is stored on a disk. The example uses a
  637. device context for the application window as the reference DC.
  638. The dimensions of the application's client area are used to define
  639. the dimensions of the picture frame. Using the rectangle
  640. dimensions returned by the GetClientRect function, the example
  641. converts the device units to .01-millimeter units and passes the
  642. converted values to the CreateEnhMetaFile function. The
  643. example also embeds a text description of the picture in the
  644. header of the enhanced metafile.
  645.  
  646. // Obtain a handle to a reference DC.
  647.  
  648. hdcRef = GetDC(hWnd);
  649.  
  650. // Determine the picture frame dimensions.
  651. // iWidthMM is the display width in millimeters.
  652. // iHeightMM is the display height in millimeters.
  653. // iWidthPels is the display width in pixels.
  654. // iHeightPels is the display height in pixels.
  655.  
  656. iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE);
  657. iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE);
  658. iWidthPels = GetDeviceCaps(hdcRef, HORZRES);
  659. iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
  660.  
  661.  
  662. // Use iWidthMM, iWidthPels, iHeightMM, and iHeightPels to determine the
  663. // number of .01-millimeter units per pixel in the x and y directions.
  664.  
  665. iMMPerPelX = (iWidthMM * 100)/iWidthPels;
  666. iMMPerPelY = (iHeightMM * 100)/iHeightPels;
  667.  
  668. // Retrieve the coordinates of the client rectangle in pixels.
  669.  
  670. GetClientRect(hWnd, &rect);
  671.  
  672. // Convert client coordinates to .01-mm units.
  673.  
  674. rect.left = rect.left * iMMPerPelX;
  675. rect.top = rect.top * iMMPerPelY;
  676. rect.right = rect.right * iMMPerPelX;
  677.  
  678. rect.bottom = rect.bottom * iMMPerPelY;
  679.  
  680. // Create the metafile DC.
  681.  
  682. hdcMeta = CreateEnhMetaFile(hdcRef,
  683. (LPTSTR)"MYFILE.EMF", &rect,
  684.                             (LPSTR)"ACME
  685. Inc.\0Rocket Skates\0\0");
  686.  
  687. if (!hdcMeta)
  688.     errhandler("CreateEnhMetaFile", hWnd);
  689.  
  690. // Release the reference DC.
  691.  
  692. ReleaseDC(hWnd, hdcRef);
  693.  
  694. Playing an enhanced metafile
  695.  
  696. Playing an enhanced metafile is also similar to the method used
  697. to play Windows metafiles. The following example demonstrates
  698. how to open an enhanced metafile stored on disk, and displays
  699. the associated picture in the client area. The example passes
  700. the handle returned by the GetEnhMetaFile function to the
  701. PlayEnhMetaFile function in order to display the picture.  Before
  702. diving into the code, consider the following advice about
  703. enumeration of the metafile and some tips on how to maximize
  704. the advanced features of the GDI metafile player.
  705.  
  706. Using EnumEnhMetaFile
  707.  
  708. It's common practice to enumerate Windows metafiles, rather
  709. than simply to play them back, to achieve better control over
  710. positioning, scaling, getting access to application-specific
  711. comments, or manipulating the palette records. However, the
  712. improvements to enhanced metafiles reduce the need for
  713. enumeration of the metafile. In Win32, most applications need to
  714. use only PlayEnhMetaFile unless they need to edit the
  715. enhanced metafile by adding, deleting or modifying records, in
  716. which case they'd use EnumEnhMetaFile.
  717.  
  718. Advanced features
  719.  
  720. Three advanced features of enhanced metafiles require action by
  721. the application before playing the metafile to the
  722. destination DC:
  723.  
  724.      Advanced palette functionality
  725.      Advanced clipping capabilities
  726.      World-to-page transform values
  727.  
  728. The advanced palette functionality provides a means of
  729. examining the palette before playing the metafile. This is useful if
  730. the palette is to be merged with another or optimized before the
  731. enhanced metafile is played or enumerated. If the metafile palette
  732. is to be used, it must be retrieved 
  733. (GetEnhMetaFilePaletteEntries), manipulated as desired,
  734. created, selected, and realized in the destination DC.
  735. The advanced clipping capabilities permit the enhanced metafile
  736. to be clipped to a predetermined clipping region. To accomplish
  737. this, the metafile player determines if a clipping region exists in
  738. the destination DC. If a clipping region exists, the region is
  739. applied to the metafile contents as they are played. To use the
  740. clipping feature, create and select any clipping regions into the
  741. destination DC prior to playing the metafile.
  742.  
  743. Finally, the metafile player applies world-to-page transform values
  744. set in the destination DC to the contents of the enhanced
  745. metafile. If any scaling, rotation, reflection, or shearing is desired,
  746. set the world-to-page transform value in the destination DC before
  747. playing the metafile:
  748.  
  749. hemf =
  750. GetEnhMetaFile((LPSTR)"MYFILE.EMF");
  751. // Open the metafile.
  752.  
  753. hDC = GetDC(hWnd);                   // Retrieve a handle to a window DC.
  754.  
  755. GetClientRect(hWnd, &rect);  // Retrieve the client rectangle dimensions.
  756.  
  757. PlayEnhMetaFile(hDC, hemf, &rect);   // Draw the picture.
  758.  
  759. DeleteEnhMetaFile(hemf);             // Release the metafile handle.
  760.  
  761. ReleaseDC(hWnd, hDC);               // Release the window DC.
  762.  
  763. Summary
  764.  
  765. Enhanced metafiles are a giant step beyond the Windows
  766. metafile. An expanded metafile header, a description string, a
  767. palette, device independence, and ease of porting from the
  768. Windows metafile format make enhanced metafiles an offer you
  769. can't refuse! It is expected that the advanced features of
  770. enhanced metafiles will make the use of metafiles more
  771. acceptable than Windows metafiles. With the features listed
  772. below, it is easy to understand why enhanced metafiles will
  773. become an invaluable tool for Win32-based applications:
  774.  
  775. * Full transformation support (removes scaling restrictions
  776. found in Windows metafiles)
  777.  
  778. * Unrestricted clipping capabilities
  779.  
  780. * Improved palette support
  781.  
  782. * Query support (as in GetViewportExtent and GetCurrentPositionEx)
  783.  
  784. * Advanced embedding features (metafiles and EPS files)
  785.  
  786. Probably the most important point to make about enhanced
  787. metafiles is that there is very little reason to enumerate the
  788. metafile. The playback code is smarter and does much of what
  789. developers have had to do themselves by means of enumeration
  790. for years.
  791.  
  792.  
  793.