Programming Windows程式开发设计指南 第18章 Metafile

18. Metafile dedecms.com

Metafile和向量图形的关系,就像点阵图和位元映射图形的关系一样。点阵图通常来自实际的图像,而metafile则大多是通过电脑程式人为建立的。Metafile由一系列与图形函式呼叫相同的二进位记录组成,这些记录一般用於绘制直线、曲线、填入的区域和文字等。

dedecms.com

「画图(paint)」程式建立点阵图,而「绘图(draw)」程式建立metafile。在优秀的绘图程式中,能轻易地「抓住」某个独立的图形物件(例如一条直线)并将它移动到其他位置。这是因为组成图形的每个成员都是以单独的记录储存的。在画图程式中,这是不可能的-您通常都会局限於删除或插入点阵图矩形块。 本文来自织梦

由於metafile以图形绘制命令描述图像,因此可以对图像进行缩放而不会失真。点阵图则不然,如果以二倍大小来显示点阵图,您却无法得到二倍的解析度,而只是在水平和垂直方向上重复点阵图的位元。

dedecms.com

Metafile可以转换为点阵图,但是会丢失一些资讯:组成metafile的图形物件将不再是独立的,而是被合并进大的图像。将点阵图转换为metafile要艰难得多,一般仅限於非常简单的图像,而且它需要大量处理来分析边界和轮廓。而metafile可以包含绘制点阵图的命令。 本文来自织梦

虽然metafile可以作为图片剪辑储存在磁片上,但是它们大多用於程式通过剪贴簿共用图片的情况。由於metafile将图片描述为图像函式呼叫的集合,因而它们既比点阵图占用更少的空间,又比点阵图更与装置无关。 本文来自织梦

Microsoft Windows支援两种metafile格式和支援这些格式的两组函式。我首先讨论从Windows 1.0到目前的32位元Windows版本都支援的metafile函式,然後讨论为32位元Windows系统开发的「增强型metafile」。增强型metafile在原有metafile的基础上有了一些改进,应该尽可能地加以利用。

织梦好,好织梦

旧的metafile格式
  copyright dedecms

Metafile既能够暂时储存在记忆体中,也能够以档案的形式储存在磁片上。对应用程式来说,两者区别不大,尤其是由Windows来处理磁片上储存和载入metafile资料的档案I/O时,更是如此。 本文来自织梦

记忆体metafile的简单利用
 

dedecms.com

如果呼叫CreateMetaFile函式来建立metafile装置内容,Windows就会以早期的格式建立一个metafile,然後您可以使用大部分GDI绘图函式在该metafile装置内容上进行绘图。这些GDI呼叫并不在任何具体的装置上绘图,相反地,它们被储存在metafile中。当关闭metafile装置内容时,会得到metafile的代号。这时就可以在某个具体的装置内容上「播放」这个metafile,这与直接执行metafileGDI函式的效果等同。 copyright dedecms

CreateMetaFile只有一个参数,它可以是NULL或档案名称。如果是NULL,则metafile储存在记忆体中。如果是档案名称(以.WMF作为「Windows Metafile」的副档名),则metafile储存在磁片档案中。

织梦内容管理系统

程式18-1中的METAFILE显示了在WM_CREATE讯息处理期间建立记忆体metafile的方法,并在WM_PAINT讯息处理期间将图像显示100遍。 copyright dedecms

 程式18-1  METAFILE 织梦内容管理系统 
METAFILE.C 
织梦内容管理系统
/*------------------------------------------------------------------------- 

dedecms.com

        METAFILE.C --          Metafile Demonstration Program copyright dedecms 
                                                                     (c) Charles Petzold, 1998 内容来自dedecms 
--------------------------------------------------------------------------*/ 织梦好,好织梦 
  
内容来自dedecms
#include <windows.h> 
织梦内容管理系统
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; copyright dedecms 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
内容来自dedecms
                                                                     PSTR szCmdLine, int iCmdShow) copyright dedecms 
{ 织梦内容管理系统 
        static TCHAR szAppName [] = TEXT ("Metafile") ; 本文来自织梦 
        HWND                                                         hwnd ; 本文来自织梦 
       MSG                                                          msg ; 
织梦好,好织梦
        WNDCLASS                                              wndclass ; 织梦好,好织梦 
  

本文来自织梦

        wndclass.style                                               = CS_HREDRAW | CS_VREDRAW ; copyright dedecms 
        wndclass.lpfnWndProc                          = WndProc ; 
织梦内容管理系统
        wndclass.cbClsExtra                           = 0 ; 本文来自织梦 
        wndclass.cbWndExtra                           = 0 ; dedecms.com 
        wndclass.hInstance                            = hInstance ; 内容来自dedecms 
        wndclass.hIcon                                               = LoadIcon (NULL, IDI_APPLICATION) ; 

dedecms.com

        wndclass.hCursor                                      = LoadCursor (NULL, IDC_ARROW) ; 

本文来自织梦

        wndclass.hbrBackground                = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 

dedecms.com

        wndclass.lpszMenuName                 = NULL ; 
本文来自织梦
        wndclass.lpszClassName                = szAppName ; 

内容来自dedecms

      

本文来自织梦

        if (!RegisterClass (&wndclass)) dedecms.com 
        { 本文来自织梦 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), copyright dedecms 
                                                                     szAppName, MB_ICONERROR) ; 
织梦内容管理系统
                       return 0 ; 本文来自织梦 
       } 
内容来自dedecms
      

织梦好,好织梦

        hwnd = CreateWindow (  szAppName, TEXT ("Metafile Demonstration"), 

织梦好,好织梦

                         WS_OVERLAPPEDWINDOW, 

织梦好,好织梦

                         CW_USEDEFAULT, CW_USEDEFAULT, 
本文来自织梦
                         CW_USEDEFAULT, CW_USEDEFAULT, 
本文来自织梦
                         NULL, NULL, hInstance, NULL) ; 织梦内容管理系统 
      织梦内容管理系统 
        ShowWindow (hwnd, iCmdShow) ; 内容来自dedecms 
        UpdateWindow (hwnd) ; 织梦内容管理系统 
      copyright dedecms 
        while (GetMessage (&msg, NULL, 0, 0)) 织梦内容管理系统 
     { copyright dedecms 
                       TranslateMessage (&msg) ; 织梦内容管理系统 
                       DispatchMessage (&msg) ; 
copyright dedecms
        } copyright dedecms 
        return msg.wParam ; dedecms.com 
} 
织梦好,好织梦
  
织梦好,好织梦
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) 
本文来自织梦
{ 

本文来自织梦

        static HMETAFILE               hmf ; 内容来自dedecms 
        static int                                    cxClient, cyClient ; 本文来自织梦 
        HBRUSH                                                hBrush ; 

dedecms.com

        HDC                                                          hdc, hdcMeta ; 内容来自dedecms 
        int                                                          x, y ; dedecms.com 
        PAINTSTRUCT                                   ps ; 

织梦内容管理系统

      织梦好,好织梦 
        switch (message) 
织梦好,好织梦
        { 织梦好,好织梦 
        case    WM_CREATE: 

dedecms.com

                               hdcMeta=       CreateMetaFile (NULL) ; 
内容来自dedecms
                               hBrush  =       CreateSolidBrush (RGB (0, 0, 255)) ; 本文来自织梦 
                               Rectangle      (hdcMeta, 0, 0, 100, 100) ; 

内容来自dedecms

           织梦好,好织梦 
                               MoveToEx               (hdcMeta,      0,      0,      NULL) ; 
织梦好,好织梦
                               LineTo                 (hdcMeta,      100,    100)    ; 内容来自dedecms 
                               MoveToEx               (hdcMeta,      0,      100,    NULL) ; 内容来自dedecms 
                               LineTo                 (hdcMeta,      100,    0)      ; 织梦内容管理系统 
           内容来自dedecms 
                               SelectObject (hdcMeta, hBrush) ; 

内容来自dedecms

                               Ellipse (hdcMeta, 20, 20, 80, 80) ; 本文来自织梦 
           本文来自织梦 
                               hmf = CloseMetaFile (hdcMeta) ; 

dedecms.com

           copyright dedecms 
                               DeleteObject (hBrush) ; 本文来自织梦 
                               return 0 ; 
本文来自织梦
           

织梦好,好织梦

        case    WM_SIZE: copyright dedecms 
                               cxClient = LOWORD (lParam) ; 织梦内容管理系统 
                               cyClient = HIWORD (lParam) ; 
内容来自dedecms
                               return 0 ; 
copyright dedecms
           本文来自织梦 
        case    WM_PAINT: 

copyright dedecms

                               hdc = BeginPaint (hwnd, &ps) ; 

copyright dedecms

           内容来自dedecms 
                               SetMapMode (hdc, MM_ANISOTROPIC) ; 

本文来自织梦

                               SetWindowExtEx (hdc, 1000, 1000, NULL) ; copyright dedecms 
                               SetViewportExtEx (hdc, cxClient, cyClient, NULL) ; 

织梦内容管理系统

           内容来自dedecms 
                               for (x = 0 ; x < 10 ; x++) dedecms.com 
                               for (y = 0 ; y < 10 ; y++) 内容来自dedecms 
                               { 内容来自dedecms 
                                              SetWindowOrgEx (hdc, -100 * x, -100 * y, NULL) ; 

织梦内容管理系统

                                              PlayMetaFile (hdc, hmf) ; 织梦好,好织梦 
                               } 

织梦好,好织梦

                               EndPaint (hwnd, &ps) ; 
内容来自dedecms
                               return 0 ; 织梦内容管理系统 
                
copyright dedecms
        case    WM_DESTROY: 
内容来自dedecms
                               DeleteMetaFile (hmf) ; 织梦内容管理系统 
                               PostQuitMessage (0) ; 本文来自织梦 
                               return 0 ; 内容来自dedecms 
        } 
织梦内容管理系统
        return DefWindowProc (hwnd, message, wParam, lParam) ; 织梦内容管理系统 
} 
dedecms.com

这个程式展示了在使用记忆体metafile时所涉及的4metafile函式的用法。第一个是CreateMetaFile。在WM_CREATE讯息处理期间用NULL参数呼叫该函式,并传回metafile装置内容的代号。然後,METAFILE利用这个metafileDC来绘制两条直线和一个蓝色椭圆。这些函式呼叫以二进位形式储存在metafile中。CloseMetaFile函式传回metafile的代号。因为以後还要用到该metafile代号,所以把它储存在静态变数。 织梦内容管理系统

metafile包含GDI函式呼叫的二进位表示码,它们是两个MoveToEx呼叫、两个LineTo呼叫、一个SelectObject呼叫(指定蓝色画刷)和一个Ellipse呼叫。座标没有指定任何映射方式或转换,它们只是作为数值资料被储存在metafile中。 本文来自织梦

WM_PAINT讯息处理期间,METAFILE设定一种映射方式并呼叫PlayMetaFile在视窗中绘制物件100次。Metafile中函式呼叫的座标按照目的装置内容的目前变换方式加以解释。在呼叫PlayMetaFile时,事实上是在重复地呼叫最初在WM_CREATE讯息处理期间建立metafile时,在CreateMetaFileCloseMetaFile之间所做的所有呼叫。 织梦好,好织梦

和任何GDI物件一样,metafile物件也应该在程式终止前被删除。这是在WM_DESTROY讯息处理期间用DeleteMetaFile函式处理的工作。 copyright dedecms

METAFILE程式的结果如图18-1所示。 copyright dedecms


 

本文来自织梦

织梦好,好织梦

 

本文来自织梦

18-1 METAFILE程式执行结果显示 内容来自dedecms

 

metafile储存在磁碟上
 

dedecms.com

在上面的例子中,CreateMetaFileNULL参数表示要建立储存在记忆体中的metafile。我们也可以建立作为档案储存在磁碟上的metafile,这种方法对於大的metafile比较合适,因为可以节省记忆体空间。而另一方面,每次使用磁片上的metafile时,就需要存取磁片。

copyright dedecms

要把METAFILE转换为使用metafile磁片档案的程式,必须把CreateMetaFileNULL参数替换为档案名称。在WM_CREATE处理结束时,可以用metafile代号来呼叫DeleteMetaFile,这样代号被删除,但是磁片档案仍然被储存著。 本文来自织梦

在处理WM_PAINT讯息处理期间,可以通过呼叫GetMetaFile来取得此磁碟档案的metafile代号: 内容来自dedecms

hmf = GetMetaFile (szFileName) ; 
copyright dedecms

现在就可以像前面那样显示这个metafile。在WM_PAINT讯息处理结束时,可以用下面的叙述删除该metafile代号: 本文来自织梦

DeleteMetaFile (hmf) ; 

织梦好,好织梦

在开始处理WM_DESTROY讯息时,不必删除metafile,因为它已经在WM_CREATE讯息和每个WM_PAINT讯息结束时被删除了,但是仍然需要删除磁碟档案:

织梦好,好织梦

DeleteFile (szFileName) ; 
织梦内容管理系统

当然,除非您想储存该档案。 dedecms.com

正如在第十章讨论过的,metafile也可以作为使用者自订资源。您可以简单地把它当作资料块载入。如果您有一块包含metafile内容的资料,那么您可以使用

本文来自织梦

hmf = SetMetaFileBitsEx (iSize, pData) ; 

copyright dedecms

来建立metafileSetMetaFileBitsEx有一个对应的函式-GetMetaFileBitsEx,此函式将metafile的内容复制到记忆体块中。

内容来自dedecms

老式metafile与剪贴簿
  dedecms.com

老式metafile有个讨厌的缺陷。如果您具有老式metafile的代号,那么,当您在显示metafile时如何确定它的大小呢?除非您深入分析metafile的内部结构,否则无法得知。 dedecms.com

此外,当程式从剪贴簿取得老式metafile时,如果metafile被定义为在MM_ISOTROPICMM_ANISOTROPIC映射方式下显示,则此程式在使用该metafile时具有最大程度的灵活性。程式收到该metafile後,就可以在显示它之前简单地通过设定视埠的范围来缩放图像。然而,如果metafile内的映射方式被设定为MM_ISOTROPICMM_ANISOTROPIC,则收到该metafile的程式将无法继续执行。程式仅能在显示metafile之前或之後进行GDI呼叫,不允许在显示metafile当中进行GDI呼叫。 本文来自织梦

为了解决这些问题,老式metafile代号不直接放入剪贴簿供其他程式取得,而是作为「metafile图片」(METAFILEPICT结构型态)的一部分。此结构使得从剪贴簿上取得metafile图片的程式能够在显示metafile之前设定映射方式和视埠范围。 织梦内容管理系统

METAFILEPICT结构的长度为16个位元组,定义如下: 内容来自dedecms

typedef struct tagMETAFILEPICT 织梦内容管理系统 
{ 内容来自dedecms 
        LONG mm ;                                     // mapping mode dedecms.com 
        LONG xExt ;                                   // width of the metafile image 织梦好,好织梦 
        LONG yExt ;                                   // height of the metafile image 

织梦内容管理系统

        LONG hMF ;                                    // handle to the metafile 

内容来自dedecms

} 
dedecms.com
METAFILEPICT ; 织梦好,好织梦 

对於MM_ISOTROPICMM_ANISOTROPIC以外的所有映射方式,图像大小用xExtyExt值表示,其单位是由mm给出的映射方式的单位。利用这些资讯,从剪贴簿复制metafile图片结构的程式就能够确定在显示metafile时所需的显示空间。建立该metafile的程式可以将这些值设定为输入metafileGDI绘制函式中所使用的最大的x座标和y座标值。

dedecms.com

MM_ISOTROPICMM_ANISOTROPIC映射方式下,xExtyExt栏位有不同的功能。我们在第五章中曾介绍过一个程式,该程式为了在GDI函式中使用与图像实际尺寸无关的逻辑单位而采用MM_ISOTROPICMM_ANISOTROPIC映射方式。当程式只想保持纵横比而可以忽略图形显示平面的大小时,采用MM_ISOTROPIC模式;反之,当不需要考虑纵横比时采用MM_ANISOTROPIC模式。您也许还记得,第五章中在程式将映射方式设定为MM_ISOTROPICMM_ANISOTROPIC後,通常会呼叫SetWindowExtExSetViewportExtExSetWindowExtEx呼叫使用逻辑单位来指定程式在绘制时使用的单位,而SetViewportExtEx呼叫使用的装置单位大小则取决於图形显示平面(例如,视窗显示区域的大小)。 内容来自dedecms

如果程式为剪贴簿建立了MM_ISOTROPICMM_ANISOTROPIC方式的metafile,则该metafile本身不应包含对SetViewportExtEx的呼叫,因为该呼叫中的装置单位应该依据建立metafile的程式的显示平面,而不是依据从剪贴簿读取并显示metafile的程式的显示平面。从剪贴簿取得metafile的程式可以利用xExtyExt值来设定合适的视埠范围以便显示metafile。但是当映射方式是MM_ISOTROPICMM_ANISOTROPIC时,metafile本身包含设定视窗范围的呼叫。Metafile内的GDI绘图函式的座标依据这些视窗的范围。

本文来自织梦

建立metafilemetafile图片遵循以下规则:

内容来自dedecms

  • 设定METAFILEPICT结构的mm栏位来指定映射方式。
     
  • 对於MM_ISOTROPICMM_ANISOTROPIC以外的映射方式,xExtyExt栏位设定为图像的宽和高,单位与mm栏位相对应。对於在MM_ISOTROPICMM_ANISOTROPIC方式下显示的metafile,工作要复杂一些。在MM_ANISOTROPIC模式下,当程式既不对图片大小跟纵横比给出任何建议资讯时,xExtyExt的值均为零。在这两种模式下,如果xExtyExt的值为正数,它们就是以0.01mm单位(MM_HIMETRIC单位)表示该图像的宽度和高度。在MM_ISOTROPIC方式下,如果xExtyExt为负值,它们就指出了图像的纵横比而不是大小。
     
  • MM_ISOTROPICMM_ANISOTROPIC映射方式下,metafile本身含有对SetWindowExtEx的呼叫,也可能有对SetWindowOrgEx的呼叫。亦即,建立metafile的程式在metafile装置内容中呼叫这些函式。Metafile一般不会包含对SetMapModeSetViewportExtExSetViewportOrgEx的呼叫。

    dedecms.com


     
  • metafile应该是记忆体metafile,而不是metafile档案。
     

这里有一段范例程式码,它建立metafile并将其复制到剪贴簿。如果metafile使用MM_ISOTROPICMM_ANISOTROPIC映射方式,则该metafile的第一个呼叫应该设定视窗范围(在其他模式中,视窗的大小是固定的)。无论在哪种模式下,视窗的位置应如下设定: 本文来自织梦

hdcMeta = CreateMetaFile (NULL) ; 

内容来自dedecms

SetWindowExtEx (hdcMeta, ...) ; 

内容来自dedecms

SetWindowOrgEx (hdcMeta, ...) ; 织梦好,好织梦 

Metafile绘图函式中的座标决定於这些视窗范围和视窗原点。当程式使用GDI呼叫在metafile装置内容中绘制完成後,关闭metafile以得到metafile代号: 织梦内容管理系统

hmf = CloseMetaFile (hdcMeta) ; 内容来自dedecms 

该程式还需要定义指向METAFILEPICT型态结构的指标,并为此结构配置一块整体记忆体: copyright dedecms

GLOBALHANDLE           hGlobal ; 

织梦好,好织梦

LPMETAFILEPICT         pMFP ; dedecms.com 
其他行程式 dedecms.com 
hGlobal= GlobalAlloc (GHND | GMEM_SHARE, sizeof (METAFILEPICT)) ; 
本文来自织梦
pMFP = (LPMETAFILEPICT) GlobalLock (hGlobal) ; 
内容来自dedecms

接著,程式设定该结构的4个栏位: copyright dedecms

pMFP->mm       = MM_... ; 

dedecms.com

pMFP->xExt     = ...  ; 本文来自织梦 
pMFP->yExt     = ...  ; 

织梦内容管理系统

pMFP->hMF      = hmf  ; 织梦内容管理系统 
  

织梦内容管理系统

GlobalUnlock (hGlobal) ; dedecms.com 

然後,程式将包含有metafile图片的整体记忆体块传送给剪贴簿:

织梦内容管理系统

OpenClipboard (hwnd) ; dedecms.com 
EmptyClipboard () ; 
本文来自织梦
SetClipboardData (CF_METAFILEPICT, hGlobal) ; 织梦好,好织梦 
CloseClipboard () ; 
织梦好,好织梦

完成这些呼叫後,hGlobal代号(包含metafile图片结构的记忆体块)和hmf代号(metafile本身)就对建立它们的程式失效了。 copyright dedecms

现在来看一看难的部分。当程式从剪贴簿取得metafile并显示它时,必须完成下列步骤: copyright dedecms

  1. 程式利用metafile图片结构的mm栏位设定映射方式。
  2. 对於MM_ISOTROPICMM_ANISOTROPIC以外的映射方式,程式用xExtyExt值设定剪贴矩形或简单地设定图像大小。而在MM_ISOTROPICMM_ANISOTROPIC映射方式,程式使用xExtyExt来设定视埠范围。
  3. 然後,程式显示metafile

下面程式码,首先打开剪贴簿,得到metafile图片结构代号并将其锁定: dedecms.com

OpenClipboard (hwnd) ; dedecms.com 
hGlobal = GetClipboardData (CF_METAFILEPICT) ; 

织梦内容管理系统

pMFP = (LPMETAFILEPICT) GlobalLock (hGlobal) ; 

内容来自dedecms

现在可以储存目前装置内容的属性,并将映射方式设定为结构中的mm值:

内容来自dedecms

SaveDC (hdc) ; 织梦好,好织梦 
SetMappingMode (pMFP->mm) ; 

本文来自织梦

如果映射方式不是MM_ISOTROPICMM_ANISOTROPIC,则可以用xExtyExt的值设定剪贴矩形。由於这两个值是逻辑单位,必须用LPtoDP将其转换为用於剪贴矩形的装置单位的座标。也可以简单地储存这些值以掌握图像的大小。

织梦好,好织梦

对於MM_ISOTROPICMM_ANISOTROPIC映射方式,xExtyExt用来设定视埠范围。下面有一个用来完成此项任务的函式,如果xExtyExt没有建议的大小,则该函式假定cxClientcyClient分别表示metafile显示区域的图素高度和宽度。 内容来自dedecms

void PrepareMetaFile (HDC hdc, LPMETAFILEPICT pmfp, 

本文来自织梦

                               int cxClient, int cyClient) 

织梦好,好织梦

{ 内容来自dedecms 
        int xScale, yScale, iScale ; 
本文来自织梦
        SetMapMode (hdc, pmfp->mm) ; 
本文来自织梦
        if (pmfp->mm == MM_ISOTROPIC || pmfp->mm == MM_ANISOTROPIC) 

织梦内容管理系统

        { 
dedecms.com
                               if (pmfp->xExt == 0) 本文来自织梦 
                                      SetViewportExtEx (hdc, cxClient, cyClient, NULL) ; 
本文来自织梦
                               else if (pmfp->xExt > 0) 织梦好,好织梦 
                                      SetViewportExtEx (hdc, 
织梦好,好织梦
                                      pmfp->xExt *   GetDeviceCaps (hdc, HORZRES) / 

dedecms.com

                                GetDeviceCaps (hdc, HORZSIZE) / 100), 织梦内容管理系统 
                                      pmfp->yExt *   GetDeviceCaps (hdc, VERTRES) / 本文来自织梦 
                                GetDeviceCaps (hdc, VERTSIZE) / 100), NULL) ; 
织梦好,好织梦
                                           else if (pmfp->xExt < 0) 内容来自dedecms 
                                      { 织梦好,好织梦 
                               xScale = 100 *cxClient * GetDeviceCaps (hdc, HORZSIZE) / 
内容来自dedecms
                        GetDeviceCaps (hdc, HORZRES) / -pmfp->xExt ; 

内容来自dedecms

                               lScale = 100 *cyClient * GetDeviceCaps (hdc, VERTSIZE) / dedecms.com 
                        GetDeviceCaps (hdc, VERTRES) / -pmfp->yExt ; 

织梦内容管理系统

                               iScale = min (xScale, yScale) ; copyright dedecms 
  dedecms.com 
   SetViewportExtEx (hdc, -pmfp->xExt * iScale * GetDeviceCaps (hdc, HORZRES) / 织梦好,好织梦 
                     GetDeviceCaps (hdc, HORZSIZE) / 100, -pmfp->yExt * iScale  

本文来自织梦

* GetDeviceCaps (hdc, VERTRES) / GetDeviceCaps (hdc, VERTSIZE) / 100, NULL) ; dedecms.com 
                       } 

本文来自织梦

               } dedecms.com 
} 

copyright dedecms

上面的程式码假设xExtyExt同时都为零、大於零或小於零,这三种状态之一。如果范围为零,表示没有建议大小或纵横比,视埠范围设定为显示metafile的区域。如果大於零,则xExtyExt的值代表图像的建议大小,单位是0.01mmGetDeviceCaps函式用来确定每0.01mm中包含的图素数,并且该值与metafile图片结构的范围值相乘。如果小於零,则xExtyExt的值表示建议的纵横比而不是建议的大小。iScale的值首先根据对应cxClientcyClient的毫米表示的纵横比计算出来,该缩放因数用於设定图素单位的视埠范围。 织梦好,好织梦

完成了上述工作後,可以设定视埠原点,显示metafile,并恢复装置内容: dedecms.com

PlayMetaFile (pMFP->hMF) ; 本文来自织梦 
RestoreDC (hdc, -1) ; 
dedecms.com

然後,对记忆体块解锁并关闭剪贴簿:

织梦内容管理系统

GlobalUnlock (hGlobal) ; dedecms.com 
CloseClipboard () ; 织梦好,好织梦 

如果程式使用增强型metafile就可以省去这项工作。当某个应用程式将这些格式放入剪贴簿而另一个程式却要求从剪贴簿中获得其他格式时,Windows剪贴簿会自动在老式metafile和增强型metafile之间进行格式转换。

dedecms.com

增强型metafile
  copyright dedecms

「增强型metafile」格式是在32位元Windows版本中发表的。它包含一组新的函式呼叫、一对新的资料结构、新的剪贴簿格式和新的档案副档名.EMF

内容来自dedecms

这种新的metafile格式最重要的改进是加入可通过函式呼叫取得的更丰富的表头资讯,这种表头资讯可用来帮助应用程式显示metafile图像。

内容来自dedecms

有些增强型metafile函式使您能够在增强型metafile(EMF)格式和老式metafile格式(也称作Windows metafile(WMF)格式)之间来回转换。当然,这种转换很可能遇到麻烦,因为老式metafile格式并不支援某些,例如GDI绘图路径等,新的32位元图形功能。 内容来自dedecms

基本程序
  内容来自dedecms

程式18-2所示的EMF1建立并显示增强型metafilecopyright dedecms

 程式18-2  EMF1 织梦内容管理系统 
EMF1.C 织梦内容管理系统 
/*---------------------------------------------------------------------------- 本文来自织梦 
        EMF1.C --      Enhanced Metafile Demo #1 copyright dedecms 
                                              (c) Charles Petzold, 1998 
本文来自织梦
-----------------------------------------------------------------------------*/ 
织梦内容管理系统
  
本文来自织梦
#include <windows.h> 
dedecms.com
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 织梦好,好织梦 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 

dedecms.com

                                                                     LPSTR lpszCmdLine, int nCmdShow) 

dedecms.com

{ copyright dedecms 
        static TCHAR   szAppName[] = TEXT ("EMF1") ; 

内容来自dedecms

        HWND                                  hwnd ; 本文来自织梦 
        MSG                                   msg ; 
织梦内容管理系统
        WNDCLASS                       wndclass ; 织梦好,好织梦 
      内容来自dedecms 
        wndclass.style                                               = CS_HREDRAW | CS_VREDRAW ; 

内容来自dedecms

        wndclass.lpfnWndProc                          = WndProc ; 内容来自dedecms 
        wndclass.cbClsExtra                           = 0 ; 
内容来自dedecms
        wndclass.cbWndExtra                           = 0 ; 本文来自织梦 
        wndclass.hInstance                            = hInstance ; 内容来自dedecms 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 织梦好,好织梦 
        wndclass.hCursor                      = LoadCursor (NULL, IDC_ARROW) ; dedecms.com 
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 织梦内容管理系统 
        wndclass.lpszMenuName                 = NULL ; 

copyright dedecms

        wndclass.lpszClassName                = szAppName ; dedecms.com 
  织梦内容管理系统 
        if (!RegisterClass (&wndclass)) 织梦内容管理系统 
        { 
织梦内容管理系统
                               MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 织梦好,好织梦 
                                                                            szAppName, MB_ICONERROR) ; 

copyright dedecms

                               return 0 ; dedecms.com 
     } 本文来自织梦 
      
织梦好,好织梦
        hwnd = CreateWindow (  szAppName, TEXT ("Enhanced Metafile Demo #1"), 内容来自dedecms 
                                      WS_OVERLAPPEDWINDOW, 内容来自dedecms 
                                      CW_USEDEFAULT, CW_USEDEFAULT, 

内容来自dedecms

                                      CW_USEDEFAULT, CW_USEDEFAULT, 织梦内容管理系统 
                                      NULL, NULL, hInstance, NULL) ; dedecms.com 
      

内容来自dedecms

        ShowWindow (hwnd, nCmdShow) ; 
织梦好,好织梦
        UpdateWindow (hwnd) ; 
织梦内容管理系统
      
dedecms.com
        while (GetMessage (&msg, NULL, 0, 0)) 内容来自dedecms 
        { 

织梦好,好织梦

                               TranslateMessage (&msg) ; 织梦内容管理系统 
                               DispatchMessage (&msg) ; 

织梦好,好织梦

     } dedecms.com 
        return msg.wParam ; dedecms.com 
} 织梦好,好织梦 
  本文来自织梦 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) 本文来自织梦 
{ 
本文来自织梦
       static HENHMETAFILE    hemf ; 织梦好,好织梦 
        HDC                                                                  hdc, hdcEMF ; 内容来自dedecms 
        PAINTSTRUCT                                           ps ; 
copyright dedecms
        RECT                                                                 rect ; 

内容来自dedecms

      
内容来自dedecms
        switch (message) 

copyright dedecms

     { 

本文来自织梦

        case    WM_CREATE: 

织梦好,好织梦

                               hdcEMF = CreateEnhMetaFile (NULL, NULL, NULL, NULL) ; 
本文来自织梦
  

copyright dedecms

                               Rectangle      (hdcEMF, 100, 100, 200, 200) ; 

内容来自dedecms

           织梦好,好织梦 
                               MoveToEx               (hdcEMF, 100, 100, NULL) ; 内容来自dedecms 
                               LineTo                 (hdcEMF, 200, 200) ; dedecms.com 
           
copyright dedecms
                               MoveToEx               (hdcEMF, 200, 100, NULL) ; 

本文来自织梦

                               LineTo                 (hdcEMF, 100, 200) ; 

内容来自dedecms

  

dedecms.com

                               hemf = CloseEnhMetaFile (hdcEMF) ; 
本文来自织梦
                               return 0 ; 
本文来自织梦
           
dedecms.com
        case    WM_PAINT: copyright dedecms 
                               hdc = BeginPaint (hwnd, &ps) ; 

dedecms.com

           内容来自dedecms 
                               GetClientRect (hwnd, &rect) ; 

本文来自织梦

           dedecms.com 
                               rect.left              =                      rect.right             / 4 ; 

copyright dedecms

                               rect.right             = 3 *   rect.right             / 4 ; 
织梦好,好织梦
                               rect.top               =                      rect.bottom            / 4 ; 本文来自织梦 
                               rect.bottom            = 3 *   rect.bottom            / 4 ; 

本文来自织梦

           
织梦内容管理系统
                               PlayEnhMetaFile (hdc, hemf, &rect) ; 内容来自dedecms 
           织梦好,好织梦 
                               EndPaint (hwnd, &ps) ; 

本文来自织梦

                               return 0 ; 
织梦内容管理系统
           本文来自织梦 
        case    WM_DESTROY: dedecms.com 
                               DeleteEnhMetaFile (hemf) ; 内容来自dedecms 
           copyright dedecms 
                               PostQuitMessage (0) ; 
织梦好,好织梦
                               return 0 ; 
内容来自dedecms
     } 织梦好,好织梦 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 

dedecms.com

} 织梦好,好织梦 

EMF1的视窗讯息处理程式处理WM_CREATE讯息处理期间,程式首先通过呼叫CreateEnhMetaFile来建立增强型metafile。该函式有4个参数,但可以把它们都设为NULL。稍候我将说明这4个参数在非NULL情况下的使用方法。 dedecms.com

CreateMetaFile一样,CreateEnhMetaFile函式传回特定的装置内容代号。该程式利用这个代号绘制一个矩形和该矩形的两条对角线。这些函式呼叫及其参数被转换为二进位元的形式并储存在metafile中。

copyright dedecms

最後通过对CloseEnhMetaFile函式的呼叫结束了增强型metafile的建立并传回指向它的代号。该档案代号储存在HENHMETAFILE型态的静态变数中。 织梦内容管理系统

WM_PAINT讯息处理期间,EMF1RECT结构取得程式的显示区域视窗大小。通过调整结构中的4个栏位,使该矩形的长和宽为显示区域视窗长和宽的一半并位於视窗的中央。然後EMF1呼叫PlayEnhMetaFile,该函式的第一个参数是视窗的装置内容代号,第二个参数是该增强型metafile的代号,第三个参数是指向RECT结构的指标。

织梦内容管理系统

metafile的建立程序中,GDI得出整个metafile图像的尺寸。在本例中,图像的长和宽均为100个单位。在metafile的显示程序中,GDI将图像拉伸以适应PlayEnhMetaFile函式指定的矩形大小。EMF1Windows下执行的三个执行实体如图18-2所示。 内容来自dedecms


 

织梦好,好织梦

copyright dedecms

  织梦好,好织梦

18-2 EMF1得萤幕显示

织梦好,好织梦

 

最後,在WM_DESTROY讯息处理期间,EMF1呼叫DeleteEnhMetaFile删除metafile织梦内容管理系统

让我们总结一下从EMF1程式学到的一些东西。 dedecms.com

首先,该程式在建立增强型metafile时,画矩形和直线的函式所使用的座标并不是实际意义上的座标。您可以将它们同时加倍或都减去某个常数,而其结果不会改变。这些座标只是在定义图像时说明彼此间的对应关系。 本文来自织梦

其次,为了适於在传递给PlayEnhMetaFile函式的矩形中显示,图像大小会被缩放。因此,如图18-2所示,图像可能会变形。尽管metafile座标指出该图像是正方形的,但一般情况下我们却得不到这样的图像。而在某些时候,这又正是我们想要得到的图像。例如,将图像嵌入一段文书处理格式的文字中时,可能会要求使用者为图像指定矩形,并且确保整个图像恰好位於矩形中而不浪费空间。这样,使用者可通过适当调整矩形的大小来得到正确的纵横比。

织梦好,好织梦

然而有时候,您也许希望保留图像最初的纵横比,因为这一点对於表现视觉资讯尤为重要。例如,警察的嫌疑犯草图既不能比原型胖也不能比原型瘦。或者您希望保留原来图像的度量尺寸,图像必须是两英寸高,否则就不能正常显示。在这种情况下,保留图像的原来尺寸就非常重要了。

dedecms.com

同时也要注意metafile中画出的那些对角线似乎没有与矩形顶点相交。这是由於Windowsmetafile中储存矩形座标的方式造成的。稍後,会说明解决这个问题的方法。 内容来自dedecms

揭开内幕
 

内容来自dedecms

如果看一看metafile的内容会对metafile工作的方式有一个更好的理解。如果您有一个metafile档案,这将很容易做到,程式18-3中的EMF2程式建立了一个metafile

织梦内容管理系统

 程式18-3  EMF2 

织梦内容管理系统

EMF2.C 
织梦好,好织梦
/*----------------------------------------------------------------------------- 

内容来自dedecms

        EMF2.C --      Enhanced Metafile Demo #2 

copyright dedecms

                                              (c) Charles Petzold, 1998 
内容来自dedecms
-----------------------------------------------------------------------------*/ 织梦内容管理系统 
  

copyright dedecms

#include <windows.h> 本文来自织梦 
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 织梦内容管理系统 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
内容来自dedecms
                                                                     LPSTR lpszCmdLine, int nCmdShow) copyright dedecms 
{ 

织梦好,好织梦

        static TCHAR           szAppName[] = TEXT ("EMF2") ; 

dedecms.com

        HWND                                          hwnd ; 
本文来自织梦
        MSG                                           msg ; 
织梦好,好织梦
        WNDCLASS                              wndclass ; dedecms.com 
        wndclass.style                                        = CS_HREDRAW | CS_VREDRAW ; 
dedecms.com
        wndclass.lpfnWndProc                          = WndProc ; copyright dedecms 
        wndclass.cbClsExtra                           = 0 ; 

织梦好,好织梦

        wndclass.cbWndExtra                           = 0 ; copyright dedecms 
        wndclass.hInstance                            = hInstance ; 内容来自dedecms 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 
织梦内容管理系统
        wndclass.hCursor                      = LoadCursor (NULL, IDC_ARROW) ; 
dedecms.com
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 
织梦内容管理系统
        wndclass.lpszMenuName                 = NULL ; 

dedecms.com

        wndclass.lpszClassName                = szAppName ; 内容来自dedecms 
      
本文来自织梦
        if (!RegisterClass (&wndclass)) 织梦内容管理系统 
        { 内容来自dedecms 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 
织梦好,好织梦
                                                                     szAppName, MB_ICONERROR) ; 内容来自dedecms 
                       return 0 ; 
织梦好,好织梦
        } copyright dedecms 
      织梦好,好织梦 
        hwnd = CreateWindow (szAppName, TEXT ("Enhanced Metafile Demo #2"), dedecms.com 
                               WS_OVERLAPPEDWINDOW, dedecms.com 
                               CW_USEDEFAULT, CW_USEDEFAULT, 
本文来自织梦
                               CW_USEDEFAULT, CW_USEDEFAULT, 织梦内容管理系统 
                               NULL, NULL, hInstance, NULL) ; 本文来自织梦 
      

copyright dedecms

        ShowWindow (hwnd, nCmdShow) ; 内容来自dedecms 
        UpdateWindow (hwnd) ; 织梦内容管理系统 
      
dedecms.com
        while (GetMessage (&msg, NULL, 0, 0)) 

织梦好,好织梦

        { 织梦好,好织梦 
                       TranslateMessage (&msg) ; 
copyright dedecms
                       DispatchMessage (&msg) ; dedecms.com 
        } 内容来自dedecms 
        return msg.wParam ; copyright dedecms 
} 织梦内容管理系统 
  织梦内容管理系统 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
copyright dedecms
{ 
copyright dedecms
        HDC                                   hdc, hdcEMF ; dedecms.com 
        HENHMETAFILE   hemf ; 
dedecms.com
        PAINTSTRUCT            ps ; dedecms.com 
        RECT                                  rect ; copyright dedecms 
      织梦好,好织梦 
        switch (message) 
内容来自dedecms
        { dedecms.com 
        case    WM_CREATE: 

织梦好,好织梦

               hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf2.emf"), NULL, 
内容来自dedecms
            TEXT ("EMF2\0EMF Demo #2\0")) ; 
内容来自dedecms
  

织梦好,好织梦

                               if (!hdcEMF) 

织梦内容管理系统

                               return 0 ; dedecms.com 
  
内容来自dedecms
                               Rectangle      (hdcEMF, 100, 100, 200, 200) ; 
内容来自dedecms
  

copyright dedecms

                               MoveToEx               (hdcEMF, 100, 100, NULL) ; 
本文来自织梦
                               LineTo                 (hdcEMF, 200, 200) ; 

织梦好,好织梦

           
copyright dedecms
                               MoveToEx               (hdcEMF, 200, 100, NULL) ; 本文来自织梦 
                               LineTo                 (hdcEMF, 100, 200) ; 本文来自织梦 
           dedecms.com 
                               hemf = CloseEnhMetaFile (hdcEMF) ; 
内容来自dedecms
           
织梦好,好织梦
                               DeleteEnhMetaFile (hemf) ; 织梦好,好织梦 
                               return 0 ; 织梦好,好织梦 
           
copyright dedecms
        case    WM_PAINT: 本文来自织梦 
                               hdc = BeginPaint (hwnd, &ps) ; 
织梦内容管理系统
           copyright dedecms 
                               GetClientRect (hwnd, &rect) ; 织梦内容管理系统 
           本文来自织梦 
                               rect.left              =           rect.right      / 4 ; 本文来自织梦 
                               rect.right     = 3 *   rect.right             / 4 ; 

织梦内容管理系统

                               rect.top       =       rect.bottom            / 4 ; 织梦内容管理系统 
                               rect.bottom    = 3 *   rect.bottom            / 4 ; dedecms.com 
           dedecms.com 
                               if (hemf = GetEnhMetaFile (TEXT ("emf2.emf"))) 织梦内容管理系统 
                               { 

copyright dedecms

                                      PlayEnhMetaFile (hdc, hemf, &rect) ; 
dedecms.com
                                      DeleteEnhMetaFile (hemf) ; 
dedecms.com
                               } 
本文来自织梦
                               EndPaint (hwnd, &ps) ; 
本文来自织梦
                               return 0 ; dedecms.com 
           织梦内容管理系统 
        case    WM_DESTROY: 织梦好,好织梦 
                               PostQuitMessage (0) ; 本文来自织梦 
                               return 0 ; 织梦好,好织梦 
        } 内容来自dedecms 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 内容来自dedecms 
} copyright dedecms 

EMF1程式中,CreateEnhMetaFile函式的所有参数均被设定为NULL。在EMF2中,第一个参数仍旧设定为NULL,该参数还可以是装置内容代号。GDI使用该参数在metafile表头中插入度量资讯,很快我会讨论它。如果该参数为NULL,则GDI认为度量资讯是由视讯装置内容决定的。 dedecms.com

CreateEnhMetaFile函式的第二个参数是档案名称。如果该参数为NULL(在EMF1中为NULL,但在EMF2中不为NULL),则该函式建立记忆体metafileEMF2建立名为EMF2.EMFmetafile档案。 内容来自dedecms

函式的第三个参数是RECT结构的位址,它指出了以0.01mm为单位的metafile的总大小。这是metafile表头资料中极其重要的资讯(这是早期的Windows metafile格式的缺陷之一)。如果该参数为NULLGDI会计算出尺寸。我比较喜欢让作业系统替我做这些事,所以将该参数设定为NULL。当应用程式对性能要求比较严格时,就需要使用该参数以避免让GDI处理太多东西。

织梦内容管理系统

最後的参数是描述该metafile的字串。该字串分为两部分:第一部分是以NULL字元结尾的应用程式名称(不一定是程式的档案名称),第二部分是描述视觉图像内容的说明,以两个NULL字元结尾。例如用C中的符号「\0」作为NULL字元,则该描述字串可以是「LoonyCad V6.4\0Flying Frogs\0\0」。由於在C中通常会在使用的字串末尾放入一个NULL字元,所以如EMF2所示,在末尾仅需一个「\0」。 内容来自dedecms

建立完metafile後,与EMF1一样,EMF2也透过利用由CreateEnhMetaFile函式传回的装置内容代号进行一些GDI函式呼叫。然後程式呼叫CloseEnhMetaFile删除装置内容代号并取得完成的metafile的代号。

内容来自dedecms

然後,在WM_CREATE讯息还没处理完毕时,EMF2做了一些EMF1没有做的事情:在获得metafile代号之後,程式呼叫DeleteEnhMetaFile。该操作释放了用於储存metafile的所有记忆体资源。然而,metafile档案仍然保留在磁碟机中(如果愿意,您可以使用如DeleteFile的档案删除函式来删除该档案)。注意metafile代号并不像EMF1中那样储存在静态变数中,这意味著在讯息之间不需要储存它。

织梦好,好织梦

现在,为了使用该metafileEMF2需要存取磁片档案。这是在WM_PAINT讯息处理期间透过呼叫GetEnhMetaFile进行的。Metafile的档案名称是该函式的唯一参数,该函式传回metafile代号。和EMF1一样,EMF2将这个档案代号传递给PlayEnhMetaFile函式。该metafile图像在PlayEnhMetaFile函式的最後一个参数所指定的矩形中显示。与EMF1不同的是,EMF2WM_PAINT讯息结束之前就删除该metafile。此後每次处理WM_PAINT讯息时,EMF2都会再次读取metafile,显示并删除它。 内容来自dedecms

要记住,对metafile的删除操作仅是释放了用以储存metafile的记忆体资源而已,磁片metafile甚至在程式执行结束後还保留在磁片上。

dedecms.com

由於EMF2留下了metafile档案,您可以看一看它的内容。图18-3显示了该程式建立的EMF2.EMF档案的一堆十六进位代码。

dedecms.com

0000    01 00 00 00 88 00 00 00 64 00 00 00 64 00 00 00           ........d...d... 
copyright dedecms
0010    C8 00 00 00 C8 00 00 00 35 0C 00 00 35 0C 00 00       ........5...5... 内容来自dedecms 
0020    6A 18 00 00 6A 18 00 00 20 45 4D 46 00 00 01 00       j...j...EMF.... 

dedecms.com

0030    F4 00 00 00 07 00 00 00 01 00 00 00 12 00 00 00       ................ 本文来自织梦 
0040    64 00 00 00 00 00 00 00 00 04 00 00 00 03 00 00       d............... 织梦内容管理系统 
0050    40 01 00 00 F0 00 00 00 00 00 00 00 00 00 00 00       @............... 
dedecms.com
0060    00 00 00 00 45 00 4D 00 46 00 32 00 00 00 45 00       ....E.M.F.2...E. 本文来自织梦 
0070    4D 00 46 00 20 00 44 00 65 00 6D 00 6F 00 20 00       M.F..D.e.m.o.. 

dedecms.com

0080    23 00 32 00 00 00 00 00 2B 00 00 00 18 00 00 00       #.2.....+....... dedecms.com 
0090    63 00 00 00 63 00 00 00 C6 00 00 00 C6 00 00 00       c...c........... 
dedecms.com
00A0    1B 00 00 00 10 00 00 00 64 00 00 00 64 00 00 00       ........d...d... 
织梦内容管理系统
00B0    36 00 00 00 10 00 00 00 C8 00 00 00 C8 00 00 00       6............... 织梦好,好织梦 
00C0    1B 00 00 00 10 00 00 00 C8 00 00 00 64 00 00 00       ............d... copyright dedecms 
00D0    36 00 00 00 10 00 00 00 64 00 00 00 C8 00 00 00       6.......d....... 

内容来自dedecms

00E0    0E 00 00 00 14 00 00 00 00 00 00 00 10 00 00 00       ................ 
copyright dedecms
00F0    14 00 00 00                                                                 .... 
dedecms.com

 

本文来自织梦

18-3 EMF2.EMF的十六进位代码

dedecms.com

 

18-3所示的metafileEMF2Microsoft Windows NT 4下,视讯显示器的解析度为1024×768时建立的。同一程式在Windows 98下建立的metafile会比前者少12个位元组,这一点将在稍後讨论。同样地,视讯显示器的解析度也影响metafile表头的某些资讯。

本文来自织梦

增强型metafile格式使我们对metafile的工作方式有更深刻的理解。增强型metafile由可变长度的记录组成,这些记录的一般格式由ENHMETARECORD结构说明,它在WINGDI.H表头档案中定义如下: dedecms.com

typedef struct tagENHMETARECORD 本文来自织梦 
{ 

织梦好,好织梦

        DWORD iType ;                                 // record type 

copyright dedecms

        DWORD nSize ;                                 // record size dedecms.com 
        DWORD dParm [1] ;                      // parameters 
织梦内容管理系统
} 
内容来自dedecms
ENHMETARECORD ; 织梦好,好织梦 

当然,那个只有一个元素的阵列指出了阵列元素的变数。参数的数量取决於记录型态。iType栏位可以是定义在WINGDI.H档案中以字首EMR_开始的近百个常数之一。nSize栏位是总记录的大小,包括iTypenSize栏位以及一个或多个dParm栏位。 copyright dedecms

有了这些知识後,让我们看一下图18-3。第一个栏位型态为0x00000001,大小为0x00000088,所以它占据档案的前136个位元组。记录型态为1表示常数EMR_HEADER。我们不妨把对表头纪录的讨论往後搁,先跳到位於第一个记录末尾的偏移量0x0088处。

copyright dedecms

後面的5个记录与EMF2建立metafile之後的5GDI函式呼叫有关。该记录在偏移量0x0088处有一个值为0x0000002B的型态代码,这代表EMR_RECTANGLE,很明显是用於Rectangle呼叫的metafile记录。它的长度为0x00000018 (十进位24)位元组,用以容纳432位元参数。实际上Rectangle函式有5个参数,但是第一个参数,也就是装置内容代号并未储存在metafile中,因为它没有实际意义。尽管在EMF2的函式呼叫中指定了矩形的顶点座标分别是(100100)(200200),但4个参数中的2个是0x00000063 (99),另外2个是0x000000C6 (198)EMF2程式在Windows 98下建立的metafile显示出前两个参数是0x00000064 (100),後2个参数是0x000000C7(199)。显然,在Rectangle参数储存到metafile之前,Windows对它们作了调整,但没有保持一致。这就是对角线端点与矩形顶点不能重合的原因。 内容来自dedecms

其次,有416位元记录与2MoveToEx (0x0000001BEMR_MOVETOEX)LineTo (0x00000036EMR_LINETO)呼叫有关。位於metafile中的参数与传递给函式的参数相同。

copyright dedecms

Metafile20个位元组长的型态代码为0x0000000EEMR_EOF(「end of file」)的记录结尾。

dedecms.com

增强型metafile总是以表头纪录开始。它对应於ENHMETAHEADER型态的结构,定义如下:

dedecms.com

typedef struct tagENHMETAHEADER copyright dedecms 
{ 

织梦好,好织梦

        DWORD iType ;       // EMR_HEADER = 1 
copyright dedecms
        DWORD nSize ;       // structure size  copyright dedecms 
        RECTL rclBounds ;    // bounding rectangle in pixels 

内容来自dedecms

        RECTL rclFrame ;     // size of image in 0.01 millimeters 

copyright dedecms

        DWORD dSignature ;  // ENHMETA_SIGNATURE = " EMF" 

织梦内容管理系统

        DWORD nVersion ;    // 0x00010000 

copyright dedecms

        DWORD nBytes ;     // file size in bytes 
织梦内容管理系统
        DWORD nRecords ;   // total number of records 

copyright dedecms

        WORD  nHandles ;   // number of handles in handle table 本文来自织梦 
        WORD  sReserved ; 织梦内容管理系统 
       DWORD nDescription ;    // character length of description string 

dedecms.com

        DWORD offDescription ;   // offset of description string in file 

本文来自织梦

        DWORD nPalEntries ;     // number of entries in palette 
本文来自织梦
        SIZEL szlDevice ;        // device resolution in pixels 本文来自织梦 
        SIZEL szlMillimeters ;            // device resolution in millimeters dedecms.com 
        DWORD cbPixelFormat ;  // size of pixel format 

dedecms.com

        DWORD offPixelFormat ;  // offset of pixel format 

dedecms.com

        DWORD bOpenGL ;      // FALSE if no OpenGL records 内容来自dedecms 
} 

内容来自dedecms

ENHMETAHEADER ; 

织梦好,好织梦

这种表头纪录的存在可能是增强型metafile格式对早期Windows metafile所做的最为重要的改进。不需要对metafile档案使用档案I/O函式来取得这些表头资讯。如果具有metafile代号,就可以使用GetEnhMetaFileHeader函式: 内容来自dedecms

GetEnhMetaFileHeader (hemf, cbSize, &emh) ; 

dedecms.com

第一个参数是metafile代号。最後一个参数是指向ENHMETAHEADER结构的指标。第二个参数是该结构的大小。可以使用类似的GetEnh-MetaFileDescription函式取得描述字串。 织梦内容管理系统

如上面所定义的,ENHMETAHEADER结构有100位元组长,但在MF2.EMFmetafile中,记录的大小包括描述字串,所以大小为0x88,即136位元组。而Windows 98metafile的表头纪录不包含ENHMETAHEADER结构的最後3个栏位,这一点解释了12个位元组的差别。 dedecms.com

rclBounds栏位是指出图像大小的RECT结构,单位是图素。将其从十六进位转换过来,我们看到该图像正如我们希望的那样,其左上角位於(100,100),右下角位於(200,200)dedecms.com

rclFrame栏位是提供相同资讯的另一个矩形结构,但它是以0.01毫米为单位。在这种情况下,该档案显示两对角顶点分别位於(0x0C35,0x0C35)(0x186A,0x186A),用十进位表示为(3125,3125)(6250,6250)的矩形。这些数字是怎么来的?我们很快就会明白。 织梦内容管理系统

dSignature栏位始终为值ENHMETA_SIGNATURE0x464D4520。这看上去是一个奇怪的数字,但如果将位元组的排列顺序倒过来(就像Intel处理器在记忆体中储存多位元组数那样)并转换成ASCII码,就变成字串" EMF"dVersion栏位的值始终是0x00010000

copyright dedecms

其後是nBytes栏位,该栏位在本例中是0x000000F4,这是该metafile的总位元组数。nRecords栏位(在本例中是0x00000007)指出了记录数-包括表头纪录、5GDI函式呼叫和档案结束记录。 织梦内容管理系统

下面是两个十六位元的栏位。nHandles栏位为0x0001。该栏位一般指出metafile所使用的图形物件(如画笔、画刷和字体)的非内定代号的数量。由於没有使用这些图形物件,您可能会认为该栏位为零,但实际上GDI自己保留了第一个栏位。我们将很快见到代号储存在metafile中的方式。 copyright dedecms

下两个栏位指出描述字串的字元个数,以及描述字串在档案中的偏移量,这里它们分别为0x00000012(十进位数字18)和0x00000064。如果metafile没有描述字串,则这两个栏位均为零。 织梦内容管理系统

nPalEntries栏位指出在metafile的调色盘表中条目的个数,本例中没有这种情况。

织梦好,好织梦

接著表头纪录包括两个SIZEL结构,它们包含两个32位栏位,cxcyszlDevice栏位(在metafile中的偏移量为0x0040)指出了以图素为单位的输出设备大小,szlMillimeters栏位(偏移量为0x0050)指出了以毫米为单位的输出设备大小。在增强型metafile文件中,这个输出设备被称作「参考设备(reference device)」。它是依据作为第一个参数传递给CreateEnhMetaFile呼叫的代号所指出的装置内容。如果该参数设为NULL,则GDI使用视讯显示器。当EMF2建立上面所示的metafile时,正巧是在Windows NT上以1024×768显示模式工作,因此这就是GDI使用的参考设备。

dedecms.com

GDI通过呼叫GetDeviceCaps取得此资讯。EMF2.EMF中的szlDevice栏位是0x0400×0x0300(即1024×768),它是以HORZRESVERTRES作为参数呼叫GetDeviceCaps得到的。szlMillimeters栏位是0x140×0xF0,或320×240,是以HORZSIZEVERTSIZE作为参数呼叫GetDeviceCaps得到的。

织梦好,好织梦

通过简单的除法就可以得出图素为0.3125mm高和0.3125mm宽,这就是前面描述的GDI计算rclFrame矩形尺寸的方法。 织梦好,好织梦

metafile中,ENHMETAHEADER结构後跟一个描述字串,该字串是CreateEnhMetaFile函式的最後一个参数。在本例中,该字串由後跟一个NULL字元的「EMF2」字串和後跟两个NULL字元的「EMF Demo #2」字串组成。总共18个字元,要是以Unicode方式储存则为36个字元。无论建立metafile的程式执行在Windows NT还是Windows 98下,该字串始终以Unicode方式储存。 内容来自dedecms

metafileGDI物件
 

本文来自织梦

我们已经知道了GDI绘图命令储存在metafile中方式,现在看一下GDI物件的储存方式。程式18-4 EMF3除了建立用於绘制矩形和直线的非内定画笔和画刷以外,与前面介绍的EMF2程式很相似。该程式也对Rectangle座标的问题提出了一点修改。EMF3程式使用GetVersion来确定执行环境是Windows 98还是Windows NT,并适当地调整参数。

copyright dedecms

 程式18-4  EMF3 织梦好,好织梦 
EMF3.C 织梦好,好织梦 
/*---------------------------------------------------------------------------- 
dedecms.com
        EMF3.C --      Enhanced Metafile Demo #3 dedecms.com 
                                              (c) Charles Petzold, 1998 

copyright dedecms

-----------------------------------------------------------------------------*/ 内容来自dedecms 
  
织梦内容管理系统
#include <windows.h> 织梦内容管理系统 
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
copyright dedecms
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 

织梦内容管理系统

                                                                     PSTR szCmdLine, int iCmdShow) 本文来自织梦 
{ 
本文来自织梦
        static TCHAR szAppName[] = TEXT ("EMF3") ; 
dedecms.com
        HWND                                                         hwnd ; 
dedecms.com
        MSG                                                          msg ; 
织梦好,好织梦
        WNDCLASS                                              wndclass ; 

织梦内容管理系统

      

内容来自dedecms

        wndclass.style                                               = CS_HREDRAW | CS_VREDRAW ; 
织梦内容管理系统
        wndclass.lpfnWndProc                          = WndProc ; 

内容来自dedecms

        wndclass.cbClsExtra                           = 0 ; dedecms.com 
        wndclass.cbWndExtra                           = 0 ; 本文来自织梦 
        wndclass.hInstance                            = hInstance ; dedecms.com 
        wndclass.hIcon                                               = LoadIcon (NULL, IDI_APPLICATION) ; dedecms.com 
        wndclass.hCursor                                      = LoadCursor (NULL, IDC_ARROW) ; 

织梦好,好织梦

        wndclass.hbrBackground        = GetStockObject (WHITE_BRUSH) ; 

copyright dedecms

        wndclass.lpszMenuName                 = NULL ; 织梦好,好织梦 
        wndclass.lpszClassName                = szAppName ; 织梦好,好织梦 
      本文来自织梦 
        if (!RegisterClass (&wndclass)) 
织梦好,好织梦
        { dedecms.com 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 
本文来自织梦
                                                                     szAppName, MB_ICONERROR) ; 
内容来自dedecms
                       return 0 ; 

织梦好,好织梦

     } 织梦好,好织梦 
      内容来自dedecms 
        hwnd = CreateWindow (  szAppName, TEXT ("Enhanced Metafile Demo #3"), 
dedecms.com
                               WS_OVERLAPPEDWINDOW, 织梦好,好织梦 
                               CW_USEDEFAULT, CW_USEDEFAULT, 
copyright dedecms
                               CW_USEDEFAULT, CW_USEDEFAULT, 
本文来自织梦
                               NULL, NULL, hInstance, NULL) ; 
dedecms.com
      

copyright dedecms

        ShowWindow (hwnd, iCmdShow) ; 本文来自织梦 
        UpdateWindow (hwnd) ; 内容来自dedecms 
      
dedecms.com
        while (GetMessage (&msg, NULL, 0, 0)) 

织梦好,好织梦

        { 

织梦好,好织梦

                       TranslateMessage (&msg) ; 

内容来自dedecms

                       DispatchMessage (&msg) ; 内容来自dedecms 
        } dedecms.com 
        return msg.wParam ; 

织梦内容管理系统

} dedecms.com 
  内容来自dedecms 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) 内容来自dedecms 
{ 本文来自织梦 
        LOGBRUSH                              lb ; dedecms.com 
       HDC                                           hdc, hdcEMF ; 织梦内容管理系统 
        HENHMETAFILE           hemf ; 

织梦好,好织梦

        PAINTSTRUCT                    ps ; dedecms.com 
        RECT                                          rect ; 织梦内容管理系统 
        switch (message) 

织梦内容管理系统

     { 
copyright dedecms
        case    WM_CREATE: 

内容来自dedecms

               hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf3.emf"), NULL, 本文来自织梦 
            TEXT ("EMF3\0EMF Demo #3\0")) ; 织梦好,好织梦 
           
本文来自织梦
                               SelectObject (hdcEMF, CreateSolidBrush (RGB (0, 0, 255))) ; 内容来自dedecms 
           

copyright dedecms

                               lb.lbStyle = BS_SOLID ; 
dedecms.com
                               lb.lbColor = RGB (255, 0, 0) ; 
织梦内容管理系统
                               lb.lbHatch = 0 ; 

织梦内容管理系统

  织梦内容管理系统 
                               SelectObject (hdcEMF,  
织梦好,好织梦
                       ExtCreatePen (PS_SOLID | PS_GEOMETRIC, 5, &lb, 0, NULL)) ; 织梦好,好织梦 
           dedecms.com 
                               if (GetVersion () & 0x80000000) // Windows 98 dedecms.com 
                       Rectangle (hdcEMF, 100, 100, 201, 201) ; 
本文来自织梦
                               else     

内容来自dedecms

                                  // Windows NT 

织梦内容管理系统

                                              Rectangle (hdcEMF, 101, 101, 202, 202) ; 织梦好,好织梦 
           本文来自织梦 
                               MoveToEx               (hdcEMF, 100, 100, NULL) ; 

dedecms.com

                               LineTo                 (hdcEMF, 200, 200) ; 
copyright dedecms
           

内容来自dedecms

                               MoveToEx               (hdcEMF, 200, 100, NULL) ; 

copyright dedecms

                               LineTo                 (hdcEMF, 100, 200) ; 
本文来自织梦
           
本文来自织梦
                               DeleteObject (SelectObject (hdcEMF, GetStockObject (BLACK_PEN))) ; 

dedecms.com

                               DeleteObject (SelectObject (hdcEMF, GetStockObject (WHITE_BRUSH))) ; 

dedecms.com

           
织梦内容管理系统
                               hemf = CloseEnhMetaFile (hdcEMF) ; dedecms.com 
           
dedecms.com
                                              DeleteEnhMetaFile (hemf) ; copyright dedecms 
                                              return 0 ; 
内容来自dedecms
           内容来自dedecms 
                       case    WM_PAINT: 
本文来自织梦
                                              hdc = BeginPaint (hwnd, &ps) ; 内容来自dedecms 
           内容来自dedecms 
                                      GetClientRect (hwnd, &rect) ; 

dedecms.com

           
dedecms.com
                                              rect.left              =       rect.right             / 4 ; 
织梦内容管理系统
                                              rect.right             = 3 *   rect.right             / 4 ; dedecms.com 
                                              rect.top               =       rect.bottom            / 4 ; 织梦好,好织梦 
                                              rect.bottom            = 3 *   rect.bottom            / 4 ; 织梦内容管理系统 
           
织梦好,好织梦
                                              hemf = GetEnhMetaFile (TEXT ("emf3.emf")) ; 织梦内容管理系统 
           

内容来自dedecms

                                              PlayEnhMetaFile (hdc, hemf, &rect) ; 织梦内容管理系统 
                                              DeleteEnhMetaFile (hemf) ; 

dedecms.com

                                              EndPaint (hwnd, &ps) ; 内容来自dedecms 
                                              return 0 ; 
织梦好,好织梦
           
copyright dedecms
                       case    WM_DESTROY: 

copyright dedecms

                                              PostQuitMessage (0) ; 
内容来自dedecms
                                              return 0 ; 
织梦内容管理系统
        } 

本文来自织梦

        return DefWindowProc (hwnd, message, wParam, lParam) ; 
copyright dedecms
} 
dedecms.com

如我们所看到的,当利用CreateEnhMetaFile传回的装置内容代号来呼叫GDI函式时,这些函式呼叫被储存在metafile中而不是直接输出到萤幕或印表机上。然而,一些GDI函式根本不涉及特定的装置内容。其中有关建立画笔和画刷等图形物件的GDI函式十分重要。虽然逻辑画笔和画刷的定义储存在由GDI保留的记忆体中,但是在建立这些物件时,这些抽象的定义并未与任何特定的装置内容相关。

dedecms.com

EMF3呼叫CreateSolidBrushExtCreatePen函式。因为这些函式不需要装置内容代号,`所以GDI不会把这些呼叫储存在metafile里。当呼叫它们时,GDI函式只是简单地建立图形绘制物件而不会影响metafile

copyright dedecms

然而,当程式呼叫SelectObject函式将GDI物件选入metafile装置内容时,GDI既为物件建立函式编码(源自用於储存物件的内部GDI资料)也为metafile中的SelectObject呼叫进行编码。为了解其工作方式,我们来看一下EMF3.EMF档案的十六进位代码,如图18-4所示:

织梦内容管理系统

0000    01 00 00 00 88 00 00 00 60 00 00 00 60 00 00 00           ........`...`... 

内容来自dedecms

0010    CC 00 00 00 CC 00 00 00 B8 0B 00 00 B8 0B 00 00     ................ 

本文来自织梦

0020    E7 18 00 00 E7 18 00 00 20 45 4D 46 00 00 01 00       ........EMF..... copyright dedecms 
0030    88 01 00 00 0F 00 00 00 03 00 00 00 12 00 00 00       ................ 内容来自dedecms 
0040    64 00 00 00 00 00 00 00 00 04 00 00 00 03 00 00       d............... dedecms.com 
0050    40 01 00 00 F0 00 00 00 00 00 00 00 00 00 00 00       @............... 内容来自dedecms 
0060    00 00 00 00 45 00 4D 00 46 00 33 00 00 00 45 00       ....E.M.F.3...E. dedecms.com 
0070    4D 00 46 00 20 00 44 00 65 00 6D 00 6F 00 20 00       M.F....D.e.m.o.. 
dedecms.com
0080    23 00 33 00 00 00 00 00 27 00 00 00 18 00 00 00       #.3.....'....... 

dedecms.com

0090    01 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00       ................ 
织梦好,好织梦
00A0    25 00 00 00 0C 00 00 00 01 00 00 00 5F 00 00 00       %..........._... 
本文来自织梦
00B0    34 00 00 00 02 00 00 00 34 00 00 00 00 00 00 00       4.......4....... 织梦好,好织梦 
00C0    34 00 00 00 00 00 00 00 00 00 01 00 05 00 00 00       4............... 
织梦好,好织梦
00D0    00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00       ................ 织梦内容管理系统 
00E0    25 00 00 00 0C 00 00 00 02 00 00 00 2B 00 00 00       %...........+... 织梦内容管理系统 
00F0    18 00 00 00 63 00 00 00 63 00 00 00 C6 00 00 00       ....c...c....... 
本文来自织梦
0100    C6 00 00 00 1B 00 00 00 10 00 00 00 64 00 00 00       ............d... 织梦内容管理系统 
0110    64 00 00 00 36 00 00 00 10 00 00 00 C8 00 00 00       d...6........... copyright dedecms 
0120    C8 00 00 00 1B 00 00 00 10 00 00 00 C8 00 00 00       ................ copyright dedecms 
0130    64 00 00 00 36 00 00 00 10 00 00 00 64 00 00 00       d...6.......d... 织梦内容管理系统 
0140    C8 00 00 00 25 00 00 00 0C 00 00 00 07 00 00 80       ....%........... copyright dedecms 
0150    28 00 00 00 0C 00 00 00 02 00 00 00 25 00 00 00       (...........%... 织梦好,好织梦 
0160    0C 00 00 00 00 00 00 80 28 00 00 00 0C 00 00 00       ........(....... 织梦内容管理系统 
0170    01 00 00 00 0E 00 00 00 14 00 00 00 00 00 00 00       ................ copyright dedecms 
0180    10 00 00 00 14 00 00 00                                                          ........ 

织梦好,好织梦

  本文来自织梦

18-4 EMF3.EMF的十六进位代码

织梦好,好织梦

 

如果把这个metafile跟前面的EMF2.EMF档案进行比较,第一个不同点就是EMF3.EMF表头部分中的rclBounds栏位。在EMF2.EMF中,它指出图像限定在座标(0x64,0x64)(0xC8,0xC8)区域内。而在EMF3.EMF中,座标是(0x60,0x60)(0xCC,0xCC)。这表示使用了较粗的笔。rclFrame栏位(以0.01mm为单位指出图像大小)也受到影响。 本文来自织梦

EMF2.EMF中的nBytes栏位(偏移量为0x0030)显示该metafile长度为0xFA位元组,EMF3.EMF中长度为0x0188位元组。EMF2.EMFmetafile包含7个记录(一个表头纪录,5GDI函式呼叫和一个档案结束记录),但是EMF3.EMF档案包含15个记录。多出的8个记录是两个物件建立函式、4个对SelectObject函式的呼叫和两个对DeleteObject函式的呼叫。

织梦好,好织梦

nHandles栏位(在档案中偏移量为0x0038)指出GDI物件的代号个数。该栏位的值总是比metafile使用的非内定物件数多一。(Platform SDK文件解释这个多出来的一是「此表中保留的零索引」)。该栏位在EMF2.EMF的值为1,而在EMF3.EMF中的值为3,多出的数指出了画笔和画刷。 dedecms.com

让我们跳到档案中偏移量为0x0088的地方,即第二个记录(表头纪录之後的第一个记录)。记录型态为0x27,对应常数为EMR_CREATE-BRUSHINDIRECT。该metafile记录用於CreateBrushIndirect函式,此函式需要指向LOGBRUSH结构的指标作为参数。该记录的长度为0x18(或24)位元组。

内容来自dedecms

每个被选入metafile装置内容的非备用GDI物件得到一个号码,该号码从1开始编号。这在此记录的下4个位元组中指出,在metafile中的偏移量是0x0090。此记录下面的34位元组栏位分别对应LOGBRUSH结构的3个栏位:0x00000000BS_SOLIDlbStyle栏位)、0x00FF0000lbColor栏位)和0x00000000lbHatch栏位)。 内容来自dedecms

下一个记录在EMF3.EMF中的偏移量为0x00A0,记录型态为0x25,或EMR_SELECTOBJECT,是用於SelectObject呼叫的metafile记录。该记录的长度为0x0C(或12)位元组,下一个栏位是数值0x01,指出它是选中的第一个GDI物件,这就是逻辑画刷。

copyright dedecms

EMF3.EMF中的偏移量0x00AC是下一个记录,它的记录型态为0x5FEMR_EXTCREATEPEN。该记录有0x34(或52)个位元组。下一个4位元组栏位是0x02,它表示这是在metafile内使用的第二个非备用GDI物件。

内容来自dedecms

EMR_EXTCREATEPEN记录的下4个栏位重复记录大小两次,之间用0栏位隔开:0x340x000x340x00。下一个栏位是0x00010000,它是PS_SOLID (0x00000000)PS_GEOMETRIC (0x00010000)组合的画笔样式。接下来是5个单元的宽度,紧接著是ExtCreatePen中使用的逻辑画刷结构的3个栏位,後接0栏位。

织梦好,好织梦

如果建立了自订的扩展画笔样式,EMR_EXTCREATEPEN记录会超过52个位元组,这样会影响记录的第二栏位及两个重复的大小栏位。在描述LOGBRUSH结构的3个栏位後面不会是0(像在EMF3.EMF中那样),而是指出了虚线和空格的数量。这後面接著用於虚线和空格长度的许多栏位。 copyright dedecms

EMF3.EMF的下一个12位元组的栏位是指出第二个物件(画笔)的另一个SelectObject呼叫。接下来的5个记录与EMF2.EMF中的一样-一个0x2B(EMR_RECTANGLE)的记录型态和两组0x1B (EMR_MOVETOEX)0x36 (EMR_LINETO)记录。 内容来自dedecms

这些绘图函式後面跟著两组0x25(EMR_SELECTOBJECT)0x28 (EMR_DELETEOBJECT)12位元组记录。选择物件记录具有0x800000070x80000000的参数。在设定高位元时,它指出一个备用物件,在此例中是0x07(对应BLACK_PEN)和0x00 (WHITE_BRUSH)

织梦好,好织梦

DeleteObject呼叫有21两个参数,用於在metafile中使用的两个非内定物件。虽然DeleteObject函式并不需要装置内容代号作为它的第一个参数,但GDI显然保留了metafile中使用的被程式删除的物件。

内容来自dedecms

最後,metafile0x0EEMF_EOF)记录结束。

内容来自dedecms

总结一下,每当非内定的GDI物件首次被选入metafile装置内容时,GDI都会为该物件建立函式的记录编码(此例中,为EMR_CREATEBRUSHINDIRECTEMR_EXTCREATEPEN)。每个物件有一个依序从1开始的唯一数值,此数值由记录的第三个栏位表示。跟在此记录後的是引用该数值的EMR_SELECTOBJECT记录。以後,将物件选入metafile装置内容时(在中间时期没有被删除),就只需要EMR_SELECTOBJECT记录了。 织梦好,好织梦

metafile和点阵图
  本文来自织梦

现在,让我们做点稍微复杂的事,在metafile装置内容中绘制一幅点阵图,如程式18-5 EMF4所示。 织梦内容管理系统

 程式18-5  EMF4 织梦好,好织梦 
EMF4.C 

copyright dedecms

/*---------------------------------------------------------------------------- copyright dedecms 
        EMF4.C --      Enhanced Metafile Demo #4 织梦内容管理系统 
                                              (c) Charles Petzold, 1998 内容来自dedecms 
----------------------------------------------------------------------------*/ dedecms.com 
  

copyright dedecms

#define OEMRESOURCE 织梦内容管理系统 
#include <windows.h> 

织梦好,好织梦

  
织梦好,好织梦
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; dedecms.com 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 本文来自织梦 
                                                                     PSTR szCmdLine, int iCmdShow) 

本文来自织梦

{ 本文来自织梦 
        static TCHAR   szAppName[] = TEXT ("EMF4") ; 内容来自dedecms 
        HWND                                  hwnd ; 
copyright dedecms
        MSG                                   msg ; dedecms.com 
        WNDCLASS                       wndclass ; 本文来自织梦 
      织梦内容管理系统 
        wndclass.style                                               = CS_HREDRAW | CS_VREDRAW ; 
织梦好,好织梦
        wndclass.lpfnWndProc                          = WndProc ; 织梦内容管理系统 
        wndclass.cbClsExtra                           = 0 ; 织梦好,好织梦 
        wndclass.cbWndExtra                           = 0 ; 

copyright dedecms

       wndclass.hInstance                            = hInstance ; 

织梦内容管理系统

        wndclass.hIcon                                               = LoadIcon (NULL, IDI_APPLICATION) ; 

织梦好,好织梦

        wndclass.hCursor                                      = LoadCursor (NULL, IDC_ARROW) ; 

织梦好,好织梦

        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 
织梦好,好织梦
        wndclass.lpszMenuName                 = NULL ; 内容来自dedecms 
        wndclass.lpszClassName                = szAppName ; 
织梦内容管理系统
      copyright dedecms 
        if (!RegisterClass (&wndclass)) 织梦内容管理系统 
        { 

本文来自织梦

                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 
织梦内容管理系统
                                                                     szAppName, MB_ICONERROR) ; 
dedecms.com
                       return 0 ; 内容来自dedecms 
        } 内容来自dedecms 
      

本文来自织梦

        hwnd = CreateWindow (  szAppName, TEXT ("Enhanced Metafile Demo #4"), 

本文来自织梦

                         WS_OVERLAPPEDWINDOW, 

织梦好,好织梦

                         CW_USEDEFAULT, CW_USEDEFAULT, 织梦好,好织梦 
                         CW_USEDEFAULT, CW_USEDEFAULT, 

本文来自织梦

                         NULL, NULL, hInstance, NULL) ; 

内容来自dedecms

      本文来自织梦 
        ShowWindow (hwnd, iCmdShow) ; 织梦内容管理系统 
        UpdateWindow (hwnd) ; 织梦内容管理系统 
        while (GetMessage (&msg, NULL, 0, 0)) 本文来自织梦 
        { 
本文来自织梦
                       TranslateMessage (&msg) ; 
织梦好,好织梦
                       DispatchMessage (&msg) ; copyright dedecms 
        } 

本文来自织梦

        return msg.wParam ; dedecms.com 
} 织梦好,好织梦 
  

copyright dedecms

LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) 内容来自dedecms 
{ 织梦好,好织梦 
        BITMAP                         bm ; dedecms.com 
        HBITMAP                        hbm ; 
织梦好,好织梦
        HDC                            hdc, hdcEMF, hdcMem ; 

织梦内容管理系统

        HENHMETAFILE                   hemf ; 内容来自dedecms 
        PAINTSTRUCT                    ps ; copyright dedecms 
        RECT                           rect ; copyright dedecms 
      dedecms.com 
        switch (message) copyright dedecms 
        { 

内容来自dedecms

        case    WM_CREATE: 本文来自织梦 
               hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf4.emf"), NULL, 本文来自织梦 
            TEXT ("EMF4\0EMF Demo #4\0")) ; 本文来自织梦 
           本文来自织梦 
                               hbm = LoadBitmap (NULL, MAKEINTRESOURCE (OBM_CLOSE)) ; 

内容来自dedecms

           

内容来自dedecms

                               GetObject (hbm, sizeof (BITMAP), &bm) ; dedecms.com 
           
织梦内容管理系统
                               hdcMem = CreateCompatibleDC (hdcEMF) ; 
内容来自dedecms
           copyright dedecms 
                               SelectObject (hdcMem, hbm) ; dedecms.com 
           本文来自织梦 
                               StretchBlt (hdcEMF,100,100,100,100, 

织梦内容管理系统

                       hdcMem,0,0,bm.bmWidth, bm.bmHeight, SRCCOPY) ; 内容来自dedecms 
           
本文来自织梦
                               DeleteDC (hdcMem) ; 织梦内容管理系统 
                       DeleteObject (hbm) ; 
织梦好,好织梦
           
织梦好,好织梦
                               hemf = CloseEnhMetaFile (hdcEMF) ; 
织梦内容管理系统
           本文来自织梦 
                               DeleteEnhMetaFile (hemf) ; 

织梦内容管理系统

                               return 0 ; copyright dedecms 
           

织梦好,好织梦

        case    WM_PAINT: 织梦好,好织梦 
                               hdc = BeginPaint (hwnd, &ps) ; 本文来自织梦 
           
织梦好,好织梦
                               GetClientRect (hwnd, &rect) ; copyright dedecms 
                               rect.left              =     rect.right               / 4 ; 织梦好,好织梦 
                               rect.right             = 3 * rect.right               / 4 ; 
dedecms.com
                               rect.top                       =     rect.bottom      / 4 ; 

织梦内容管理系统

                               rect.bottom            = 3 * rect.bottom              / 4 ; 

织梦内容管理系统

           
本文来自织梦
                               hemf = GetEnhMetaFile (TEXT ("emf4.emf")) ; dedecms.com 
           
本文来自织梦
                               PlayEnhMetaFile (hdc, hemf, &rect) ; 
织梦内容管理系统
                               DeleteEnhMetaFile (hemf) ; copyright dedecms 
                               EndPaint (hwnd, &ps) ; 织梦好,好织梦 
                               return 0 ; 织梦内容管理系统 
           

本文来自织梦

        case    WM_DESTROY: 内容来自dedecms 
                               PostQuitMessage (0) ; copyright dedecms 
                               return 0 ; dedecms.com 
        } 
本文来自织梦
        return DefWindowProc (hwnd, message, wParam, lParam) ; 

织梦内容管理系统

} copyright dedecms 

为了方便,EMF4载入由常数OEM_CLOSE指出的系统点阵图。在装置内容中显示点阵图的惯用方法是通过使用CreateCompatibleDC建立与目的装置内容(此例为metafile装置内容)相容的记忆体装置内容。然後,通过使用SelectObject将点阵图选入该记忆体装置内容并且从该记忆体装置内容呼叫BitBltStretchBlt把点阵图画到目的装置内容。结束後,删除记忆体装置内容和点阵图。

dedecms.com

您会注意到EMF4也呼叫GetObject来确定点阵图的大小。这对SelectObject呼叫是很必要的。

内容来自dedecms

首先,这份程式码储存metafile的空间对GDI来说就是个挑战。在StretchBlt呼叫前根本没有别的GDI函式去处理metafile的装置内容。因此,让我们来看一看EMF4.EMF里头是如何做的,图18-5只显示了一部分。 织梦内容管理系统

0000    01 00 00 00 88 00 00 00 64 00 00 00 64 00 00 00              ........d...d... 
dedecms.com
0010    C7 00 00 00 C7 00 00 00 35 0C 00 00 35 0C 00 00                   ........5...5... 
dedecms.com
0020    4B 18 00 00 4B 18 00 00 20 45 4D 46 00 00 01 00              K...K....EMF.... 

copyright dedecms

0030    F0 0E 00 00 03 00 00 00 01 00 00 00 12 00 00 00              ................ dedecms.com 
0040    64 00 00 00 00 00 00 00 00 04 00 00 00 03 00 00              d............... dedecms.com 
0050    40 01 00 00 F0 00 00 00 00 00 00 00 00 00 00 00              @............... 本文来自织梦 
0060    00 00 00 00 45 00 4D 00 46 00 34 00 00 00 45 00              ....E.M.F.4...E. 织梦好,好织梦 
0070    4D 00 46 00 20 00 44 00 65 00 6D 00 6F 00 20 00              M.F...D.e.m.o... 

织梦好,好织梦

0080    23 00 34 00 00 00 00 00 4D 00 00 00 54 0E 00 00              #.4.....M...T... dedecms.com 
0090    64 00 00 00 64 00 00 00 C7 00 00 00 C7 00 00 00              d...d........... 

本文来自织梦

00A0    64 00 00 00 64 00 00 00 64 00 00 00 64 00 00 00              d...d...d...d... 

dedecms.com

00B0    20 00 CC 00 00 00 00 00 00 00 00 00 00 00 80 3F              ..............? 
本文来自织梦
00C0    00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00              ...........?.... dedecms.com 
00D0    00 00 00 00 FF FF FF 00 00 00 00 00 6C 00 00 00              ............l... 

本文来自织梦

00E0    28 00 00 00 94 00 00 00 C0 0D 00 00 28 00 00 00              (...........(... 
copyright dedecms
00F0    16 00 00 00 28 00 00 00 28 00 00 00 16 00 00 00              ....(...(....... 织梦好,好织梦 
0100    01 00 20 00 00 00 00 00 C0 0D 00 00 00 00 00 00              .. ............. 内容来自dedecms 
0110    00 00 00 00 00 00 00 00 00 00 00 00 C0 C0 C0 00              ................ 本文来自织梦 
0120    C0 C0 C0 00 C0 C0 C0 00 C0 C0 C0 00 C0 C0 C0 00           ................ 

内容来自dedecms

. . . .  

本文来自织梦

0ED0    C0 C0 C0 00 C0 C0 C0 00 C0 C0 C0 00 0E 00 00 00           ................ 
copyright dedecms
0EE0    14 00 00 00 00 00 00 00 10 00 00 00 14 00 00 00              ................ 
织梦好,好织梦

  copyright dedecms

18-5 EMF4.EMF的部分十六进位代码 本文来自织梦

 

metafile只包含3个记录-表头纪录、0x0E54位元组长度的0x4D(或EMR_STRETCHBLT)和档案结束记录。

织梦内容管理系统

我不解释该记录每个栏位的含义,但我会指出关键部分,以便理解GDIEMF4.C中的一系列函式呼叫转化为单个metafile记录的方法。

织梦内容管理系统

GDI已经把原始的与设备相关的点阵图转化为与装置无关的点阵图(DIB)。整个DIB储存在记录著自身大小的记录中。我想,在显示metafile和点阵图时,GDI实际上使用StretchDIBits函式而不是StretchBlt。或者,GDI使用CreateDIBitmapDIB转变回与设备相关的点阵图,然後使用记忆体装置内容及StretchBlt来显示点阵图。 copyright dedecms

EMR_STRETCHBLT记录开始於metafile的偏移量0x0088处。DIB储存在metafile中,以偏移量0x00F4开始,到0x0EDC处的记录结尾结束。DIBBITMAPINFOHEADER型态的40位元组的结构开始。在偏移量0x011C处接有22个图素行,每行40个图素。这是每图素32位元的DIB,所以每个图素需要4个位元组。 dedecms.com

列举metafile内容
 

织梦好,好织梦

当您希望存取metafile内的个别记录时,可以使用称作metafile列举的程序。如程式18-6 EMF5所示。此程式使用metafile来显示与EMF3相同的图像,但它是通过metafile列举来进行的。 本文来自织梦

 程式18-6 EMF5 dedecms.com 
EMF5.C 

织梦好,好织梦

/*---------------------------------------------------------------------------- 内容来自dedecms 
        EMF5.C --      Enhanced Metafile Demo #5 
内容来自dedecms
                                              (c) Charles Petzold, 1998 
dedecms.com
-----------------------------------------------------------------------------*/ 
本文来自织梦
#include <windows.h> copyright dedecms 
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; copyright dedecms 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
内容来自dedecms
                                                                     PSTR szCmdLine, int iCmdShow) dedecms.com 
{ 

织梦好,好织梦

        static TCHAR   szAppName[] = TEXT ("EMF5") ; 本文来自织梦 
        HWND                                  hwnd ; 

织梦好,好织梦

       MSG                                   msg ; 织梦好,好织梦 
        WNDCLASS                       wndclass ; 
织梦好,好织梦
      
内容来自dedecms
        wndclass.style                                               = CS_HREDRAW | CS_VREDRAW ; 

dedecms.com

        wndclass.lpfnWndProc                          = WndProc ; 
copyright dedecms
        wndclass.cbClsExtra                           = 0 ; 
本文来自织梦
        wndclass.cbWndExtra                           = 0 ; 
dedecms.com
        wndclass.hInstance                            = hInstance ; 内容来自dedecms 
        wndclass.hIcon                                               = LoadIcon (NULL, IDI_APPLICATION) ; dedecms.com 
        wndclass.hCursor                                      = LoadCursor (NULL, IDC_ARROW) ; copyright dedecms 
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 
本文来自织梦
        wndclass.lpszMenuName                 = NULL ; 

织梦内容管理系统

        wndclass.lpszClassName                = szAppName ; 

本文来自织梦

      

本文来自织梦

        if (!RegisterClass (&wndclass)) 

织梦内容管理系统

        { copyright dedecms 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 

dedecms.com

                                                                     szAppName, MB_ICONERROR) ; copyright dedecms 
                       return 0 ; 

织梦好,好织梦

     } 

织梦好,好织梦

      
织梦内容管理系统
        hwnd = CreateWindow (  szAppName, TEXT ("Enhanced Metafile Demo #5"), 
本文来自织梦
                               WS_OVERLAPPEDWINDOW, 内容来自dedecms 
                               CW_USEDEFAULT, CW_USEDEFAULT, 

内容来自dedecms

                               CW_USEDEFAULT, CW_USEDEFAULT, 织梦好,好织梦 
                               NULL, NULL, hInstance, NULL) ; 内容来自dedecms 
      
dedecms.com
        ShowWindow (hwnd, iCmdShow) ; 

copyright dedecms

        UpdateWindow (hwnd) ; 
织梦内容管理系统
      
织梦好,好织梦
        while (GetMessage (&msg, NULL, 0, 0)) copyright dedecms 
        { 
本文来自织梦
                       TranslateMessage (&msg) ; dedecms.com 
                       DispatchMessage (&msg) ; 

织梦好,好织梦

        } 
copyright dedecms
        return msg.wParam ; 本文来自织梦 
} 
内容来自dedecms
  copyright dedecms 
int CALLBACK EnhMetaFileProc (HDC hdc, HANDLETABLE * pHandleTable, 
内容来自dedecms
                                CONST ENHMETARECORD * pEmfRecord,  copyright dedecms 
                              int iHandles, LPARAM pData) 织梦好,好织梦 
{ 织梦好,好织梦 
        PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfRecord, iHandles) ; 本文来自织梦 
        return TRUE ; 
内容来自dedecms
} 本文来自织梦 
  本文来自织梦 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) dedecms.com 
{ 本文来自织梦 
        HDC                    hdc ; 

dedecms.com

        HENHMETAFILE           hemf ; 织梦内容管理系统 
        PAINTSTRUCT            ps ; 
本文来自织梦
        RECT                   rect ; 

内容来自dedecms

      
织梦好,好织梦
        switch (message) 内容来自dedecms 
     { 
dedecms.com
        case    WM_PAINT: 
内容来自dedecms
                               hdc = BeginPaint (hwnd, &ps) ; 织梦内容管理系统 
           
内容来自dedecms
                               GetClientRect (hwnd, &rect) ; 内容来自dedecms 
           

内容来自dedecms

                               rect.left                      =     rect.right               / 4 ; 

织梦内容管理系统

                               rect.right                     = 3 * rect.right               / 4 ; 
织梦内容管理系统
                               rect.top                       =     rect.bottom              / 4 ; 织梦好,好织梦 
                               rect.bottom                    = 3 * rect.bottom              / 4 ; 内容来自dedecms 
           

copyright dedecms

                       hemf = GetEnhMetaFile (TEXT ("..\\emf3\\emf3.emf")) ; 本文来自织梦 
           本文来自织梦 
                               EnumEnhMetaFile (hdc, hemf, EnhMetaFileProc, NULL, &rect) ; 
copyright dedecms
                               DeleteEnhMetaFile (hemf) ; 

dedecms.com

                               EndPaint (hwnd, &ps) ; copyright dedecms 
                               return 0 ; 织梦内容管理系统 
           织梦好,好织梦 
        case    WM_DESTROY: 织梦好,好织梦 
                               PostQuitMessage (0) ; 织梦内容管理系统 
                               return 0 ; 织梦内容管理系统 
        } 本文来自织梦 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 

dedecms.com

} 

本文来自织梦

此程式使用EMF3程式建立的EMF3.EMF档案,所以确定在执行此程式前先执行EMF3程式。同时,需要在Visual C++环境中执行两个程式,以确保路径的正确。在处理WM_PAINT时,两个程式的主要区别是EMF3呼叫PlayEnhMetaFile,而EMF5呼叫EnumEnhMetaFilePlayEnhMetaFile函式有下面的语法:

本文来自织梦

PlayEnhMetaFile (hdc, hemf, &rect) ; 织梦好,好织梦 

第一个参数是要显示的metafile的装置内容代号。第二个参数是增强型metafile代号。第三个参数是指向描述装置内容平面上矩形的RECT结构的指标。Metafile图像大小被缩放过,以便刚好能够显示在不超过该矩形的区域内。 dedecms.com

EnumEnhMetaFile5个参数,其中3个与PlayEnhMetaFile一样(虽然RECT结构的指标已经移到参数表的末尾)。 本文来自织梦

EnumEnhMetaFile的第三个参数是列举函式的名称,它用於呼叫EnhMetaFileProc。第四个参数是希望传递给列举函式的任意资料的指标,这里将该参数简单地设定为NULL织梦好,好织梦

现在看一看列举函式。当呼叫EnumEnhMetaFile时,对於metafile中的每一个记录,GDI都将呼叫EnhMetaFileProc一次,包括表头纪录和档案结束记录。通常列举函式传回TRUE,但它可能传回FALSE以略过剩下的列举程序。 本文来自织梦

该列举函式有5个参数,稍後会描述它们。在这个程式中,我仅把前4个参数传递给PlayEnhMetaFileRecord,它使GDI执行由该记录代表的函式呼叫,好像您明确地呼叫它一样。 织梦内容管理系统

EMF5使用EnumEnhMetaFilePlayEnhMetaFileRecord得到的结果与EMF3呼叫PlayEnhMetaFile得到的结果一样。区别在於EMF5现在直接介入了metafile的显示程序,并能够存取各个metafile记录。这是很有用的。 织梦内容管理系统

列举函式的第一个参数是装置内容代号。GDIEnumEnhMetaFile的第一个参数中简单地取得此代号。列举函式把该代号传递给PlayEnhMetaFileRecord来标识图像显示的目的装置内容。

织梦好,好织梦

我们先跳到列举函式的第三个参数,它是指向ENHMETARECORD型态结构的指标,前面已经提到过。这个结构描述实际的metafile记录,就像它亲自在metafile中编码一样。

本文来自织梦

您可以写一些程式码来检查这些记录。您也许不想把某些记录传送到PlayEnhMetaFileRecord函式。例如,在EMF5.C中,把下行插入到PlayEnhMetaFileRecord呼叫的前面:

本文来自织梦

if (pEmfRecord->iType != EMR_LINETO) 本文来自织梦 

重新编译程序,执行它,将只看到矩形,而没有两条线。或使用下面的叙述: 本文来自织梦

if (pEmfRecord->iType != EMR_SELECTOBJECT) 织梦好,好织梦 

这个小改变会让GDI用内定物件显示图像,而不是用metafile所建立的画笔和画刷。

本文来自织梦

程式中不应该修改metafile记录,不过先不要担心这一点。先来看一看程式18-7 EMF6内容来自dedecms

 程式18-7 EMF6 
内容来自dedecms
EMF6.C 织梦好,好织梦 
/*---------------------------------------------------------------------------- 

内容来自dedecms

        EMF6.C --      Enhanced Metafile Demo #6 

copyright dedecms

                                              (c) Charles Petzold, 1998 dedecms.com 
-----------------------------------------------------------------------------*/ 织梦好,好织梦 
  
织梦好,好织梦
#include <windows.h> 
copyright dedecms
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 

本文来自织梦

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 织梦内容管理系统 
                                                                     PSTR lpszCmdLine, int iCmdShow) copyright dedecms 
{ 织梦好,好织梦 
        static TCHAR   szAppName[] = TEXT ("EMF6") ; dedecms.com 
        HWND                                  hwnd ; 
copyright dedecms
        MSG                                   msg ; copyright dedecms 
        WNDCLASS                       wndclass ; 
copyright dedecms
      织梦内容管理系统 
        wndclass.style                                = CS_HREDRAW | CS_VREDRAW ; 

织梦内容管理系统

        wndclass.lpfnWndProc                          = WndProc ; copyright dedecms 
        wndclass.cbClsExtra                           = 0 ; 
内容来自dedecms
        wndclass.cbWndExtra                           = 0 ; 本文来自织梦 
        wndclass.hInstance                            = hInstance ; 内容来自dedecms 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 

内容来自dedecms

        wndclass.hCursor                      = LoadCursor (NULL, IDC_ARROW) ; 
本文来自织梦
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 
内容来自dedecms
        wndclass.lpszMenuName                 = NULL ; 织梦好,好织梦 
        wndclass.lpszClassName                = szAppName ; 

织梦好,好织梦

      

织梦好,好织梦

        if (!RegisterClass (&wndclass)) 

内容来自dedecms

        { 本文来自织梦 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 
本文来自织梦
                                                                     szAppName, MB_ICONERROR) ; 
织梦内容管理系统
                       return 0 ; dedecms.com 
        } 
织梦好,好织梦
      本文来自织梦 
        hwnd = CreateWindow (szAppName, TEXT ("Enhanced Metafile Demo #6"), 
内容来自dedecms
                         WS_OVERLAPPEDWINDOW, 织梦内容管理系统 
                         CW_USEDEFAULT, CW_USEDEFAULT, 
内容来自dedecms
                         CW_USEDEFAULT, CW_USEDEFAULT, 内容来自dedecms 
                         NULL, NULL, hInstance, NULL) ; 
织梦内容管理系统
      dedecms.com 
        ShowWindow (hwnd, iCmdShow) ; dedecms.com 
        UpdateWindow (hwnd) ; 

织梦内容管理系统

        while (GetMessage (&msg, NULL, 0, 0)) 织梦好,好织梦 
        { 织梦内容管理系统 
                       TranslateMessage (&msg) ; 本文来自织梦 
                       DispatchMessage (&msg) ; 本文来自织梦 
        } 

本文来自织梦

        return msg.wParam ; dedecms.com 
} 

本文来自织梦

  织梦内容管理系统 
int CALLBACK EnhMetaFileProc (HDC hdc, HANDLETABLE * pHandleTable, 

织梦好,好织梦

                              CONST ENHMETARECORD * pEmfRecord,  

copyright dedecms

                              int iHandles, LPARAM pData) 

dedecms.com

{ dedecms.com 
        ENHMETARECORD * pEmfr ; 
本文来自织梦
        pEmfr = (ENHMETARECORD *) malloc (pEmfRecord->nSize) ; 

dedecms.com

        CopyMemory (pEmfr, pEmfRecord, pEmfRecord->nSize) ; 

dedecms.com

        if (pEmfr->iType == EMR_RECTANGLE) 织梦好,好织梦 
                               pEmfr->iType = EMR_ELLIPSE ; 

copyright dedecms

        PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfr, iHandles) ; 
织梦好,好织梦
        free (pEmfr) ; 
内容来自dedecms
        return TRUE ; 

本文来自织梦

} 

本文来自织梦

  
织梦好,好织梦
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) dedecms.com 
{ 
dedecms.com
        HDC                    hdc ; copyright dedecms 
        HENHMETAFILE           hemf ; 

织梦好,好织梦

        PAINTSTRUCT            ps ; 
dedecms.com
        RECT                   rect ; 内容来自dedecms 
      
织梦好,好织梦
        switch (message) 

织梦内容管理系统

        { dedecms.com 
        case    WM_PAINT: 织梦内容管理系统 
                               hdc = BeginPaint (hwnd, &ps) ; 

内容来自dedecms

           织梦好,好织梦 
                               GetClientRect (hwnd, &rect) ; dedecms.com 
           
本文来自织梦
                               rect.left                      =     rect.right       / 4 ; 

织梦内容管理系统

                               rect.right                     = 3 * rect.right       / 4 ; 
dedecms.com
                               rect.top                       =     rect.bottom      / 4 ; 

织梦内容管理系统

                               rect.bottom                    = 3 * rect.bottom      / 4 ; 本文来自织梦 
           本文来自织梦 
               hemf = GetEnhMetaFile (TEXT ("..\\emf3\\emf3.emf")) ; 
dedecms.com
               EnumEnhMetaFile (      hdc, hemf, EnhMetaFileProc, NULL, &rect) ; 本文来自织梦 
                                                     DeleteEnhMetaFile (hemf) ; 内容来自dedecms 
                                                      EndPaint (hwnd, &ps) ; 

织梦好,好织梦

                                                     return 0 ; 本文来自织梦 
           

织梦内容管理系统

        case    WM_DESTROY: 织梦好,好织梦 
                               PostQuitMessage (0) ; 
织梦内容管理系统
                               return 0 ; 内容来自dedecms 
     } dedecms.com 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 内容来自dedecms 
} 织梦好,好织梦 

EMF5一样,EMF6使用EMF3程式建立的EMF3.EMFmetafile,因此要在Visual C++中执行这个程式之前先执行过EMF3程式。

dedecms.com

EMF6展示了如果在显示metafile之前要修改它们,解决方法是非常简单的:做个被修改过的副本出来就好了。您可以看到,列举程序一开始使用malloc配置一块metafile记录大小的记忆体,它是由传递给该函式的pEmfRecord结构的nSize栏位表示的。这个记忆体块的指标储存在变数pEmfr中,pEmfr本身是指向ENHMETARECORD结构的指标。

dedecms.com

程式使用CopyMemorypEmfRecord指向的结构内容复制到pEmfr指向的结构中。现在我们就可以做些修改了。程式检查记录是否为EMR_RECTANGLE型态,如果是,则用EMR_ELLIPSE取代iType栏位。PEmfr指标被传递到PlayEnhMetaFileRecord然後被释放。结果是程式画出一个椭圆而不是矩形。其他的内容的修改方式都是相同的。

织梦内容管理系统

当然,我们的小改变很容易起作用,因为RectangleEllipse函式有同样的参数,这些参数都定义同一件事-图画的边界框。要进行范围更广的修改需要一些不同metafile记录格式的相关知识。 dedecms.com

另一个可能性是插入一、两个额外的记录。例如,用下面的叙述代替EMF6.C中的if叙述:

织梦内容管理系统

if (pEmfr->iType == EMR_RECTANGLE) 内容来自dedecms 
{ copyright dedecms 
        PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfr, nObjects) ; 内容来自dedecms 
        pEmfr->iType = EMR_ELLIPSE ; 本文来自织梦 
} 
copyright dedecms

无论何时出现Rectangle记录,程式都会处理此记录并把它更改为Ellipse,然後再显示。现在程式将画出矩形和椭圆。 织梦好,好织梦

现在讨论一下在列举metafileGDI物件处理的方式。

织梦内容管理系统

metafile表头中,ENHMETAHEADER结构的nHandles栏位是比在metafile中建立的GDI物件数还要大的值。因此,对於EMF5EMF6中的metafile,此栏位是3,表示画笔、画刷和其他东西。「其他东西」的具体内容,稍後我会说明。

内容来自dedecms

您会注意到EMF5EMF6中列举函式的倒数第二个参数,也称作nHandles,它是同一个数,3

本文来自织梦

列举函式的第二个参数是指向HANDLETABLE结构的指标,在WINGDI.H中定义如下:

织梦内容管理系统

typedef struct tagHANDLETABLE 

织梦内容管理系统

{ 织梦内容管理系统 
        HGDIOBJ objectHandle [1] ; 织梦内容管理系统 
} 

本文来自织梦

HANDLETABLE ; 

内容来自dedecms

HGDIOBJ资料型态是GDI物件的代号,被定义为32位元的指标,类似於所有其他GDI物件。这是那些带有一个元素的阵列栏位的结构之一。这意味著此栏位具有可变的长度。objectHandle阵列中的元素数等於nHandles,在此程式中是3

copyright dedecms

在列举函式中,可以使用以下运算式取得这些GDI物件代号:

织梦好,好织梦

pHandleTable->objectHandle[i] copyright dedecms 

对於3个代号,i012

织梦好,好织梦

每次呼叫列举函式时,阵列的第一个元素都将包含所列举的metafile代号。这就是前面提到的「其他东西」。

dedecms.com

在第一次呼叫列举函式时,表的第二、第三个元素将是0。它们是画笔和画刷代号的保留位置。 dedecms.com

以下是列举函式运作的方式:metafile中的第一个物件建立函式具有EMR_CREATEBRUSHINDIRECT的记录型态,此记录指出了物件编号1。当把该记录传递给PlayEnhMetaFileRecord时,GDI建立画刷并取得它的代号。此代号储存在objectHandle阵列的元素1(第二个元素)中。当把第一个EMR_SELECTOBJECT记录传递给PlayEnhMetaFileRecord时,GDI发现此物件编号为1,并能够从表中找到该物件实际的代号,而把它用来呼叫SelectObject。当metafile最後删除画刷时,GDIobjectHandle阵列的元素1设定回0织梦好,好织梦

通过存取objectHandle阵列,可以使用例如GetObjectTypeGetObject等呼叫取得在metafile中使用的物件资讯。

dedecms.com

嵌入图像
  织梦内容管理系统

列举metafile的最重要应用也许是在现有的metafile中嵌入其他图像(甚至是整个metafile)。事实上,现有的metafile保持不变;真正进行的是建立包含现有metafile和新嵌入图像的新metafile。基本的技巧是把metafile装置内容代号传递给EnumEnhMetaFile,作为它的第一个参数。这使您能够在metafile装置内容上显示metafile记录和GDI函式呼叫。

copyright dedecms

metafile命令序列的开头或结尾嵌入新图像是极简单的-就在EMR_HEADER记录之後或在EMF_EOF记录之前。然而,如果您熟悉现有的metafile结构,就可以把新的绘图命令嵌入所需的任何地方。如程式18-8 EMF7所示。

内容来自dedecms

 程式18-8 EMF7 
dedecms.com
EMF7.C 织梦内容管理系统 
/*--------------------------------------------------------------------------- 

copyright dedecms

        EMF7.C -- Enhanced Metafile Demo #7 copyright dedecms 
                                              (c) Charles Petzold, 1998 dedecms.com 
-----------------------------------------------------------------------------*/ 内容来自dedecms 
  织梦内容管理系统 
#include <windows.h> 
织梦好,好织梦
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
dedecms.com
int WINAPI WinMain (   HINSTANCE hInstance, HINSTANCE hPrevInstance, 织梦内容管理系统 
                                                                            PSTR lpszCmdLine, int iCmdShow) 织梦内容管理系统 
{ 本文来自织梦 
        static TCHAR   szAppName[] = TEXT ("EMF7") ; 

内容来自dedecms

        HWND                                  hwnd ; 
copyright dedecms
        MSG                                   msg ; 内容来自dedecms 
        WNDCLASS                       wndclass ; 内容来自dedecms 
      

copyright dedecms

        wndclass.style                                        = CS_HREDRAW | CS_VREDRAW ; 

织梦好,好织梦

        wndclass.lpfnWndProc                          = WndProc ; 
copyright dedecms
        wndclass.cbClsExtra                           = 0 ; 

织梦内容管理系统

        wndclass.cbWndExtra                           = 0 ; dedecms.com 
        wndclass.hInstance                            = hInstance ; copyright dedecms 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 织梦内容管理系统 
        wndclass.hCursor                      = LoadCursor (NULL, IDC_ARROW) ; 本文来自织梦 
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; 织梦好,好织梦 
        wndclass.lpszMenuName                 = NULL ; 织梦内容管理系统 
        wndclass.lpszClassName                = szAppName ; 
copyright dedecms
      
织梦内容管理系统
        if (!RegisterClass (&wndclass)) 织梦好,好织梦 
        { 

dedecms.com

                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), 

copyright dedecms

                                                                     szAppName, MB_ICONERROR) ; dedecms.com 
                       return 0 ; 
copyright dedecms
        } 
dedecms.com
      织梦好,好织梦 
        hwnd = CreateWindow (szAppName, TEXT ("Enhanced Metafile Demo #7"), copyright dedecms 
                         WS_OVERLAPPEDWINDOW, 

copyright dedecms

                         CW_USEDEFAULT, CW_USEDEFAULT, 
织梦内容管理系统
                         CW_USEDEFAULT, CW_USEDEFAULT, 织梦内容管理系统 
                         NULL, NULL, hInstance, NULL) ; 

织梦内容管理系统

      

织梦内容管理系统

        ShowWindow (hwnd, iCmdShow) ; 
本文来自织梦
        UpdateWindow (hwnd) ; 内容来自dedecms 
      
织梦好,好织梦
        while (GetMessage (&msg, NULL, 0, 0)) 本文来自织梦 
        { copyright dedecms 
                       TranslateMessage (&msg) ; 

织梦内容管理系统

                       DispatchMessage (&msg) ; 

织梦内容管理系统

        } dedecms.com 
     return msg.wParam ; 织梦好,好织梦 
} 
织梦好,好织梦
  copyright dedecms 
int CALLBACK EnhMetaFileProc (HDC hdc, HANDLETABLE * pHandleTable, 

copyright dedecms

                              CONST ENHMETARECORD * pEmfRecord,  织梦内容管理系统 
                                int iHandles, LPARAM pData) 

本文来自织梦

{ 

copyright dedecms

        HBRUSH                         hBrush ; 内容来自dedecms 
        HPEN                                  hPen ; 织梦好,好织梦 
        LOGBRUSH                       lb ; 内容来自dedecms 
      本文来自织梦 
        if (pEmfRecord->iType != EMR_HEADER && pEmfRecord->iType != EMR_EOF) 

dedecms.com

                       PlayEnhMetaFileRecord (hdc, pHandleTable, pEmfRecord, iHandles) ; copyright dedecms 
        if (pEmfRecord->iType == EMR_RECTANGLE) 
内容来自dedecms
        { 内容来自dedecms 
                       hBrush = SelectObject (hdc, GetStockObject (NULL_BRUSH)) ; dedecms.com 
                       lb.lbStyle = BS_SOLID ; 内容来自dedecms 
                       lb.lbColor = RGB (0, 255, 0) ; 
内容来自dedecms
                       lb.lbHatch = 0 ; 

本文来自织梦

           内容来自dedecms 
                       hPen = SelectObject (hdc, 

内容来自dedecms

                                              ExtCreatePen (PS_SOLID | PS_GEOMETRIC, 5, &lb, 0, NULL)) ; 

copyright dedecms

               Ellipse (hdc, 100, 100, 200, 200) ; 
内容来自dedecms
                       DeleteObject (SelectObject (hdc, hPen)) ; 
织梦好,好织梦
                       SelectObject (hdc, hBrush) ; 

本文来自织梦

        } 织梦好,好织梦 
        return TRUE ; 内容来自dedecms 
} 

织梦内容管理系统

  
dedecms.com
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) 织梦好,好织梦 
{ 
织梦好,好织梦
        ENHMETAHEADER          emh ; 
dedecms.com
        HDC                                           hdc, hdcEMF ; 织梦内容管理系统 
        HENHMETAFILE           hemfOld, hemf ; 
织梦好,好织梦
        PAINTSTRUCT                    ps ; 

织梦好,好织梦

        RECT                                          rect ; 

copyright dedecms

         本文来自织梦 
        switch (message) 本文来自织梦 
        { 
织梦内容管理系统
        case    WM_CREATE: copyright dedecms 
           
织梦内容管理系统
                                                             // Retrieve existing metafile and header dedecms.com 
           

本文来自织梦

                               hemfOld = GetEnhMetaFile (TEXT ("..\\emf3\\emf3.emf")) ; 
织梦内容管理系统
           织梦好,好织梦 
                              GetEnhMetaFileHeader (hemfOld, sizeof (ENHMETAHEADER), &emh) ; 
copyright dedecms
           

dedecms.com

                                                             // Create a new metafile DC 内容来自dedecms 
           dedecms.com 
                       hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf7.emf"), NULL, dedecms.com 
                                              TEXT ("EMF7\0EMF Demo #7\0")) ; 

织梦内容管理系统

           

内容来自dedecms

                                                             // Enumerate the existing metafile 
copyright dedecms
           
本文来自织梦
                               EnumEnhMetaFile (hdcEMF, hemfOld, EnhMetaFileProc, NULL, 

织梦好,好织梦

                                              (RECT *) & emh.rclBounds) ; 织梦内容管理系统 
           

copyright dedecms

                                                             // Clean up 

织梦内容管理系统

           本文来自织梦 
                       hemf = CloseEnhMetaFile (hdcEMF) ; 织梦内容管理系统 
           

dedecms.com

                       DeleteEnhMetaFile (hemfOld) ; 织梦好,好织梦 
                               DeleteEnhMetaFile (hemf) ; dedecms.com 
                               return 0 ; 
内容来自dedecms
           本文来自织梦 
        case    WM_PAINT: 织梦好,好织梦 
                               hdc = BeginPaint (hwnd, &ps) ; 织梦好,好织梦 
           本文来自织梦 
                               GetClientRect (hwnd, &rect) ; 织梦好,好织梦 
                               rect.left                      =     rect.right       / 4 ; 
内容来自dedecms
                               rect.right                     = 3 * rect.right       / 4 ; 
本文来自织梦
                               rect.top                       =     rect.bottom   / 4 ; 

织梦内容管理系统

                               rect.bottom                    = 3 * rect.bottom   / 4 ; 

dedecms.com

           织梦内容管理系统 
                               hemf = GetEnhMetaFile (TEXT ("emf7.emf")) ; 

织梦内容管理系统

           本文来自织梦 
                               PlayEnhMetaFile (hdc, hemf, &rect) ; 

织梦好,好织梦

                               DeleteEnhMetaFile (hemf) ; 

织梦好,好织梦

                               EndPaint (hwnd, &ps) ; 

本文来自织梦

                               return 0 ; 

织梦好,好织梦

           
copyright dedecms
        case    WM_DESTROY: 内容来自dedecms 
                               PostQuitMessage (0) ; 
内容来自dedecms
                               return 0 ; 

织梦内容管理系统

        } 本文来自织梦 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 本文来自织梦 
} 
dedecms.com

EMF7使用EMF3程式建立的EMF3.EMF,所以在执行EMF7之前要执行EMF3程式建立metafilededecms.com

EMF7中的WM_PAINT处理使用PlayEnhMetaFile而不是EnumEnhMetaFile,而且WM_CREATE处理有很大的差别。 内容来自dedecms

首先,程式通过呼叫GetEnhMetaFile取得EMF3.EMF档案的metafile代号,还呼叫GetEnhMetaFileHeader得到增强型metafile表头记录,目的是在後面的EnumEnhMetaFile呼叫中使用rclBounds栏位。 copyright dedecms

接下来,程式建立新的metafile档案,名为EMF7.EMFCreateEnhMetaFile函式为metafile传回装置内容代号。然後,使用EMF7.EMFmetafile装置内容代号和EMF3.EMFmetafile代号呼叫EnumEnhMetaFilededecms.com

现在来看一看EnhMetaFileProc。如果被列举的记录不是表头纪录或档案结束记录,函式就呼叫PlayEnhMetaFileRecord把记录转换为新的metafile装置内容(并不一定排除表头纪录或档案结束记录,但它们会使metafile变大)。 织梦内容管理系统

如果刚转换的记录是Rectangle呼叫,则函式建立画笔用绿色的轮廓线和透明的内部来绘制椭圆。注意程式中经由储存先前的画笔和画刷代号来恢复装置内容状态的方法。在此期间,所有这些函式都被插入到metafile中(记住,也可以使用PlayEnhMetaFile在现有的metafile中插入整个metafile)。

dedecms.com

回到WM_CREATE处理,程式呼叫CloseEnhMetaFile取得新metafile的代号。然後,它删除两个metafile代号,将EMF3.EMFEMF7.EMF档案留在磁片上。 织梦好,好织梦

从程式显示输出中可以很明显地看到,椭圆是在矩形之後两条交叉线之前绘制的。 织梦内容管理系统

增强型metafile阅览器和印表机
 

本文来自织梦

使用剪贴簿转换增强型metafile非常简单,剪贴簿型态是CF_ENHMETAFILEGetClipboardData函式传回增强型metafile代号,SetClipboardData也使用该metafile代号。复制metafile时可以使用CopyEnhMetaFile函式。如果把增强型metafile放在剪贴簿中,Windows会让需要旧格式的那些程式也可以使用它。如果在剪贴簿中放置旧格式的metafileWindows将也会自动视需要把内容转换为增强型metafile的格式。

本文来自织梦

程式18-9 EMFVIEW所示为在剪贴簿中传送metafile的程式码,它也允许载入、储存和列印metafile织梦内容管理系统

 程式18-9 EMFVIEW 织梦内容管理系统 
EMFVIEW.C 
内容来自dedecms
/*--------------------------------------------------------------------------- 内容来自dedecms 
        EMFVIEW.C --   View Enhanced Metafiles 本文来自织梦 
                                                             (c) Charles Petzold, 1998 
dedecms.com
-----------------------------------------------------------------------------*/ 
织梦好,好织梦
  织梦内容管理系统 
#include <windows.h> 织梦内容管理系统 
#include <commdlg.h> copyright dedecms 
#include "resource.h" 

织梦好,好织梦

  
织梦好,好织梦
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; dedecms.com 
TCHAR szAppName[] = TEXT ("EmfView") ; 本文来自织梦 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 

织梦好,好织梦

                                                                     PSTR szCmdLine, int iCmdShow) copyright dedecms 
{ 织梦好,好织梦 
        HACCEL                         hAccel ; 内容来自dedecms 
        HWND                                  hwnd ; 

copyright dedecms

        MSG                                   msg ; 内容来自dedecms 
        WNDCLASS wndclass ; 
copyright dedecms
        wndclass.style                                = CS_HREDRAW | CS_VREDRAW ; 
copyright dedecms
        wndclass.lpfnWndProc                          = WndProc ; 织梦内容管理系统 
        wndclass.cbClsExtra                           = 0 ; 
内容来自dedecms
        wndclass.cbWndExtra                           = 0 ; 织梦好,好织梦 
        wndclass.hInstance                            = hInstance ; 

织梦好,好织梦

        wndclass.hIcon                        = LoadIcon (NULL, IDI_APPLICATION) ; 

织梦好,好织梦

        wndclass.hCursor                      = LoadCursor (NULL, IDC_ARROW) ; 

dedecms.com

        wndclass.hbrBackground                = (HBRUSH) GetStockObject (WHITE_BRUSH) ; copyright dedecms 
        wndclass.lpszMenuName                 = szAppName ; dedecms.com 
        wndclass.lpszClassName                = szAppName ; 内容来自dedecms 
  
织梦内容管理系统
        if (!RegisterClass (&wndclass)) 织梦好,好织梦 
        { 

织梦好,好织梦

                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"),  

copyright dedecms

                                                                     szAppName, MB_ICONERROR) ; 
copyright dedecms
                       return 0 ; 

织梦内容管理系统

        } copyright dedecms 
  

内容来自dedecms

        hwnd = CreateWindow (  szAppName, TEXT ("Enhanced Metafile Viewer"), 本文来自织梦 
                                      WS_OVERLAPPEDWINDOW, copyright dedecms 
                                      CW_USEDEFAULT, CW_USEDEFAULT, 

织梦好,好织梦

                                      CW_USEDEFAULT, CW_USEDEFAULT,  copyright dedecms 
                                      NULL, NULL, hInstance, NULL) ; 

本文来自织梦

  

织梦内容管理系统

        ShowWindow (hwnd, iCmdShow) ; 织梦内容管理系统 
        UpdateWindow (hwnd) ; 织梦好,好织梦 
  织梦好,好织梦 
        hAccel = LoadAccelerators (hInstance, szAppName) ; 
dedecms.com
        while (GetMessage (&msg, NULL, 0, 0)) copyright dedecms 
        { dedecms.com 
                       if (!TranslateAccelerator (hwnd, hAccel, &msg)) copyright dedecms 
                       { 内容来自dedecms 
                              TranslateMessage (&msg) ; 
本文来自织梦
                             DispatchMessage (&msg) ; 织梦内容管理系统 
                       } 织梦好,好织梦 
        } 
copyright dedecms
        return msg.wParam ; 

织梦好,好织梦

} 

copyright dedecms

  
copyright dedecms
HPALETTE CreatePaletteFromMetaFile (HENHMETAFILE hemf) 

织梦内容管理系统

{ 
copyright dedecms
        HPALETTE                       hPalette ; 织梦内容管理系统 
        int                                   iNum ; 

本文来自织梦

        LOGPALETTE *   plp ; dedecms.com 
  dedecms.com 
        if (!hemf) 织梦内容管理系统 
                               return NULL ; dedecms.com 
        if (0 == (iNum = GetEnhMetaFilePaletteEntries (hemf, 0, NULL))) 

织梦好,好织梦

                               return NULL ; 织梦内容管理系统 
        plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ; 内容来自dedecms 
        plp->palVersion    = 0x0300 ; 

copyright dedecms

        plp->palNumEntries = iNum ; copyright dedecms 
  copyright dedecms 
        GetEnhMetaFilePaletteEntries (hemf, iNum, plp->palPalEntry) ; 
copyright dedecms
        hPalette = CreatePalette (plp) ; 

织梦内容管理系统

        free (plp) ; dedecms.com 
        return hPalette ; 织梦内容管理系统 
} 内容来自dedecms 
  织梦好,好织梦 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) copyright dedecms 
{ 
dedecms.com
        static DOCINFO         di = { sizeof (DOCINFO), TEXT ("EmfView: Printing") } ; copyright dedecms 
        static HENHMETAFILE hemf ; 本文来自织梦 
        static OPENFILENAME ofn ; 本文来自织梦 
        static PRINTDLG                printdlg = { sizeof (PRINTDLG) } ; 内容来自dedecms 
        static TCHAR                          szFileName [MAX_PATH], szTitleName [MAX_PATH] ; 本文来自织梦 
        static TCHAR                          szFilter[] =  dedecms.com 
                                                                                            TEXT ("Enhanced Metafiles (*.EMF)\0*.emf\0") 内容来自dedecms 
                                                                                            TEXT ("All Files (*.*)\0*.*\0\0") ; dedecms.com 
        BOOL                                                         bSuccess ; dedecms.com 
        ENHMETAHEADER                         header ; 

织梦内容管理系统

        HDC                                                          hdc, hdcPrn ; 

织梦内容管理系统

        HENHMETAFILE                          hemfCopy ; 织梦好,好织梦 
        HMENU                                                        hMenu ; 
dedecms.com
        HPALETTE                                              hPalette ; copyright dedecms 
        int                                                          i, iLength, iEnable ; copyright dedecms 
        PAINTSTRUCT                                   ps ; copyright dedecms 
        RECT                                                         rect ; 

织梦好,好织梦

        PTSTR                                                        pBuffer ; 
copyright dedecms
  
dedecms.com
        switch (message) 内容来自dedecms 
        { 织梦内容管理系统 
        case WM_CREATE: 内容来自dedecms 
                               // Initialize OPENFILENAME structure 
dedecms.com
                               ofn.lStructSize                       = sizeof (OPENFILENAME) ; 内容来自dedecms 
                               ofn.hwndOwner                         = hwnd ; 本文来自织梦 
                               ofn.hInstance                         = NULL ; 

织梦内容管理系统

                               ofn.lpstrFilter                       = szFilter ; 
dedecms.com
                               ofn.lpstrCustomFilter              = NULL ; 
本文来自织梦
                               ofn.nMaxCustFilter                    = 0 ; 织梦好,好织梦 
                               ofn.nFilterIndex                      = 0 ; 内容来自dedecms 
                               ofn.lpstrFile                         = szFileName ; 
本文来自织梦
                               ofn.nMaxFile                          = MAX_PATH ; 

copyright dedecms

                               ofn.lpstrFileTitle                    = szTitleName ; 
内容来自dedecms
                               ofn.nMaxFileTitle                     = MAX_PATH ; copyright dedecms 
                               ofn.lpstrInitialDir                   = NULL ; dedecms.com 
                               ofn.lpstrTitle                        = NULL ; 
内容来自dedecms
                               ofn.Flags                             = 0 ;    织梦好,好织梦 
                               ofn.nFileOffset                       = 0 ; dedecms.com 
                               ofn.nFileExtension                    = 0 ; 织梦内容管理系统 
                               ofn.lpstrDefExt                       = TEXT ("emf") ; 
织梦内容管理系统
                               ofn.lCustData                         = 0 ; 本文来自织梦 
                               ofn.lpfnHook                          = NULL ; 
dedecms.com
                               ofn.lpTemplateName                    = NULL ; 

copyright dedecms

                              return 0 ; 内容来自dedecms 
  
本文来自织梦
       case    WM_INITMENUPOPUP: copyright dedecms 
                               hMenu = GetMenu (hwnd) ; copyright dedecms 
  
织梦好,好织梦
                               iEnable = hemf ? MF_ENABLED : MF_GRAYED ; 织梦内容管理系统 
  

内容来自dedecms

               EnableMenuItem (hMenu, IDM_FILE_SAVE_AS,              iEnable) ; 
copyright dedecms
               EnableMenuItem (hMenu, IDM_FILE_PRINT,                iEnable) ; 内容来自dedecms 
               EnableMenuItem (hMenu, IDM_FILE_PROPERTIES,           iEnable) ; 
本文来自织梦
               EnableMenuItem (hMenu, IDM_EDIT_CUT,                  iEnable) ; 织梦好,好织梦 
                       EnableMenuItem (hMenu, IDM_EDIT_COPY,                 iEnable) ; 

织梦好,好织梦

                       EnableMenuItem (hMenu, IDM_EDIT_DELETE,               iEnable) ; 织梦好,好织梦 
                       EnableMenuItem (hMenu, IDM_EDIT_PASTE, dedecms.com 
                       IsClipboardFormatAvailable (CF_ENHMETAFILE) ? 

织梦内容管理系统

                       MF_ENABLED : MF_GRAYED) ; 本文来自织梦 
                       return 0 ; dedecms.com 
  织梦内容管理系统 
        case    WM_COMMAND: 

内容来自dedecms

                       switch (LOWORD (wParam)) 织梦内容管理系统 
                                      { dedecms.com 
                               case    IDM_FILE_OPEN: 

本文来自织梦

                                      // Show the File Open dialog box 

本文来自织梦

  织梦好,好织梦 
                                              ofn.Flags = 0 ; 

织梦内容管理系统

      
dedecms.com
                                              if (!GetOpenFileName (&ofn)) 织梦内容管理系统 
                                                                     return 0 ; dedecms.com 
                
copyright dedecms
                                      // If there's an existing EMF, get rid of it. 织梦好,好织梦 
  本文来自织梦 
                                              if (hemf) dedecms.com 
                                              { 
织梦好,好织梦
                                                                     DeleteEnhMetaFile (hemf) ; 

织梦好,好织梦

                                                                     hemf = NULL ; 织梦好,好织梦 
                                              } 
copyright dedecms
                                                                     // Load the EMF into memory 
copyright dedecms
  

内容来自dedecms

                                      SetCursor (LoadCursor (NULL, IDC_WAIT)) ; dedecms.com 
                                      ShowCursor (TRUE) ; 织梦好,好织梦 
  织梦内容管理系统 
                                      hemf = GetEnhMetaFile (szFileName) ; copyright dedecms 
  
本文来自织梦
                                      ShowCursor (FALSE) ; 内容来自dedecms 
                                      SetCursor (LoadCursor (NULL, IDC_ARROW)) ; 织梦好,好织梦 
  织梦好,好织梦 
                       // Invalidate the client area for later update copyright dedecms 
  dedecms.com 
                                      InvalidateRect (hwnd, NULL, TRUE) ; 织梦好,好织梦 
  

织梦好,好织梦

                                      if (hemf == NULL) copyright dedecms 
                                      { 织梦好,好织梦 
                    MessageBox (      hwnd, TEXT ("Cannot load metafile"),  
本文来自织梦
                                      szAppName, MB_ICONEXCLAMATION | MB_OK) ; 内容来自dedecms 
                                      } 

织梦内容管理系统

                                      return 0 ; 织梦好,好织梦 
  织梦内容管理系统 
                       case    IDM_FILE_SAVE_AS: 
本文来自织梦
                                      if (!hemf) copyright dedecms 
                                                             return 0 ; 织梦内容管理系统 
  织梦内容管理系统 
                                                            // Show the File Save dialog box 

内容来自dedecms

  dedecms.com 
                                      ofn.Flags = OFN_OVERWRITEPROMPT ; 

本文来自织梦

      本文来自织梦 
                                      if (!GetSaveFileName (&ofn)) 

内容来自dedecms

                                                             return 0 ; 

织梦内容管理系统

                
dedecms.com
                                                             // Save the EMF to disk file 
copyright dedecms
  织梦内容管理系统 
                                      SetCursor (LoadCursor (NULL, IDC_WAIT)) ; 

内容来自dedecms

                                      ShowCursor (TRUE) ; dedecms.com 
  
内容来自dedecms
                                      hemfCopy = CopyEnhMetaFile (hemf, szFileName) ; 
dedecms.com
  dedecms.com 
                                      ShowCursor (FALSE) ; 
dedecms.com
                                      SetCursor (LoadCursor (NULL, IDC_ARROW)) ; 

织梦好,好织梦

                                      if (hemfCopy) 内容来自dedecms 
                                      { 
本文来自织梦
                                                             DeleteEnhMetaFile (hemf) ; 

copyright dedecms

                                                             hemf = hemfCopy ; 织梦好,好织梦 
                                      } 

本文来自织梦

                                      else 
copyright dedecms
                    MessageBox (      hwnd, TEXT ("Cannot save metafile"),  本文来自织梦 
                                      szAppName, MB_ICONEXCLAMATION | MB_OK) ; 

织梦好,好织梦

                                      return 0 ; 
内容来自dedecms
  

copyright dedecms

                       case    IDM_FILE_PRINT: 

织梦内容管理系统

                               // Show the Print dialog box and get printer DC dedecms.com 
  

织梦好,好织梦

               printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ; 
dedecms.com
  本文来自织梦 
                                      if (!PrintDlg (&printdlg)) 
织梦好,好织梦
                                                             return 0 ; copyright dedecms 
                copyright dedecms 
                                      if (NULL == (hdcPrn = printdlg.hDC))  

本文来自织梦

                                      { 
织梦好,好织梦
                   MessageBox (       hwnd, TEXT ("Cannot obtain printer DC"), 
copyright dedecms
                                szAppName, MB_ICONEXCLAMATION | MB_OK) ; 织梦好,好织梦 
                                                             return 0 ; dedecms.com 
                                      } 
本文来自织梦
                                                             // Get size of printable area of page 织梦好,好织梦 
  copyright dedecms 
                                      rect.left              = 0 ; 织梦内容管理系统 
                                      rect.right             = GetDeviceCaps (hdcPrn, HORZRES) ; copyright dedecms 
                                      rect.top               = 0 ; copyright dedecms 
                                      rect.bottom            = GetDeviceCaps (hdcPrn, VERTRES) ; 织梦内容管理系统 
  
内容来自dedecms
                                      bSuccess = FALSE ; 内容来自dedecms 
  织梦好,好织梦 
                                                             // Play the EMF to the printer copyright dedecms 
  
织梦好,好织梦
                                      SetCursor (LoadCursor (NULL, IDC_WAIT)) ; 

本文来自织梦

                                      ShowCursor (TRUE) ; 

内容来自dedecms

  copyright dedecms 
                                      if ((StartDoc (hdcPrn, &di) > 0) && (StartPage (hdcPrn) > 0)) 
内容来自dedecms
                               { 
copyright dedecms
                                                             PlayEnhMetaFile (hdcPrn, hemf, &rect) ; 
copyright dedecms
                     
内容来自dedecms
                                                     if (EndPage (hdcPrn) > 0) 

本文来自织梦

                                                     { 
织梦内容管理系统
                                                                            bSuccess = TRUE ; 
dedecms.com
                                                                            EndDoc (hdcPrn) ; 织梦好,好织梦 
                                                     } 
内容来自dedecms
                                      } copyright dedecms 
                                      ShowCursor (FALSE) ; 
copyright dedecms
                                      SetCursor (LoadCursor (NULL, IDC_ARROW)) ; 
copyright dedecms
  

织梦好,好织梦

                                      DeleteDC (hdcPrn) ; 内容来自dedecms 
  织梦好,好织梦 
                                      if (!bSuccess) 

本文来自织梦

                MessageBox (   hwnd, TEXT ("Could not print metafile"), 
织梦好,好织梦
                                        szAppName, MB_ICONEXCLAMATION | MB_OK) ; 
织梦好,好织梦
                                      return 0 ; 
内容来自dedecms
  

copyright dedecms

                       case    IDM_FILE_PROPERTIES: 织梦内容管理系统 
                                      if (!hemf) 织梦好,好织梦 
                                                             return 0 ; 本文来自织梦 
  织梦好,好织梦 
                                      iLength = GetEnhMetaFileDescription (hemf, 0, NULL) ; 
本文来自织梦
                                      pBuffer = malloc ((iLength + 256) * sizeof (TCHAR)) ; 织梦内容管理系统 
  

织梦好,好织梦

                                      GetEnhMetaFileHeader (hemf, sizeof (ENHMETAHEADER), &header) ; 内容来自dedecms 
  
织梦好,好织梦
                                                     // Format header file information  本文来自织梦 
  

织梦内容管理系统

                                      i  = wsprintf (pBuffer,  

本文来自织梦

                                                                            TEXT ("Bounds = (%i, %i) to (%i, %i) pixels\n"), 内容来自dedecms 
                                                                             header.rclBounds.left, header.rclBounds.top, 

dedecms.com

                                                                             header.rclBounds.right, header.rclBounds.bottom) ; 
dedecms.com
  

织梦内容管理系统

                                      i += wsprintf (pBuffer + i,  本文来自织梦 
                                                                            TEXT ("Frame = (%i, %i) to (%i, %i) mms\n"), 
织梦好,好织梦
                                                                             header.rclFrame.left, header.rclFrame.top, 

dedecms.com

                                                                             header.rclFrame.right, header.rclFrame.bottom) ; dedecms.com 
  织梦好,好织梦 
                                      i += wsprintf (pBuffer + i, 
copyright dedecms
                                                                            TEXT ("Resolution = (%i, %i) pixels") 
本文来自织梦
                                                                            TEXT (" = (%i, %i) mms\n"), 本文来自织梦 
                                                                             header.szlDevice.cx, header.szlDevice.cy, copyright dedecms 
                                                                             header.szlMillimeters.cx,  内容来自dedecms 
                                                                             header.szlMillimeters.cy) ; 织梦好,好织梦 
  

织梦内容管理系统

                                      i += wsprintf (pBuffer + i, 
织梦内容管理系统
                                                                            TEXT ("Size = %i, Records = %i, ") 
织梦内容管理系统
                                                                            TEXT ("Handles = %i, Palette entries = %i\n"), 

本文来自织梦

                                                                            header.nBytes, header.nRecords, 内容来自dedecms 
                                                                            header.nHandles, header.nPalEntries) ; 

织梦内容管理系统

                                                                     // Include the metafile description, if present 

本文来自织梦

  
本文来自织梦
                                      if (iLength) 织梦内容管理系统 
                                      { 
dedecms.com
                                                                     i += wsprintf (pBuffer + i, TEXT ("Description = ")) ; 
织梦内容管理系统
                                                                     GetEnhMetaFileDescription (hemf, iLength, pBuffer + i) ; 本文来自织梦 
                                                                     pBuffer [lstrlen (pBuffer)] = '\t' ; 
织梦好,好织梦
                                      } 织梦内容管理系统 
  织梦内容管理系统 
                                      MessageBox (hwnd, pBuffer, TEXT ("Metafile Properties"), MB_OK) ; 
dedecms.com
                                      free (pBuffer) ;                               本文来自织梦 
                                      return 0 ; 内容来自dedecms 
  dedecms.com 
                       case    IDM_EDIT_COPY: 织梦内容管理系统 
                       case    IDM_EDIT_CUT: 织梦内容管理系统 
                                      if (!hemf) 
织梦内容管理系统
                                                             return 0 ; 织梦好,好织梦 
  dedecms.com 
                                                             // Transfer metafile copy to the clipboard 
copyright dedecms
  
本文来自织梦
                                      hemfCopy = CopyEnhMetaFile (hemf, NULL) ; 
织梦好,好织梦
  织梦内容管理系统 
                                      OpenClipboard (hwnd) ; 

本文来自织梦

                                      EmptyClipboard () ; 本文来自织梦 
                                      SetClipboardData (CF_ENHMETAFILE, hemfCopy) ; 

织梦内容管理系统

                                      CloseClipboard () ; 

内容来自dedecms

  
copyright dedecms
                                      if (LOWORD (wParam) == IDM_EDIT_COPY) 内容来自dedecms 
                                                             return 0 ; 

本文来自织梦

                                                     // fall through if IDM_EDIT_CUT  copyright dedecms 
                       case    IDM_EDIT_DELETE: 

本文来自织梦

                                      if (hemf) 
dedecms.com
                                      { 
内容来自dedecms
                                                     DeleteEnhMetaFile (hemf) ; 
copyright dedecms
                                                     hemf = NULL ; 本文来自织梦 
                                                     InvalidateRect (hwnd, NULL, TRUE) ; 本文来自织梦 
                                      } 织梦好,好织梦 
                                      return 0 ; 本文来自织梦 
  织梦内容管理系统 
               case    IDM_EDIT_PASTE: 
copyright dedecms
                                      OpenClipboard (hwnd) ; dedecms.com 
                                      hemfCopy = GetClipboardData (CF_ENHMETAFILE) ; 
内容来自dedecms
  织梦内容管理系统 
                                      CloseClipboard () ; 

织梦好,好织梦

                                      if (hemfCopy && hemf) 内容来自dedecms 
                                      { dedecms.com 
                                                     DeleteEnhMetaFile (hemf) ; 

内容来自dedecms

                                                     hemf = NULL ; 

内容来自dedecms

                                      } 

内容来自dedecms

  

本文来自织梦

                                      hemf = CopyEnhMetaFile (hemfCopy, NULL) ; dedecms.com 
                                      InvalidateRect (hwnd, NULL, TRUE) ; 内容来自dedecms 
                                      return 0 ; 

本文来自织梦

  

本文来自织梦

               case    IDM_APP_ABOUT: 
内容来自dedecms
                                      MessageBox (   hwnd,   TEXT ("Enhanced Metafile Viewer\n") 
织梦好,好织梦
                            TEXT ("(c) Charles Petzold, 1998"), dedecms.com 
                                                                                             szAppName, MB_OK) ; 
copyright dedecms
                                      return 0 ; 

织梦内容管理系统

  

织梦内容管理系统

               case    IDM_APP_EXIT: 织梦好,好织梦 
                                      SendMessage (hwnd, WM_CLOSE, 0, 0L) ; 
织梦好,好织梦
                                      return 0 ; copyright dedecms 
                       } 织梦内容管理系统 
                       break ; 内容来自dedecms 
          
copyright dedecms
        case    WM_PAINT: 织梦内容管理系统 
                               hdc = BeginPaint (hwnd, &ps) ; copyright dedecms 
  
copyright dedecms
                               if (hemf) 本文来自织梦 
                               { 本文来自织梦 
                                      if (    hPalette = CreatePaletteFromMetaFile (hemf)) 
本文来自织梦
                                      { copyright dedecms 
                                                             SelectPalette (hdc, hPalette, FALSE) ; 
copyright dedecms
                                                             RealizePalette (hdc) ; 
copyright dedecms
                                      } 

本文来自织梦

                                      GetClientRect (hwnd, &rect) ; 
本文来自织梦
                                      PlayEnhMetaFile (hdc, hemf, &rect) ; 

织梦内容管理系统

  

dedecms.com

                                      if (hPalette) 织梦内容管理系统 
                                                             DeleteObject (hPalette) ; 

织梦内容管理系统

                               } 本文来自织梦 
                               EndPaint (hwnd, &ps) ; 内容来自dedecms 
                               return 0 ; dedecms.com 
  copyright dedecms 
        case    WM_QUERYNEWPALETTE: 
本文来自织梦
                               if (!hemf || !(hPalette = CreatePaletteFromMetaFile (hemf))) dedecms.com 
                                              return FALSE ; 

内容来自dedecms

  织梦内容管理系统 
                               hdc = GetDC (hwnd) ; 织梦好,好织梦 
                               SelectPalette (hdc, hPalette, FALSE) ; 

copyright dedecms

                               RealizePalette (hdc) ; 内容来自dedecms 
                               InvalidateRect (hwnd, NULL, FALSE) ; 织梦内容管理系统 
           织梦内容管理系统 
                               DeleteObject (hPalette) ; 
本文来自织梦
                               ReleaseDC (hwnd, hdc) ; 内容来自dedecms 
                               return TRUE ; 

织梦好,好织梦

  

copyright dedecms

        case    WM_PALETTECHANGED: 内容来自dedecms 
                               if ((HWND) wParam == hwnd) 

copyright dedecms

                                              break ; 

copyright dedecms

  

织梦好,好织梦

                               if (!hemf || !(hPalette = CreatePaletteFromMetaFile (hemf))) 织梦内容管理系统 
                                              break ; 本文来自织梦 
  dedecms.com 
                               hdc = GetDC (hwnd) ; 
织梦内容管理系统
                               SelectPalette (hdc, hPalette, FALSE) ; 织梦好,好织梦 
                               RealizePalette (hdc) ; 内容来自dedecms 
                               UpdateColors (hdc) ; 内容来自dedecms 
           

织梦好,好织梦

                               DeleteObject (hPalette) ; dedecms.com 
                               ReleaseDC (hwnd, hdc) ; 
本文来自织梦
                               break ; 织梦内容管理系统 
           

织梦内容管理系统

        case    WM_DESTROY: 内容来自dedecms 
                               if (hemf) 
内容来自dedecms
                                              DeleteEnhMetaFile (hemf) ; 本文来自织梦 
  

织梦好,好织梦

                               PostQuitMessage (0) ; 内容来自dedecms 
                               return 0 ; 

织梦内容管理系统

        } 

织梦好,好织梦

        return DefWindowProc (hwnd, message, wParam, lParam) ; 

dedecms.com

} 
内容来自dedecms
 EMFVIEW.RC (摘录) 

内容来自dedecms

//Microsoft Developer Studio generated resource script. 
内容来自dedecms
#include "resource.h" 
织梦内容管理系统
#include "afxres.h" 
织梦内容管理系统
  织梦内容管理系统 
///////////////////////////////////////////////////////////////////////////// 

copyright dedecms

// Menu 织梦内容管理系统 
EMFVIEW MENU DISCARDABLE  本文来自织梦 
BEGIN copyright dedecms 
        POPUP "&File" dedecms.com 
        BEGIN 
dedecms.com
        MENUITEM "&Open\tCtrl+O",  IDM_FILE_OPEN 织梦好,好织梦 
        MENUITEM "Save &As...",    IDM_FILE_SAVE_AS 

dedecms.com

               MENUITEM SEPARATOR 
dedecms.com
               MENUITEM "&Print...\tCtrl+P",IDM_FILE_PRINT 
内容来自dedecms
        MENUITEM SEPARATOR 织梦好,好织梦 
               MENUITEM "&Properties",         IDM_FILE_PROPERTIES copyright dedecms 
               MENUITEM SEPARATOR 
copyright dedecms
               MENUITEM "E&xit",               IDM_APP_EXIT 内容来自dedecms 
END 

dedecms.com

        POPUP "&Edit" 织梦内容管理系统 
        BEGIN 
织梦内容管理系统
        MENUITEM "Cu&t\tCtrl+X",                             IDM_EDIT_CUT 织梦内容管理系统 
        MENUITEM "&Copy\tCtrl+C",                    IDM_EDIT_COPY copyright dedecms 
               MENUITEM "&Paste\tCtrl+V",            IDM_EDIT_PASTE 

织梦内容管理系统

        MENUITEM "&Delete\tDel",                     IDM_EDIT_DELETE 

copyright dedecms

        END dedecms.com 
        POPUP "Help" 本文来自织梦 
        BEGIN 本文来自织梦 
        MENUITEM "&About EmfView...",                 IDM_APP_ABOUT copyright dedecms 
        END 

织梦好,好织梦

END 
织梦好,好织梦
  内容来自dedecms 
///////////////////////////////////////////////////////////////////////////// 

内容来自dedecms

// Accelerator 
织梦好,好织梦
EMFVIEW ACCELERATORS DISCARDABLE  织梦内容管理系统 
BEGIN 织梦好,好织梦 
"C",IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT 
织梦内容管理系统
"O",IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT 
织梦内容管理系统
"P",IDM_FILE_PRINT,VIRTKEY, CONTROL, NOINVERT 

织梦好,好织梦

"V",IDM_EDIT_PASTE,VIRTKEY, CONTROL, NOINVERT copyright dedecms 
VK_DELETE,IDM_EDIT_DELETE,VIRTKEY, NOINVERT dedecms.com 
"X",IDM_EDIT_CUT,VIRTKEY, CONTROL, NOINVERT 
织梦内容管理系统
END 
本文来自织梦
 RESOURCE.H (摘录) 
dedecms.com
// Microsoft Developer Studio generated include file. 织梦内容管理系统 
// Used by EmfView.rc 
内容来自dedecms
  

织梦内容管理系统

#define                IDM_FILE_OPEN             40001 

本文来自织梦

#define                IDM_FILE_SAVE_AS          40002 本文来自织梦 
#define                IDM_FILE_PRINT            40003 
织梦好,好织梦
#define                IDM_FILE_PROPERTIES       40004 

织梦内容管理系统

#define                IDM_APP_EXIT              40005 

dedecms.com

#define                IDM_EDIT_CUT              40006 

织梦好,好织梦

#define                IDM_EDIT_COPY             40007 织梦好,好织梦 
#define                IDM_EDIT_PASTE            40008 dedecms.com 
#define                IDM_EDIT_DELETE           40009 

织梦好,好织梦

#define                IDM_APP_ABOUT             40010 织梦内容管理系统 

EMFVIEW也支援完整的调色盘处理,以便支援有调色盘编码资讯的metafile。(透过呼叫Selectpalette来进行)。该程式在CreatePaletteFromMetaFile函式中处理调色盘,在处理WM_PAINT显示metafile以及处理WM_QUERYNEWPALETTEWM_PALETTECHANGED讯息时,呼叫这个函式。

内容来自dedecms

在回应功能表中的「Print」命令时,EMFVIEW显示普通的印表机对话方块,然後取得页面中可列印区域的大小。Metafile被缩放成适当尺寸以填入整个区域。EMFVIEW在视窗中以类似方式显示metafile

dedecms.com

File」功能表中的「Properties」项使EMFVIEW显示包含metafile表头资讯的讯息方块。 织梦好,好织梦

如果列印本章前面建立的EMF2.EMFmetafile图像,您将会发现用高解析度的印表机列印出的线条非常细,几乎看不清楚线条的锯齿。列印向量图像时应该使用较宽的画笔(例如,一点宽)。本章後面所示的直尺图像就是这样做的。 内容来自dedecms

显示精确的metafile图像
  copyright dedecms

Metafile图像的好处在於它能够以任意大小缩放并且仍能保持一定的逼真度。这是因为metafile通常由一系列向量图形的基本图形组成,基本图形是指线条、填入的区域以及轮廓字体等等。扩大或缩小图像只是简单地缩放定义这些基本图形的所有座标点。另一方面,对点阵图来说,压缩图像会遗漏整行列的图素,因而失去重要的显示资讯。

内容来自dedecms

当然,metafile的压缩并不是完美无缺的。我们所使用的图形输出设备的图素大小是有限的。当metafile图像压缩到一定大小时,组成metafile的大量线条会变成模糊的斑点,同时区域填入图案和混色看起来也很奇怪。如果metafile中包含嵌入的点阵图或旧的点阵字体,同样会引起类似的问题。

dedecms.com

尽管如此,大多数情况下metafile可以任意地缩放。这在把metafile放入文书处理或桌上印刷文件内时非常有用。一般来说,在上述的应用程式中选择metafile图像时,会出现围绕图像的矩形,您可以用滑鼠拖动该矩形,将它缩放为任意大小。图像送到印表机时,它也具有同样对应的大小。 内容来自dedecms

然而,有时任意缩放metafile并不是个好主意。例如:假设您有一个储存著存款客户签名样本的银行系统,这些签名以一系列折线的方式储存在metafile中。将metafile变宽或变高会使签名变形,因此应该保持图像的纵横比一致。

织梦内容管理系统

在前面的范例程式中,是以显示区域的大小来确定PlayEnhMetaFile呼叫使用的围绕矩形范围。所以,如果改变程式表单的大小,也就改变了图像的大小。这与在文书处理文件中改变metafile图像大小的概念相似。 内容来自dedecms

正确地显示metafile图像(以特定的度量单位或用适当的纵横比),需要使用metafile表头中的大小资讯并根据此资讯设定矩形结构。

织梦好,好织梦

在本章剩下的范例程式中将使用名为EMF.C的程式架构,它包括列印处理的程式码、资源描述档EMF.RC和表头档案RESOURCE.H。程式18-10显示了这些档案以及EMF8.C程式,该程式使用这些档案显示一把6英寸的直尺。 内容来自dedecms

 程式18-10  EMF8 

内容来自dedecms

EMF8.C 

本文来自织梦

/*--------------------------------------------------------------------------- copyright dedecms 
        EMF8.C -- Enhanced Metafile Demo #8 
本文来自织梦
                                              (c) Charles Petzold, 1998 织梦好,好织梦 
-----------------------------------------------------------------------------*/ 织梦好,好织梦 
  dedecms.com 
#include <windows.h> 织梦内容管理系统 
TCHAR szClass          [] = TEXT ("EMF8") ; 
dedecms.com
TCHAR szTitle          [] = TEXT ("EMF8: Enhanced Metafile Demo #8") ; 
dedecms.com
  

织梦内容管理系统

void DrawRuler (HDC hdc, int cx, int cy) 织梦内容管理系统 
{ 

copyright dedecms

        int                            iAdj, i, iHeight ; 本文来自织梦 
        LOGFONT                lf ; 

本文来自织梦

        TCHAR                          ch ; 
织梦内容管理系统
  织梦内容管理系统 
        iAdj = GetVersion () & 0x80000000 ? 0 : 1 ; 
dedecms.com
                                      // Black pen with 1-point width 
织梦好,好织梦
        SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ; 织梦内容管理系统 
                                      // Rectangle surrounding entire pen (with adjustment) 
本文来自织梦
        Rectangle (hdc, iAdj, iAdj, cx + iAdj + 1, cy + iAdj + 1) ; 内容来自dedecms 
                                      // Tick marks 

copyright dedecms

        for (i = 1 ; i < 96 ; i++) 内容来自dedecms 
        { 
内容来自dedecms
                               if (i % 16 == 0) iHeight = cy /  2 ;          // inches 
本文来自织梦
               else    if (i %  8 == 0) iHeight = cy /  3 ;          // half inches 织梦内容管理系统 
               else    if (i %  4 == 0) iHeight = cy /  5 ;          // quarter inches dedecms.com 
               else    if (i %  2 == 0) iHeight = cy /  8 ;          // eighths 
织梦内容管理系统
               else                  iHeight = cy / 12 ;             // sixteenths 织梦内容管理系统 
  copyright dedecms 
                       MoveToEx (hdc, i * cx / 96, cy, NULL) ; 

本文来自织梦

                       LineTo   (hdc, i * cx / 96, cy - iHeight) ; 
copyright dedecms
        } 

copyright dedecms

                                      // Create logical font  

织梦内容管理系统

        FillMemory (&lf, sizeof (lf), 0) ; 内容来自dedecms 
        lf.lfHeight = cy / 2 ; dedecms.com 
        lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ; 

copyright dedecms

  织梦好,好织梦 
        SelectObject   (hdc, CreateFontIndirect (&lf)) ; 
dedecms.com
        SetTextAlign   (hdc, TA_BOTTOM | TA_CENTER) ; copyright dedecms 
        SetBkMode              (hdc, TRANSPARENT) ; 

copyright dedecms

  织梦内容管理系统 
                                      // Display numbers 
本文来自织梦
  
内容来自dedecms
        for (i = 1 ; i <= 5 ; i++) copyright dedecms 
        { 

本文来自织梦

                               ch = (TCHAR) (i + '0') ; 内容来自dedecms 
                               TextOut (hdc, i * cx / 6, cy / 2, &ch, 1) ; 织梦好,好织梦 
        } copyright dedecms 
                                      // Clean up 
织梦好,好织梦
        DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ; 

copyright dedecms

        DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; 
织梦内容管理系统
} 

织梦好,好织梦

  织梦内容管理系统 
void CreateRoutine (HWND hwnd) 

织梦内容管理系统

{ 织梦内容管理系统 
        HDC                                   hdcEMF ; 

织梦内容管理系统

        HENHMETAFILE hemf ; 

织梦内容管理系统

        int                                   cxMms, cyMms, cxPix, cyPix, xDpi, yDpi ; 
织梦好,好织梦
  dedecms.com 
        hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf8.emf"), NULL, 织梦好,好织梦 
                                      TEXT ("EMF8\0EMF Demo #8\0")) ; 

本文来自织梦

        if (hdcEMF == NULL) dedecms.com 
                               return ; copyright dedecms 
        cxMms          = GetDeviceCaps (hdcEMF, HORZSIZE) ; copyright dedecms 
        cyMms          = GetDeviceCaps (hdcEMF, VERTSIZE) ; copyright dedecms 
        cxPix          = GetDeviceCaps (hdcEMF, HORZRES) ; 织梦内容管理系统 
        cyPix          = GetDeviceCaps (hdcEMF, VERTRES) ; 

copyright dedecms

  copyright dedecms 
        xDpi           = cxPix * 254 / cxMms / 10 ; 

内容来自dedecms

        yDpi           = cyPix * 254 / cyMms / 10 ; 内容来自dedecms 
  织梦内容管理系统 
        DrawRuler (hdcEMF, 6 * xDpi, yDpi) ; 织梦好,好织梦 
        hemf = CloseEnhMetaFile (hdcEMF) ; dedecms.com 
        DeleteEnhMetaFile (hemf) ; 

织梦好,好织梦

} dedecms.com 
  copyright dedecms 
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) 
织梦内容管理系统
{ 

copyright dedecms

        ENHMETAHEADER          emh ; dedecms.com 
        HENHMETAFILE           hemf ; 

织梦好,好织梦

        int                                           cxImage, cyImage ; copyright dedecms 
        RECT                                          rect ; 
织梦好,好织梦
  织梦内容管理系统 
        hemf = GetEnhMetaFile (TEXT ("emf8.emf")) ; 
dedecms.com
        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; 织梦内容管理系统 
        cxImage = emh.rclBounds.right - emh.rclBounds.left ; 织梦好,好织梦 
        cyImage = emh.rclBounds.bottom - emh.rclBounds.top ; copyright dedecms 
  

织梦好,好织梦

        rect.left              = (cxArea - cxImage) / 2 ; copyright dedecms 
        rect.right             = (cxArea + cxImage) / 2 ; 内容来自dedecms 
        rect.top               = (cyArea - cyImage) / 2 ; 

dedecms.com

        rect.bottom            = (cyArea + cyImage) / 2 ; 
本文来自织梦
  
织梦内容管理系统
        PlayEnhMetaFile (hdc, hemf, &rect) ; copyright dedecms 
        DeleteEnhMetaFile (hemf) ; 本文来自织梦 
} copyright dedecms 
 EMF.C 本文来自织梦 
/*---------------------------------------------------------------------------- copyright dedecms 
        EMF.C --       Enhanced Metafile Demonstration Shell Program 织梦内容管理系统 
                                              (c) Charles Petzold, 1998 内容来自dedecms 
-----------------------------------------------------------------------------*/ 

dedecms.com

  内容来自dedecms 
#include <windows.h> 织梦好,好织梦 
#include <commdlg.h> 

dedecms.com

#include "..\\emf8\\resource.h" 本文来自织梦 
  
本文来自织梦
extern void CreateRoutine (HWND) ; 

本文来自织梦

extern void PaintRoutine  (HWND, HDC, int, int) ; dedecms.com 
  
织梦内容管理系统
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 内容来自dedecms 
HANDLE hInst ; 
dedecms.com
extern TCHAR szClass [] ; 内容来自dedecms 
extern TCHAR szTitle [] ; 织梦内容管理系统 
  copyright dedecms 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 织梦内容管理系统 
                                                                     PSTR szCmdLine, int iCmdShow) copyright dedecms 
{ 本文来自织梦 
        TCHAR                                 szResource [] = TEXT ("EMF") ; 
内容来自dedecms
        HWND                                  hwnd ; 
本文来自织梦
        MSG                                   msg ; 内容来自dedecms 
        WNDCLASS                       wndclass ; 
本文来自织梦
  dedecms.com 
        hInst = hInstance ; 

本文来自织梦

        wndclass.style                                = CS_HREDRAW | CS_VREDRAW ; copyright dedecms 
        wndclass.lpfnWndProc                          = WndProc ; dedecms.com 
        wndclass.cbClsExtra                           = 0 ; 

织梦内容管理系统

        wndclass.cbWndExtra                           = 0 ; copyright dedecms 
        wndclass.hInstance                            = hInstance ; 
copyright dedecms
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; copyright dedecms 
        wndclass.hCursor                              = LoadCursor (NULL, IDC_ARROW) ; 织梦内容管理系统 
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; dedecms.com 
        wndclass.lpszMenuName                 = szResource ; 
内容来自dedecms
        wndclass.lpszClassName                = szClass ; dedecms.com 
      本文来自织梦 
        if (!RegisterClass (&wndclass)) 

copyright dedecms

        { copyright dedecms 
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"), copyright dedecms 
                                                                     szClass, MB_ICONERROR) ; 
dedecms.com
                       return 0 ; 本文来自织梦 
        } 内容来自dedecms 
      
copyright dedecms
        hwnd = CreateWindow (  szClass, szTitle, 
copyright dedecms
                         WS_OVERLAPPEDWINDOW, dedecms.com 
                         CW_USEDEFAULT, CW_USEDEFAULT, copyright dedecms 
                         CW_USEDEFAULT, CW_USEDEFAULT, 内容来自dedecms 
                         NULL, NULL, hInstance, NULL) ; 

dedecms.com

  

dedecms.com

        ShowWindow (hwnd, iCmdShow) ; dedecms.com 
        UpdateWindow (hwnd) ; 内容来自dedecms 
  织梦好,好织梦 
        while (GetMessage (&msg, NULL, 0, 0)) 

copyright dedecms

        { 
dedecms.com
                       TranslateMessage (&msg) ; dedecms.com 
                       DispatchMessage (&msg) ; copyright dedecms 
        } 

本文来自织梦

        return msg.wParam ; 
copyright dedecms
} 
本文来自织梦
  

dedecms.com

BOOL PrintRoutine (HWND hwnd) dedecms.com 
{ 织梦内容管理系统 
        static DOCINFO                 di ; copyright dedecms 
        static PRINTDLG                printdlg = { sizeof (PRINTDLG) } ; 

dedecms.com

        static TCHAR                          szMessage [32] ; dedecms.com 
        BOOL                                                         bSuccess = FALSE ; 织梦好,好织梦 
        HDC                                                          hdcPrn ; 织梦好,好织梦 
        int                                                          cxPage, cyPage ; 织梦好,好织梦 
  
织梦好,好织梦
        printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ; 

织梦内容管理系统

        if (!PrintDlg (&printdlg)) 织梦内容管理系统 
                               return TRUE ; 
dedecms.com
        if (NULL == (hdcPrn = printdlg.hDC)) 
dedecms.com
                               return FALSE ; 本文来自织梦 
        cxPage = GetDeviceCaps (hdcPrn, HORZRES) ; 
织梦内容管理系统
        cyPage = GetDeviceCaps (hdcPrn, VERTRES) ; dedecms.com 
  
本文来自织梦
        lstrcpy (szMessage, szClass) ; dedecms.com 
        lstrcat (szMessage, TEXT (": Printing")) ; 

本文来自织梦

  

copyright dedecms

        di.cbSize                      = sizeof (DOCINFO) ; 
dedecms.com
        di.lpszDocName         = szMessage ; dedecms.com 
  本文来自织梦 
        if (StartDoc (hdcPrn, &di) > 0) 本文来自织梦 
        { 织梦内容管理系统 
                       if (StartPage (hdcPrn) > 0) 
内容来自dedecms
                       { 内容来自dedecms 
                               PaintRoutine (hwnd, hdcPrn, cxPage, cyPage) ; copyright dedecms 
                               if (EndPage (hdcPrn) > 0) 织梦好,好织梦 
                               { 本文来自织梦 
                                                     EndDoc (hdcPrn) ; 

织梦好,好织梦

                                                     bSuccess = TRUE ; 内容来自dedecms 
                               } 本文来自织梦 
                       } copyright dedecms 
        } copyright dedecms 
        DeleteDC (hdcPrn) ; 

织梦内容管理系统

        return bSuccess ; 

织梦内容管理系统

} 织梦内容管理系统 
  本文来自织梦 
LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) dedecms.com 
{ 
本文来自织梦
        BOOL                                  bSuccess ; 

织梦内容管理系统

        static int             cxClient, cyClient ; 
内容来自dedecms
        HDC                                   hdc ; copyright dedecms 
        PAINTSTRUCT            ps ; 
织梦好,好织梦
      

本文来自织梦

        switch (message) copyright dedecms 
        { copyright dedecms 
        case    WM_CREATE: dedecms.com 
                               CreateRoutine (hwnd) ; 织梦好,好织梦 
                               return 0 ; 

本文来自织梦

           dedecms.com 
        case    WM_COMMAND: 本文来自织梦 
                               switch (wParam) 

织梦内容管理系统

                               { 内容来自dedecms 
                               case    IDM_PRINT: copyright dedecms 
                                              SetCursor (LoadCursor (NULL, IDC_WAIT)) ; 织梦内容管理系统 
                                              ShowCursor (TRUE) ; 织梦好,好织梦 
                

dedecms.com

                                              bSuccess = PrintRoutine (hwnd) ; dedecms.com 
                
本文来自织梦
                                              ShowCursor (FALSE) ; copyright dedecms 
                                              SetCursor (LoadCursor (NULL, IDC_ARROW)) ; 
织梦内容管理系统
                
本文来自织梦
                                              if (!bSuccess) 

内容来自dedecms

           MessageBox (hwnd, TEXT ("Error encountered during printing"), 
内容来自dedecms
                       szClass, MB_ICONASTERISK | MB_OK) ; dedecms.com 
                          return 0 ; 
copyright dedecms
                本文来自织梦 
                               case    IDM_EXIT: 

本文来自织梦

                                              SendMessage (hwnd, WM_CLOSE, 0, 0) ; 

织梦内容管理系统

                                              return 0 ; 

内容来自dedecms

                copyright dedecms 
                               case    IDM_ABOUT: 织梦内容管理系统 
           MessageBox (hwnd, TEXT ("Enhanced Metafile Demo Program\n") 

dedecms.com

                       TEXT ("Copyright (c) Charles Petzold, 1998"), 

内容来自dedecms

                       szClass, MB_ICONINFORMATION | MB_OK) ; dedecms.com 
                          return 0 ; 
本文来自织梦
                               } dedecms.com 
                               break ; 
copyright dedecms
           
本文来自织梦
        case    WM_SIZE: 

织梦内容管理系统

                               cxClient = LOWORD (lParam) ; 
copyright dedecms
                               cyClient = HIWORD (lParam) ; 
本文来自织梦
                               return 0 ; 

dedecms.com

           织梦内容管理系统 
        case    WM_PAINT: 织梦好,好织梦 
                               hdc = BeginPaint (hwnd, &ps) ; 
织梦好,好织梦
           
copyright dedecms
                               PaintRoutine (hwnd, hdc, cxClient, cyClient) ; 

织梦内容管理系统

           

本文来自织梦

                               EndPaint (hwnd, &ps) ; 

织梦好,好织梦

                               return 0 ; 

织梦内容管理系统

           

织梦内容管理系统

        case    WM_DESTROY : 

织梦内容管理系统

                               PostQuitMessage (0) ; 本文来自织梦 
                               return 0 ; 织梦好,好织梦 
        } 内容来自dedecms 
        return DefWindowProc (hwnd, message, wParam, lParam) ; dedecms.com 
} copyright dedecms 
 EMF.RC (摘录) 

本文来自织梦

//Microsoft Developer Studio generated resource script. 内容来自dedecms 
#include "resource.h" 
dedecms.com
#include "afxres.h" 

copyright dedecms

  copyright dedecms 
///////////////////////////////////////////////////////////////////////////// 内容来自dedecms 
// Menu 内容来自dedecms 
EMF MENU DISCARDABLE  

内容来自dedecms

BEGIN 织梦内容管理系统 
        POPUP "&File" 
本文来自织梦
        BEGIN 
本文来自织梦
                               MENUITEM "&Print...",                                 IDM_PRINT 本文来自织梦 
                      MENUITEM SEPARATOR 织梦内容管理系统 
                               MENUITEM "E&xit",                                            IDM_EXIT 本文来自织梦 
        END 
织梦好,好织梦
        POPUP "&Help" 
织梦内容管理系统
        BEGIN 本文来自织梦 
                               MENUITEM "&About...",                                         IDM_ABOUT 
copyright dedecms
        END 
织梦内容管理系统
END 织梦内容管理系统 
 RESOURCE.H (摘录) 

dedecms.com

// Microsoft Developer Studio generated include file. 
内容来自dedecms
// Used by Emf.rc 
织梦好,好织梦
// 
织梦好,好织梦
#define IDM_PRINT                40001 copyright dedecms 
#define IDM_EXIT                 40002 织梦好,好织梦 
#define IDM_ABOUT                40003 

织梦好,好织梦

在处理WM_CREATE讯息处理期间,EMF.C呼叫名为CreateRoutine的外部函式,该函式建立metafileEMF.C在两个地方呼叫PaintRoutine函式:一处在WM_PAINT讯息处理期间,另一处在函式PrintRoutine中以回应功能表命令列印图像。 copyright dedecms

因为现代的印表机通常比视讯显示器有更高的解析度,列印metafile的能力是测试以特定大小处理图像能力的重要工具。当EMF8建立的metafile图像以特定大小显示时,最有意义。该图像是一把6英寸长1英寸宽的直尺,每英寸分为十六格,数字从15TrueType字体。

copyright dedecms

要绘制一把6英寸的直尺,需要知道一些设备解析度的知识。EMF8.C中的CreateRoutine函式首先建立metafile,然後使用从CreateEnhMetaFile传回的装置内容代号呼叫GetDeviceCaps四次。这些呼叫取得单位分别为毫米和图素的显示平面的高度与宽度。 内容来自dedecms

这听起来有点怪。Metafile装置内容通常是作为GDI绘制命令的储存媒介,它不是像视讯显示器或印表机的真正设备,那么它的宽度和高度从何而来?

织梦内容管理系统

您可能已经想起来了,CreateEnhMetaFile的第一个参数被称作「参考装置内容」。GDI用这为metafile建立设备特徵。如果参数设定为NULL(如EMF8中),GDI就把显示器作为参考装置内容。因而,当EMF8使用装置内容呼叫GetDeviceCaps时,它实际上取得有关显示器的资讯。

织梦好,好织梦

EMF8.C以图素大小除以毫米大小并乘以25.41英寸为25.4毫米)计算以每英寸的点数为单位的解析度。 copyright dedecms

即使我们非常认真地以metafile直尺的正确大小绘制它,但是这样子作还是不够的。PlayEnhMetaFile函式在显示图像时,使用作为最後一个参数传递给它的矩形来缩放图像大小,因此该矩形必须设定为直尺的大小。 织梦内容管理系统

由於此原因,EMF8中的PaintRoutine函式呼叫GetEnhMetaFileHeader函式来取得metafile的表头资讯。ENHMETAHEADER结构的rclBounds栏位指出以图素为单位的metafile图像的围绕矩形。程式使用此资讯使直尺位於显示区域中央,如图18-6所示。 内容来自dedecms


  本文来自织梦

内容来自dedecms

  织梦内容管理系统

18-6 EMF8得萤幕显示

本文来自织梦

 

记住,如果您拿直尺与萤幕中的直尺比较时,两者并不一定非常吻合。如同第五章中所论述的,显示器只能近似地实际显示尺寸。

copyright dedecms

既然这样做好像有用了,现在就来试著列印图像。哇!如果您有一台300dpi的雷射印表机,那么列印出的直尺的宽将会是11/3英寸。这是由於我们依据视讯显示器的图素尺寸来列印。虽然您可能认为这把小尺很可爱,但它不是我们所需要的。让我们再试一试。 织梦内容管理系统

ENHMETAHEADER结构包括两个描述图像大小的矩形结构。第一个是rclBoundsEMF8使用这个,它以图素为单位给出图像的大小。第二为rclFrame,它以0.01毫米为单位给出图像的大小。这两个栏位之间的关系是由最初建立metafile时使用的参考装置内容决定的,在此情况下为显示器(metafile表头也包括两个名为szlDeviceszlMillimeters的栏位,它们是SIZEL结构,分别以图素单位和毫米单位指出了参考设备的大小,这与从GetDeviceCaps得到的资讯一样)。

本文来自织梦

EMF9使用图像的毫米大小资讯,如程式18-11所示。 内容来自dedecms

 程式18-11  EMF9 织梦内容管理系统 
EMF9.C 
内容来自dedecms
/*--------------------------------------------------------------------------- 
织梦好,好织梦
        EMF9.C -- Enhanced Metafile Demo #9 
织梦内容管理系统
                                              (c) Charles Petzold, 1998 
内容来自dedecms
----------------------------------------------------------------------------*/ 本文来自织梦 
  

织梦内容管理系统

#include <windows.h> 
copyright dedecms
#include <string.h> 

内容来自dedecms

  织梦好,好织梦 
TCHAR szClass          [] = TEXT ("EMF9") ; 本文来自织梦 
TCHAR szTitle          [] = TEXT ("EMF9: Enhanced Metafile Demo #9") ; 
copyright dedecms
  
织梦内容管理系统
void CreateRoutine (HWND hwnd) 内容来自dedecms 
{ 
dedecms.com
} 

本文来自织梦

  本文来自织梦 
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) 

本文来自织梦

{ 

内容来自dedecms

        ENHMETAHEADER          emh ; 织梦内容管理系统 
        HENHMETAFILE           hemf ; 

内容来自dedecms

        int                                           cxMms, cyMms, cxPix, cyPix, cxImage, cyImage ; 
内容来自dedecms
        RECT                                          rect ; copyright dedecms 
  本文来自织梦 
        cxMms          = GetDeviceCaps (hdc, HORZSIZE) ; 
内容来自dedecms
        cyMms          = GetDeviceCaps (hdc, VERTSIZE) ; 

dedecms.com

        cxPix          = GetDeviceCaps (hdc, HORZRES) ; 
织梦好,好织梦
        cyPix          = GetDeviceCaps (hdc, VERTRES) ; 

织梦好,好织梦

  

copyright dedecms

        hemf = GetEnhMetaFile (TEXT ("..\\emf8\\emf8.emf")) ; dedecms.com 
        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; copyright dedecms 
        cxImage                        = emh.rclFrame.right - emh.rclFrame.left ; 
copyright dedecms
        cyImage                        = emh.rclFrame.bottom - emh.rclFrame.top ; 内容来自dedecms 
  织梦内容管理系统 
        cxImage                        = cxImage * cxPix / cxMms / 100 ; 
copyright dedecms
        cyImage                        = cyImage * cyPix / cyMms / 100 ; 

copyright dedecms

  

内容来自dedecms

        rect.left              = (cxArea - cxImage) / 2 ; 

本文来自织梦

        rect.right             = (cxArea + cxImage) / 2 ; 
本文来自织梦
        rect.top               = (cyArea - cyImage) / 2 ; 
内容来自dedecms
        rect.bottom            = (cyArea + cyImage) / 2 ; 织梦好,好织梦 
  织梦内容管理系统 
        PlayEnhMetaFile (hdc, hemf, &rect) ; 

内容来自dedecms

        DeleteEnhMetaFile (hemf) ; 
dedecms.com
} 
织梦好,好织梦

EMF9使用EMF8建立的metafile,因此确定执行EMF8

内容来自dedecms

EMF9中的PaintRoutine函式首先使用目的装置内容呼叫GetDeviceCaps四次。像在EMF8中的CreateRoutine函式一样,这些呼叫提供有关设备解析度的资讯。在得到metafile代号之後,它取得表头结构并使用rclFrame栏位来计算以0.01毫米为单位的metafile图像大小。这是第一步。 copyright dedecms

然後,函式通过乘以输出设备的图素大小、除以毫米大小再除以100(因为度量尺寸以0.01毫米为单位)将此大小转换为图素大小。现在,PaintRoutine函式具有以图素为单位的直尺大小-与显示器无关。这是适合目的设备的图素大小,而且很容易使图像居中对齐。 本文来自织梦

就显示器而言,EMF9的显示与EMF8显示的一样。但是如果从EMF9列印直尺,您会看到更正常的直尺-6英寸长、1英寸宽。 dedecms.com

缩放比例和纵横比
 

copyright dedecms

您也可能想要使用EMF8建立的直尺metafile,而不必显示6英寸的图像。保持图像正确的61的纵横比是重要的。如前所述,在文书处理程式或别的应用程式中使用围绕方框来改变metafile的大小是很方便的,但是这样会导致某种程度的失真。在这种应用程式中,应该给使用者一个选项来保持原先的纵横比,而不用管围绕方框的大小如何变化。这就是说,传递给PlayEnhMetaFile的矩形结构不能直接由使用者选择的围绕方框定义。传递给该函式的矩形结构只是围绕方框的一部分。 dedecms.com

让我们看一看程式18-12 EMF10是如何做的。 本文来自织梦

 程式18-12  EMF10 

dedecms.com

EMF10.C 内容来自dedecms 
/*-------------------------------------------------------------------------- 

织梦内容管理系统

        EMF10.C --     Enhanced Metafile Demo #10 dedecms.com 
                                              (c) Charles Petzold, 1998 本文来自织梦 
---------------------------------------------------------------------------*/ 织梦内容管理系统 
  copyright dedecms 
#include <windows.h> 

织梦好,好织梦

TCHAR szClass          [] = TEXT ("EMF10") ; 织梦内容管理系统 
TCHAR szTitle          [] = TEXT ("EMF10: Enhanced Metafile Demo #10") ; 内容来自dedecms 
void CreateRoutine (HWND hwnd) 
内容来自dedecms
{ 
织梦好,好织梦
} 

本文来自织梦

  

织梦内容管理系统

void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) 
copyright dedecms
{ 内容来自dedecms 
        ENHMETAHEADER          emh ; copyright dedecms 
        float                                         fScale ; 本文来自织梦 
        HENHMETAFILE           hemf ; dedecms.com 
        int                                           cxMms, cyMms, cxPix, cyPix, cxImage, cyImage ; 本文来自织梦 
        RECT                                          rect ; dedecms.com 
  

dedecms.com

        cxMms          = GetDeviceCaps (hdc, HORZSIZE) ; 织梦内容管理系统 
        cyMms          = GetDeviceCaps (hdc, VERTSIZE) ; 
copyright dedecms
        cxPix          = GetDeviceCaps (hdc, HORZRES) ; 
内容来自dedecms
        cyPix          = GetDeviceCaps (hdc, VERTRES) ; 
copyright dedecms
  copyright dedecms 
        hemf    = GetEnhMetaFile (TEXT ("..\\emf8\\emf8.emf")) ; 

本文来自织梦

  内容来自dedecms 
        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; 织梦好,好织梦 
  dedecms.com 
        cxImage        = emh.rclFrame.right - emh.rclFrame.left ; 内容来自dedecms 
       cyImage        = emh.rclFrame.bottom - emh.rclFrame.top ; 本文来自织梦 
  
copyright dedecms
        cxImage        = cxImage * cxPix / cxMms / 100 ; dedecms.com 
        cyImage        = cyImage * cyPix / cyMms / 100 ; 
copyright dedecms
  

内容来自dedecms

        fScale = min ((float) cxArea / cxImage, (float) cyArea / cyImage) ; 织梦好,好织梦 
  

copyright dedecms

        cxImage                        = (int) (fScale * cxImage) ; 内容来自dedecms 
        cyImage                        = (int) (fScale * cyImage) ; 
内容来自dedecms
  
本文来自织梦
        rect.left              = (cxArea - cxImage) / 2 ; 

织梦好,好织梦

        rect.right             = (cxArea + cxImage) / 2 ; 

dedecms.com

        rect.top                       = (cyArea - cyImage) / 2 ; 

内容来自dedecms

        rect.bottom = (cyArea + cyImage) / 2 ; 织梦好,好织梦 
       PlayEnhMetaFile (hdc, hemf, &rect) ; 

内容来自dedecms

        DeleteEnhMetaFile (hemf) ; 
copyright dedecms
} 

织梦内容管理系统

EMF10伸展直尺图像以适应显示区域(或列印页面的可列印部分),但不会失真。通常直尺会伸展到显示区域的整个宽度,但是会上下居中对齐。如果您把视窗拉得太小,则直尺会与显示区域一般高,但是会水平居中对齐。 dedecms.com

可能有许多种方法来计算合适的显示矩形,但是我们只根据EMF9的方式完成该项工作。EMF10.C中的PaintRoutine函式开始部分与EMF9.C相同,为目的装置内容计算6英寸长的直尺图像适当的图素大小。 织梦好,好织梦

然後,程式计算名为fScale的浮点值,它是显示区域宽度与图像宽度的比值以及显示区域高度与图像高度比值两者的最小值。这个因数在计算围绕矩形前用於增加图像的图素大小。

织梦好,好织梦

metafile中的映射方式
 

copyright dedecms

前面绘制的直尺单位有英寸,也有毫米。这种工作使用GDI提供的各种映射方式似乎非常适合。但是我坚持使用图素,并「手工」完成所有必要的计算。为什么呢?

内容来自dedecms

答案很简单,就是将映射方式与metafile一起使用会十分混乱。我们不妨实验一下。

织梦好,好织梦

当使用metafile装置内容呼叫SetMapMode时,该函式在metafile中像其他GDI函式一样被编码。如程式18-13 EMF11显示的那样。

织梦好,好织梦

 程式18-13  EMF11 copyright dedecms 
EMF11.C copyright dedecms 
/*--------------------------------------------------------------------------- 内容来自dedecms 
        EMF11.C -- Enhanced Metafile Demo #11 copyright dedecms 
                                                     (c) Charles Petzold, 1998 内容来自dedecms 
  ------------------------------------------------------------------------*/ 
内容来自dedecms
  本文来自织梦 
#include <windows.h> 织梦内容管理系统 
TCHAR szClass          [] = TEXT ("EMF11") ; 内容来自dedecms 
TCHAR szTitle          [] = TEXT ("EMF11: Enhanced Metafile Demo #11") ; 

copyright dedecms

  

copyright dedecms

void DrawRuler (HDC hdc, int cx, int cy) 织梦内容管理系统 
{ 内容来自dedecms 
        int                            i, iHeight ; 

copyright dedecms

        LOGFONT                lf ; 内容来自dedecms 
        TCHAR                          ch ; 

dedecms.com

  

织梦好,好织梦

                               // Black pen with 1-point width 织梦内容管理系统 
  

copyright dedecms

        SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ; 
织梦好,好织梦
                               // Rectangle surrounding entire pen (with adjustment) 
copyright dedecms
        if (GetVersion () & 0x80000000)       `                      // Windows 98 内容来自dedecms 
                       Rectangle (hdc, 0, -2, cx + 2, cy) ; copyright dedecms 
        else    
dedecms.com
// Windows NT copyright dedecms 
                               Rectangle (hdc, 0, -1, cx + 1, cy) ; copyright dedecms 
  

织梦内容管理系统

                               // Tick marks 

织梦好,好织梦

           
copyright dedecms
        for (i = 1 ; i < 96 ; i++) 内容来自dedecms 
        { 
内容来自dedecms
         if    (i %16== 0)    iHeight = cy /2       ;       // inches 

copyright dedecms

         else if(i % 8== 0)iHeight = cy /    3 ;     // half inches 织梦内容管理系统 
         else if(i % 4== 0)iHeight = cy /    5 ;     // quarter inches 
本文来自织梦
         else if(i % 2== 0)iHeight = cy /    8 ;     // eighths dedecms.com 
         else iHeight = cy /12;       // sixteenths 

copyright dedecms

  
dedecms.com
               MoveToEx (hdc, i * cx / 96, 0, NULL) ; 内容来自dedecms 
                       LineTo   (hdc, i * cx / 96, iHeight) ; 

本文来自织梦

        } dedecms.com 
                       // Create logical font  

本文来自织梦

        FillMemory (&lf, sizeof (lf), 0) ; 
织梦内容管理系统
        lf.lfHeight = cy / 2 ; 
本文来自织梦
        lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ; 
dedecms.com
  
内容来自dedecms
        SelectObject   (hdc, CreateFontIndirect (&lf)) ; 
织梦内容管理系统
        SetTextAlign   (hdc, TA_BOTTOM | TA_CENTER) ; dedecms.com 
        SetBkMode              (hdc, TRANSPARENT) ; 本文来自织梦 
  
copyright dedecms
                       // Display numbers 
织梦内容管理系统
  织梦内容管理系统 
        for (i = 1 ; i <= 5 ; i++) 本文来自织梦 
        { 织梦好,好织梦 
                       ch = (TCHAR) (i + '0') ; 织梦好,好织梦 
                       TextOut (hdc, i * cx / 6, cy / 2, &ch, 1) ; 织梦内容管理系统 
        } 织梦内容管理系统 
                       // Clean up 
本文来自织梦
        DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ; 

本文来自织梦

            DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; 

内容来自dedecms

} 织梦好,好织梦 
  织梦内容管理系统 
void CreateRoutine (HWND hwnd) 织梦好,好织梦 
{ 
织梦内容管理系统
        HDC            hdcEMF ; 

织梦好,好织梦

        HENHMETAFILE   hemf ; 本文来自织梦 
      copyright dedecms 
        hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf11.emf"), NULL, dedecms.com 
                                        TEXT ("EMF11\0EMF Demo #11\0")) ; copyright dedecms 
        SetMapMode (hdcEMF, MM_LOENGLISH) ; 
织梦好,好织梦
        DrawRuler (hdcEMF, 600, 100) ; 
copyright dedecms
        hemf = CloseEnhMetaFile (hdcEMF) ; 本文来自织梦 
        DeleteEnhMetaFile (hemf) ; 内容来自dedecms 
} 织梦内容管理系统 
  织梦内容管理系统 
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) 织梦内容管理系统 
{ 
织梦好,好织梦
        ENHMETAHEADER          emh ; 本文来自织梦 
        HENHMETAFILE           hemf ; 

织梦内容管理系统

        int                    cxMms, cyMms, cxPix, cyPix, cxImage, cyImage ; 
织梦内容管理系统
        RECT                   rect ; 
织梦好,好织梦
      织梦内容管理系统 
        cxMms          = GetDeviceCaps (hdc, HORZSIZE) ; 

copyright dedecms

        cyMms          = GetDeviceCaps (hdc, VERTSIZE) ; 
本文来自织梦
        cxPix          = GetDeviceCaps (hdc, HORZRES) ; 

copyright dedecms

        cyPix          = GetDeviceCaps (hdc, VERTRES) ; copyright dedecms 
      织梦内容管理系统 
        hemf = GetEnhMetaFile (TEXT ("emf11.emf")) ; 
内容来自dedecms
        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; 
内容来自dedecms
        cxImage        = emh.rclFrame.right - emh.rclFrame.left ; copyright dedecms 
        cyImage        = emh.rclFrame.bottom - emh.rclFrame.top ; 
内容来自dedecms
      织梦好,好织梦 
        cxImage        = cxImage * cxPix / cxMms / 100 ; 
dedecms.com
        cyImage        = cyImage * cyPix / cyMms / 100 ; 
本文来自织梦
      
本文来自织梦
        rect.left              = (cxArea - cxImage) / 2 ; 
内容来自dedecms
        rect.top               = (cyArea - cyImage) / 2 ; 

内容来自dedecms

        rect.right             = (cxArea + cxImage) / 2 ; 织梦好,好织梦 
        rect.bottom            = (cyArea + cyImage) / 2 ; 

织梦内容管理系统

      本文来自织梦 
        PlayEnhMetaFile (hdc, hemf, &rect) ; 
copyright dedecms
        DeleteEnhMetaFile (hemf) ; 
copyright dedecms
} 
dedecms.com

EMF11中的CreateRoutine函式比EMF8(最初的直尺metafile程式)中的那个简单,因为它不需要呼叫GetDeviceCaps来确定以每英寸点数为单位的显示器解析度。相反,EMF11呼叫SetMapMode将映射方式设定为MM_LOENGLISH,其逻辑单位等於0.01英寸。因而,直尺的大小为600×100个单位,并将这些数值传递给DrawRuler本文来自织梦

除了MoveToExLineTo呼叫绘制直尺的刻度外,EMF11中的DrawRuler函式与EMF9中的一样。当以图素单位绘制时(内定的MM_TEXT映射方式),垂直轴上的单位沿著萤幕向下增长。对於MM_LOENGLISH映射方式(以及其他度量映射方式),则向上增长。这就需要修改程式码。同时,也需要更改Rectangle函式中的调节因数。 本文来自织梦

EMF11中的PaintRoutine函式基本上与EMF9中的相同,那个版本的程式能在显示器和印表机上以正确尺寸显示直尺。唯一不同之处在於EMF11使用EMF11.EMF档案,而EMF9使用EMF8建立的EMF8.EMF档案。

织梦好,好织梦

EMF11显示的图像基本上与EMF9所显示的相同。因此,在这里可以看到将SetMapMode呼叫嵌入metafile能够简化metafile的建立,而且不影响以其正确大小显示metafile的机制。 内容来自dedecms

映射与显示
 

织梦好,好织梦

EMF11中计算目的矩形包括对GetDeviceCaps的几个呼叫。我们的第二个目的是使用映射方式代替这些呼叫。GDI将目的矩形的座标视为逻辑座标。为这些座标使用MM_HIMETRIC似乎是个好方案,因为它使用0.01毫米作为逻辑单位,与增强型metafile表头中用於围绕矩形的单位相同。

copyright dedecms

程式18-14中所示的EMF12程式,保留了EMF8中使用的DrawRuler处理方式,但是使用MM_HIMETRIC映射方式显示metafile织梦内容管理系统

 程式18-14  EMF12 织梦内容管理系统 
EMF12.C dedecms.com 
/*--------------------------------------------------------------------------- 

dedecms.com

        EMF12.C --     Enhanced Metafile Demo #12 

织梦好,好织梦

                                              (c) Charles Petzold, 1998 内容来自dedecms 
---------------------------------------------------------------------------*/ 
copyright dedecms
  copyright dedecms 
#include <windows.h> 织梦内容管理系统 
TCHAR szClass          [] = TEXT ("EMF12") ; 织梦好,好织梦 
TCHAR szTitle          [] = TEXT ("EMF12: Enhanced Metafile Demo #12") ; 织梦好,好织梦 
void DrawRuler (HDC hdc, int cx, int cy) 本文来自织梦 
{ 

copyright dedecms

        int                            iAdj, i, iHeight ; 

copyright dedecms

        LOGFONT                lf ; 织梦内容管理系统 
        TCHAR                          ch ; copyright dedecms 
  copyright dedecms 
        iAdj = GetVersion () & 0x80000000 ? 0 : 1 ; 本文来自织梦 
                               // Black pen with 1-point width 
织梦好,好织梦
        SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ; 内容来自dedecms 
                               // Rectangle surrounding entire pen (with adjustment) 
dedecms.com
        Rectangle (hdc, iAdj, iAdj, cx + iAdj + 1, cy + iAdj + 1) ; 
本文来自织梦
                               // Tick marks 
dedecms.com
        for (i = 1 ; i < 96 ; i++) 

copyright dedecms

        { 本文来自织梦 
         if (i % 16 == 0)      iHeight = cy /  2 ;                   // inches 

织梦内容管理系统

         else if (i %  8 == 0)        iHeight = cy /  3 ;            // half inches 
dedecms.com
         else if (i %  4 == 0)        iHeight = cy /  5 ;            // quarter inches 
copyright dedecms
         else if (i %  2 == 0)        iHeight = cy /  8 ;            // eighths dedecms.com 
         else iHeight = cy / 12 ;    // sixteenths 
copyright dedecms
  本文来自织梦 
                       MoveToEx (hdc, i * cx / 96, cy, NULL) ; 
本文来自织梦
                       LineTo   (hdc, i * cx / 96, cy - iHeight) ; 

本文来自织梦

        } copyright dedecms 
                               // Create logical font  
织梦好,好织梦
        FillMemory (&lf, sizeof (lf), 0) ; 本文来自织梦 
        lf.lfHeight = cy / 2 ; 本文来自织梦 
        lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ; 
本文来自织梦
  织梦内容管理系统 
        SelectObject (hdc, CreateFontIndirect (&lf)) ; 
dedecms.com
        SetTextAlign (hdc, TA_BOTTOM | TA_CENTER) ; 

本文来自织梦

        SetBkMode    (hdc, TRANSPARENT) ; 
织梦内容管理系统
  
copyright dedecms
                               // Display numbers copyright dedecms 
  织梦内容管理系统 
        for (i = 1 ; i <= 5 ; i++) 本文来自织梦 
     { 本文来自织梦 
                       ch = (TCHAR) (i + '0') ; 

织梦好,好织梦

                       TextOut (hdc, i * cx / 6, cy / 2, &ch, 1) ; 内容来自dedecms 
        } 

织梦好,好织梦

                       // Clean up 本文来自织梦 
        DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ; 织梦好,好织梦 
        DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; 

织梦内容管理系统

} 

copyright dedecms

  
内容来自dedecms
void CreateRoutine (HWND hwnd) 

织梦内容管理系统

{ 本文来自织梦 
        HDC                                   hdcEMF ; 

内容来自dedecms

        HENHMETAFILE   hemf ; dedecms.com 
        int                                   cxMms, cyMms, cxPix, cyPix, xDpi, yDpi ; 内容来自dedecms 
      

dedecms.com

        hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf12.emf"), NULL, dedecms.com 
                                      TEXT ("EMF13\0EMF Demo #12\0")) ; 
copyright dedecms
      
dedecms.com
        cxMms = GetDeviceCaps (hdcEMF, HORZSIZE) ; 

copyright dedecms

        cyMms = GetDeviceCaps (hdcEMF, VERTSIZE) ; 内容来自dedecms 
        cxPix = GetDeviceCaps (hdcEMF, HORZRES) ; copyright dedecms 
        cyPix = GetDeviceCaps (hdcEMF, VERTRES) ; 
内容来自dedecms
      
copyright dedecms
        xDpi = cxPix * 254 / cxMms / 10 ; 

dedecms.com

        yDpi = cyPix * 254 / cyMms / 10 ; copyright dedecms 
      
内容来自dedecms
        DrawRuler (hdcEMF, 6 * xDpi, yDpi) ; 
dedecms.com
        hemf = CloseEnhMetaFile (hdcEMF) ; 

织梦内容管理系统

        DeleteEnhMetaFile (hemf) ; 

织梦好,好织梦

} 
本文来自织梦
  
织梦好,好织梦
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) 本文来自织梦 
{ 
dedecms.com
        ENHMETAHEADER          emh ; 

内容来自dedecms

        HENHMETAFILE           hemf ; 

内容来自dedecms

        POINT                                         pt ; 
dedecms.com
        int                                           cxImage, cyImage ; 

织梦内容管理系统

        RECT                                          rect ; dedecms.com 
      

织梦内容管理系统

        SetMapMode (hdc, MM_HIMETRIC) ; 内容来自dedecms 
        SetViewportOrgEx (hdc, 0, cyArea, NULL) ; 内容来自dedecms 
        pt.x = cxArea ; dedecms.com 
        pt.y = 0 ; 

copyright dedecms

      

copyright dedecms

        DPtoLP (hdc, &pt, 1) ; 

内容来自dedecms

        hemf = GetEnhMetaFile (TEXT ("emf12.emf")) ; 

织梦内容管理系统

        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; dedecms.com 
        cxImage        = emh.rclFrame.right - emh.rclFrame.left ; 内容来自dedecms 
        cyImage        = emh.rclFrame.bottom - emh.rclFrame.top ; 织梦好,好织梦 
      本文来自织梦 
        rect.left              = (pt.x - cxImage) / 2 ; copyright dedecms 
        rect.top               = (pt.y + cyImage) / 2 ; 织梦内容管理系统 
        rect.right             = (pt.x + cxImage) / 2 ; copyright dedecms 
        rect.bottom            = (pt.y - cyImage) / 2 ; dedecms.com 
      织梦好,好织梦 
        PlayEnhMetaFile (hdc, hemf, &rect) ; 
织梦内容管理系统
        DeleteEnhMetaFile (hemf) ; 
内容来自dedecms
} dedecms.com 

EMF12中的PaintRoutine函式首先将映射方式设定为MM_HIMETRIC。像其他度量映射方式一样,y值沿著萤幕向上增长。然而,原点座标仍在萤幕的左上角,这就意味显示区域内的y座标值是负数。为了纠正这个问题,程式呼叫SetViewportOrgEx将原点座标设定在左下角。 本文来自织梦

装置座标(cxArea,0)位於萤幕的右上角。把该座标点传递给DPtoLP(「装置座标点到逻辑座标点」)函式,得到以0.01毫米为单位的显示区域大小。

织梦内容管理系统

然後,程式载入metafile,取得档案表头,并找到以0.01毫米为单位的metafile大小。这样计算目的矩形在显示区域居中对齐的位置就变得十分简单。

织梦好,好织梦

现在我们看到了在建立metafile时能够使用映射方式,显示它时也能使用映射方式。我们能一起完成它们吗?

织梦内容管理系统

如程式18-15 EMF13展示的那样,这是可以的。 织梦内容管理系统

 程式18-15  EMF13 

本文来自织梦

EMF13.C 
dedecms.com
/*--------------------------------------------------------------------------- 
dedecms.com
        EMF13.C --     Enhanced Metafile Demo #13 内容来自dedecms 
                                              (c) Charles Petzold, 1998 copyright dedecms 
----------------------------------------------------------------------------*/ 
dedecms.com
  dedecms.com 
#include <windows.h> 

织梦内容管理系统

TCHAR szClass          [] = TEXT ("EMF13") ; copyright dedecms 
TCHAR szTitle          [] = TEXT ("EMF13: Enhanced Metafile Demo #13") ; 

织梦内容管理系统

  copyright dedecms 
void CreateRoutine (HWND hwnd) 织梦好,好织梦 
{ 
织梦内容管理系统
} 

织梦好,好织梦

  copyright dedecms 
void PaintRoutine (HWND hwnd, HDC hdc, int cxArea, int cyArea) dedecms.com 
{ 

本文来自织梦

        ENHMETAHEADER          emh ; 织梦内容管理系统 
        HENHMETAFILE           hemf ; 织梦内容管理系统 
        POINT                                         pt ; 

织梦内容管理系统

        int                                           cxImage, cyImage ; 
织梦好,好织梦
        RECT                                          rect ; 
本文来自织梦
      织梦好,好织梦 
        SetMapMode (hdc, MM_HIMETRIC) ; 内容来自dedecms 
        SetViewportOrgEx (hdc, 0, cyArea, NULL) ; 织梦好,好织梦 
        pt.x    = cxArea ; 
织梦内容管理系统
        pt.y    = 0 ; 

copyright dedecms

      dedecms.com 
        DPtoLP (hdc, &pt, 1) ; 
本文来自织梦
      本文来自织梦 
        hemf = GetEnhMetaFile (TEXT ("..\\emf11\\emf11.emf")) ; 织梦好,好织梦 
      本文来自织梦 
        GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ; dedecms.com 
      织梦好,好织梦 
        cxImage        = emh.rclFrame.right - emh.rclFrame.left ; 
织梦好,好织梦
        cyImage        = emh.rclFrame.bottom - emh.rclFrame.top ; 

dedecms.com

      本文来自织梦 
        rect.left              = (pt.x - cxImage) / 2 ; 织梦好,好织梦 
        rect.top               = (pt.y + cyImage) / 2 ; 

织梦内容管理系统

        rect.right             = (pt.x + cxImage) / 2 ; copyright dedecms 
        rect.bottom            = (pt.y - cyImage) / 2 ; 织梦好,好织梦 
      
织梦内容管理系统
        PlayEnhMetaFile (hdc, hemf, &rect) ; 本文来自织梦 
        DeleteEnhMetaFile (hemf) ; 内容来自dedecms 
} 
内容来自dedecms

EMF13中,由於直尺metafile已由EMF11建立,所以它没有使用映射方式建立metafileEMF13只是简单地载入metafile,然後像EMF11一样使用映射方式计算目的矩形。

dedecms.com

现在,我们可以建立一些规则。在建立metafile时,GDI使用对映射方式的任意嵌入修改,来计算以图素和毫米为单位的metafile图像的大小。图像的大小储存在metafile表头内。在显示metafile时,GDI在呼叫PlayEnhMetaFile时根据有效的映射方式建立目的矩形的实际位置,而本来的metafile中并没有任何记录去更改这个位置。

内容来自dedecms