18.1 老式图元文件格式(wmf)

(1)创建图元文件:HDC hdcMeta = CreateMetaFile(lpszFile);

  ①如果lpszFile为NULL则图元文件存储在内存中,如果指定文件名(XXX.WMF)则存储为磁盘文件。

  ②返回值为图元文件的设备环境句柄,可以使用内存DC一样,用GDI绘图函数在其上绘图。

(2)关闭图元文件:HMETAFILE hmf= CloseMetaFile(hdcMeta);

  ①这里不像一般的DC,创建DC后要删除DC,而是关闭。

  ②关闭图元文件的设备环境会返回该图元文件的句柄。

(3)显示(绘制)图元文件:PlayMetaFile

  ①绘制图元文件中的各对象,即在CreateMetaFile和CloseMetaFile之间所有的GDI调用。

  ②图元文件中的函数坐标,其具体含义将由目标设备环境的当前坐标转换设置来确定。

(4)删除图元文件句柄:DeleteMetaFile(hmf);//

★注意只删除图元文件句柄,并没删除磁盘上的文件。要删除文件可调用DeleteFile。

【MetaFile程序】

  1. /*------------------------------------------------------------
  2. METAFILE.C -- Metafile Demonstration Program
  3. (c) Charles Petzold, 1998
  4. ------------------------------------------------------------*/
  5.  
  6. #include <windows.h>
  7.  
  8. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  9.  
  10. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  11. PSTR szCmdLine, int iCmdShow)
  12. {
  13. static TCHAR szAppName[] = TEXT ("Metafile") ;
  14. HWND hwnd ;
  15. MSG msg ;
  16. WNDCLASS wndclass ;
  17.  
  18. wndclass.style = CS_HREDRAW | CS_VREDRAW ;
  19. wndclass.lpfnWndProc = WndProc ;
  20. wndclass.cbClsExtra = ;
  21. wndclass.cbWndExtra = ;
  22. wndclass.hInstance = hInstance ;
  23. wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
  24. wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
  25. wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  26. wndclass.lpszMenuName = NULL ;
  27. wndclass.lpszClassName = szAppName ;
  28.  
  29. if (!RegisterClass (&wndclass))
  30. {
  31. MessageBox (NULL, TEXT ("This program requires Windows NT!"),
  32. szAppName, MB_ICONERROR) ;
  33. return ;
  34. }
  35.  
  36. hwnd = CreateWindow (szAppName, // window class name
  37. TEXT ("Metafile Demonstration"), // window caption
  38. WS_OVERLAPPEDWINDOW, // window style
  39. CW_USEDEFAULT, // initial x position
  40. CW_USEDEFAULT, // initial y position
  41. CW_USEDEFAULT, // initial x size
  42. CW_USEDEFAULT, // initial y size
  43. NULL, // parent window handle
  44. NULL, // window menu handle
  45. hInstance, // program instance handle
  46. NULL) ; // creation parameters
  47.  
  48. ShowWindow (hwnd, iCmdShow) ;
  49. UpdateWindow (hwnd) ;
  50.  
  51. while (GetMessage (&msg, NULL, , ))
  52. {
  53. TranslateMessage (&msg) ;
  54. DispatchMessage (&msg) ;
  55. }
  56. return msg.wParam ;
  57. }
  58.  
  59. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  60. {
  61.  
  62. PAINTSTRUCT ps ;
  63. static HMETAFILE hmf;
  64. static int cxClient, cyClient;
  65. HDC hdc,hdcMeta;
  66. HBRUSH hBrush;
  67. int x, y;
  68.  
  69. switch (message)
  70. {
  71. case WM_CREATE:
  72. //创建图元文件设备环境(内存中)
  73. hdcMeta = CreateMetaFile(NULL);
  74.  
  75. //创建蓝色画刷
  76. hBrush = CreateSolidBrush(RGB(, , ));
  77.  
  78. Rectangle(hdcMeta, , , , );
  79.  
  80. MoveToEx(hdcMeta, , , NULL); //左上
  81. LineTo(hdcMeta, , ); //右下
  82. MoveToEx(hdcMeta, , , NULL);//左下
  83. LineTo(hdcMeta, , ); //右上
  84.  
  85. SelectObject(hdcMeta, hBrush);
  86. Ellipse(hdcMeta, , , , );
  87.  
  88. //关闭图元文件设备环境,并返回图元文件句柄
  89. hmf = CloseMetaFile(hdcMeta);
  90.  
  91. DeleteObject(hBrush);
  92. return ;
  93.  
  94. case WM_SIZE:
  95. cxClient = LOWORD(lParam);
  96. cyClient = HIWORD(lParam);
  97. return ;
  98.  
  99. case WM_PAINT:
  100. hdc = BeginPaint (hwnd, &ps) ;
  101.  
  102. //设置图元文件里面对象的坐标单位。
  103. SetMapMode(hdc, MM_ANISOTROPIC);
  104. SetWindowExtEx(hdc, , , NULL);
  105. SetViewportExtEx(hdc, cxClient, cyClient, NULL);
  106.  
  107. //重复画图元文件100次,按10*10排列
  108. for (y = ; y < ; y++)
  109. for (x = ; x < ; x++)
  110. {
  111. SetWindowOrgEx(hdc, - * x, - * y, NULL);
  112. PlayMetaFile(hdc, hmf);
  113. }
  114.  
  115. EndPaint (hwnd, &ps) ;
  116. return ;
  117.  
  118. case WM_DESTROY:
  119. DeleteMetaFile(hmf);
  120. PostQuitMessage () ;
  121. return ;
  122. }
  123. return DefWindowProc (hwnd, message, wParam, lParam) ;
  124. }
  125.  
  126. void PrepareMetaFile(HDC hdc, LPMETAFILEPICT pmfp, int cxClient,int cyClient)
  127. {
  128. int xScale, yScale, iScale;
  129.  
  130. SetMapMode(hdc, pmfp->mm); //根据mm字段设置映射模式
  131.  
  132. //处理MM_ISOTROPIC和MM_ANISOTROPIC情况
  133. if (pmfp->mm == MM_ISOTROPIC || pmfp->mm == MM_ANISOTROPIC)
  134. {
  135. if (pmfp->xExt == ) //xExt\yExt表示不指定图像的大小时
  136. {
  137. //在图元文件内部己经会自己调用SetWindowExtEx函数,这里无须设置。
  138. SetViewportExtEx(hdc, cxClient, cyClient, NULL);
  139. }
  140. else if (pmfp->xExt >) //xExt\yExt表示图像的大小,单位是0.01mm
  141. {
  142. SetViewportExtEx(hdc,
  143. pmfp->xExt* GetDeviceCaps(hdc, HORZRES) /
  144. GetDeviceCaps(hdc, HORZSIZE) / , //将逻辑单位转为像素大小
  145. pmfp->yExt* GetDeviceCaps(hdc, VERTRES) /
  146. GetDeviceCaps(hdc, VERTSIZE) / , //将yExt*0.01mm转为像素大小
  147. NULL);
  148. }
  149. else if (pmfp->xExt < ) //xExt、yExt表示图像的比值表示纵横比。
  150. {
  151. //将图像显示区域除以图像的大小,获得缩放比
  152. //首先cxClient的单位为像素,乘以HORZSIZE/HORZRES,转换为像素规模所对应的毫米总数,再乘以100
  153. //转为单位为0.01毫米,最后再除以图像的大小,得到缩放比
  154. xScale = * cxClient * GetDeviceCaps(hdc, HORZSIZE) / //单位都化为0.01毫米进行比较
  155. GetDeviceCaps(hdc, HORZRES) / -pmfp->xExt;
  156.  
  157. yScale = * cyClient * GetDeviceCaps(hdc, VERTSIZE) / //单位都化为0.01毫米进行比较
  158. GetDeviceCaps(hdc, VERTRES) / -pmfp->yExt;
  159.  
  160. iScale = min(xScale, yScale);
  161.  
  162. //设置视口范围,将图像大小映射到整个显示区域
  163. SetViewportExtEx(hdc, -pmfp->xExt *iScale* GetDeviceCaps(hdc, HORZRES) /
  164. GetDeviceCaps(hdc, HORZSIZE) /,
  165. -pmfp->yExt *iScale* GetDeviceCaps(hdc, VERTRES) /
  166. GetDeviceCaps(hdc, VERTSIZE) /,
  167. NULL);
  168. }
  169. }
  170.  
  171. //如果不是MM_ISOTROPIC或MM_ANISOTROPIC模式,则xExt和yExt的值表示图像的宽度和
  172. //高度,单位由mm字段的设置决定。
  173. }

18.1.1 把图元文件存储到磁盘

(1)获取磁盘中的图元文件:hmf = GetMetaFile(szFileName);

(2)在WM_PAINT中处理完后,可以直接DeleteMetaFile(hmf);

(3)当把图元文件定义为资源时,可以将其作为一个数据块加载。如果己经有图元文件内容的数据块,可以使用如下语句来创建图元文件。

hmf = SetMetaFileBitsEx(iSize,pData);//根据pData的内容来创建图元文件。

GetMetaFileBitsEx(hmf,iSize,pData);//将图元文件拷到pData内存块中。iSize为图元文件的大小。

18.1.2 老式的图元文件和剪贴板

(1)老式图元文件的缺点:

  ①老式图元文件中的坐标是逻辑坐标。显示时,图像大小很难确定。

  ②如果在图元文件内部设置了MM_ISOTROPIC或MM_ANISOTROPIC映射模式时,那么程序在PlayMetaFile期间用户很难干预,也就不能设置映射模式了。只能在PlayMetaFile之前或之后设置映射模式了。但图元文件内部会调用SetWindowExtEx等函数,所以,用户设置的无法真正工作。

(2)解决方案——传入剪贴板的不是图元文件句柄,而是METAFILEPIC结构体。

字段

含义

LONG mm

映射模式

LONG xExt

图元文件的宽度和高度

1. 在除MM_ISOTROPIC和MM_ANISOTROPIC映射模式下,其单位为mm字段中设置映射模式的单位。

2. 在MM_ISOTROPIC和MM_ANISOTROPIC中,单位:0.01mm。

①xExt=0时,表示不指定图像的尺寸或纵横比

②xExt>0时,表示图像的宽度和高度。

③xExt<0时,其值单位仍然是0.01mm,但这种情况下,更有意义的是xExt/yExt的比值,即纵横比。

LONG yExt

LONG hMF

图元文件句柄

  注意:当得到图元文件设备环境后,要在其上绘图前,一般还用调用SetWindowExtEx来指定绘图逻辑单位。但一般不包含SetMapMode、SetViewportExtEx或SetViewportOrgEx的调用。因为这些是基于显示平面的设备单位。即图元文件本身,内部一般要调用SetWindowExtEx函数,但不包含SetViewportExtEx等函数。

(3)创建图元文件并复制到剪贴板

  1. //创建图元文件设备环境
  2. hdcMeta = CreateMetaFile(NULL); //基于内存的
  3. SetWindowExtEx(hdcMeta,…); //在图元文件内部设置映射模式,但不包含
  4. SetWindowOrgEx(hdcMeta,…); // SetMapMode或SetViewportExtEx函数。
  5.  
  6. //获取该图元文件的句柄
  7. hmf = CloseMetaFile(hdcMeta);
  8.  
  9. //复制到剪贴板
  10. GLOBALHANDLE hGlobal;
  11. LPMETAFILEPICT pMFP; //指向METAFILEPICT结构的指针
  12. hGlobal = GlobalAlloc(GHND|GMEM_SHARE,sizeof(METAFILEPICT));
  13. pMFP = (LPMETAFILEPICT)GlobalLock(hGlobal);
  14.  
  15. //设置结构体设置
  16. pMFP->mm = MM_...; //使用的映射模式;
  17. pMFP->xExt = …; //设置图像的宽度(逻辑单位)
  18. pMFP->yExt =…;
  19. pMPF->hMF = hmf;
  20.  
  21. GlobalUnlock(hGlobal);
  22.  
  23. //传送到剪贴板
  24. OpenClipboard(hwnd);
  25. EmptyClipboard();
  26. SetClipboardData(CF_METAFILEPICT,hGlobal);//这里传入的是METAFILEPIC结构,而不是hmf;
  27. CloseClipboard(); //至此,hGlobal和hmf句柄失效,不能再使用它们了。

(4)从剪贴板中获取图元文件,并显示。

  1. //获取METAFILEPICT结构体
  2. OpenClipboard(hwnd);
  3. hGlobal = GetClipboardData(CF_METAFILEPICT);
  4. pMFP->(LPMETAFILEPICT)GlobalLock(hGlobal);
  5.  
  6. SaveDC(hdc);
  7. //根据mm、xExt、yExt设置映射模式
  8. PrepareMetaFile(hdc,pMFP,cxClient,cyClient); //其中cxClient,cyClient为图元文件要显示的像素宽度和高度。该函数是自定义的,见后面的代码实现。
  9. PlayMetaFilepMFP->hMF);
  10. RestoreDC(hdc,-);
  11.  
  12. GlobalUnlock(hGlobal);
  13. CloseClipboard();
  14.  
  15. ()PrepareMetaFile函数的分析
  16. void PrepareMetaFile(HDC hdc, LPMETAFILEPICT pmfp, int cxClient,int cyClient)
  17. {
  18. int xScale, yScale, iScale;
  19.  
  20. SetMapMode(hdc, pmfp->mm); //根据mm字段设置映射模式
  21.  
  22. //处理MM_ISOTROPIC和MM_ANISOTROPIC情况
  23. if (pmfp->mm == MM_ISOTROPIC || pmfp->mm == MM_ANISOTROPIC)
  24. {
  25. if (pmfp->xExt == ) //xExt\yExt表示不指定图像的大小时
  26. {
  27. //在图元文件内部己经会自己调用SetWindowExtEx函数,这里无须设置。
  28. SetViewportExtEx(hdc, cxClient, cyClient, NULL);
  29. }
  30. else if (pmfp->xExt >) //xExt\yExt表示图像的大小,单位是0.01mm
  31. {
  32. SetViewportExtEx(hdc,
  33. pmfp->xExt* GetDeviceCaps(hdc, HORZRES) /
  34. GetDeviceCaps(hdc, HORZSIZE) / , //将逻辑单位转为像素大小
  35. pmfp->yExt* GetDeviceCaps(hdc, VERTRES) /
  36. GetDeviceCaps(hdc, VERTSIZE) / , //将yExt*0.01mm转为像素大小
  37. NULL);
  38. }
  39. else if (pmfp->xExt < ) //xExt、yExt表示图像的比值表示纵横比。
  40. {
  41. //将图像显示区域除以图像的大小,获得缩放比
  42. //首先cxClient的单位为像素,乘以HORZSIZE/HORZRES,转换为像素规模所对应的毫米总数,再乘以100
  43. //转为单位为0.01毫米,最后再除以图像的大小,得到缩放比
  44. xScale = * cxClient * GetDeviceCaps(hdc, HORZSIZE) / //单位都化为0.01毫米进行比较
  45. GetDeviceCaps(hdc, HORZRES) / -pmfp->xExt;
  46.  
  47. yScale = * cyClient * GetDeviceCaps(hdc, VERTSIZE) / //单位都化为0.01毫米进行比较
  48. GetDeviceCaps(hdc, VERTRES) / -pmfp->yExt;
  49.  
  50. iScale = min(xScale, yScale);
  51.  
  52. //设置视口范围,将图像大小映射到整个显示区域
  53. SetViewportExtEx(hdc, -pmfp->xExt *iScale* GetDeviceCaps(hdc, HORZRES) /
  54. GetDeviceCaps(hdc, HORZSIZE) /,
  55. -pmfp->yExt *iScale* GetDeviceCaps(hdc, VERTRES) /
  56. GetDeviceCaps(hdc, VERTSIZE) /,
  57. NULL);
  58. }
  59. }
  60.  
  61. //如果不是MM_ISOTROPIC或MM_ANISOTROPIC模式,则xExt和yExt的值表示图像的宽度和
  62. //高度,单位由mm字段的设置决定。
  63. }

(5)Windows剪贴板会自动进行老格式和增强型格式之间的转换。是否转换,要看用户从剪贴板请求的文件格式。

第18章 图元文件_18.1 老式图元文件格式(wmf)的更多相关文章

  1. 第18章 图元文件_18.2 增强型图元文件(emf)(2)

    18.2.7 增强型图元文件的查看和打印程序 (1)传递EMF到剪贴板,剪贴板类型应为:CF_ENHMETAFILE (2)CopyEnhMetaFile用于复制图元文件 (3)剪贴板中的图元文件会自 ...

  2. 第18章 图元文件_18.2 增强型图元文件(emf)(1)

    18.2 增强型图元文件(emf) 18.2.1 创建并显示增强型图元文件的步骤 (1)创建:hdcEMF = CreateEnhMetaFile(hdcRef,szFilename,lpRect,l ...

  3. 第18章 集合框架(2)-Set接口

    第18章 集合框架(2)-Set接口 Set是Collection子接口,模拟了数学上的集的概念 Set集合存储特点 1.不允许元素重复 2.不会记录元素的先后添加顺序 Set只包含从Collecti ...

  4. Java 第18章 多态

    18 章  --> 多态 继承: extends 抽象类 abstract (限制类的实例化) 抽象方法 public abstract void show(); //抽象方法只有方法的声明,没 ...

  5. LPTHW 笨方法学python 18章

    看完18章以后,发现第一个练习中,使用了*args读取全部的的输入参数作为一个元组,但是在他的练习中只给了两个变量去赋值,当用户不清楚这个函数的定义时,就可能会给出过多的变量进这个函数,那么就会出现如 ...

  6. 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  7. 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  8. Linux就这个范儿 第18章 这里也是鼓乐笙箫 Linux读写内存数据的三种方式

    Linux就这个范儿 第18章  这里也是鼓乐笙箫  Linux读写内存数据的三种方式 P703 Linux读写内存数据的三种方式 1.read  ,write方式会在用户空间和内核空间不断拷贝数据, ...

  9. 【C#4.0图解教程】笔记(第9章~第18章)

    第9章 语句 1.标签语句 ①.标签语句由一个标识符后面跟着一个冒号再跟着一条语句组成 ②.标签语句的执行完全如同标签不存在一样,并仅执行冒号后的语句. ③.给语句添加一个标签允许控制从代码的另一部分 ...

随机推荐

  1. WAF指纹识别和XSS过滤器绕过技巧

    [译文] -- “Modern Web Application Firewalls Fingerprinting and Bypassing XSS Filters” 0x1 前言 之前在乌云drop ...

  2. SharePoint 2013 为用户组自定义EventReceiver

    前 言 在SharePoint的开发中,EventReceiver是很重要的一个部分,但是,常常遇到有些需要事件的时候,却没有相应的模板,因为EventReceiver创建时的模板只有那几个,除此之外 ...

  3. TextView显示颜色高亮的问题

    TextView textView = (TextView) findViewById( R.id.tv ); String text = "<font color=\"#d ...

  4. 电脑公司最新GHOST WIN7系统32,64位优化精简版下载

    系统来自系统妈:http://www.xitongma.com 电脑公司最新GHOST win7系统32位优化精简版V2016年3月 系统概述 电脑公司ghost win7 x86(32位)万能装机版 ...

  5. 在【Xamarin+Prism开发详解三:Visual studio 2017 RC初体验】中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很是感兴趣。于是发时间深入研究了一下Visual Studio 2017RC 是不是和微软Connect()://2016上说得一样神。

    总共列出了12点,耐心点慢慢看! 1,添加了不少[代码样式]的设置项目. 通过合理的设置每个人都能写出优美的代码,而且团队项目也可以达到统一代码风格. this首选项:可以设置[字段,属性,方法,事件 ...

  6. 使用sql server profilter跟踪sql

    最近在研究EF延迟加载和贪婪加载的用法时,想要查看Linq生成的sql.一开始通过VS-->调试-->窗口-->IntelliTrace事件,来查看生成的sql,并不是十分准确.然后 ...

  7. Oracle 外连接和 (+)号的用法

    对于外连接,Oracle中可以使用“(+)”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN,下面将配合实例一一介绍.1. LEFT OUTER JOIN:左外关联 SELEC ...

  8. C#语言——类

    C#——类 一.String 类 系统内置的处理字符串类型的函数方法类.方便我们对字符串类型进行一系列的处理. 1.Length:获取字符串的长度,返回一个int类型的值 string x=Conso ...

  9. MYSQL的JOB

    要让JOB顺利运行,必须要打开MYSQL的定时器. -- 查看是否开启定时器 SHOW VARIABLES LIKE '%sche%'; -- 开启定时器 0:off 1:on -- 这个需要最高权限 ...

  10. mybatis oracle BLOB类型字段保存与读取

    一.BLOB字段 BLOB是指二进制大对象也就是英文Binary Large Object的所写,而CLOB是指大字符对象也就是英文Character Large Object的所写.其中BLOB是用 ...