第18章 图元文件_18.1 老式图元文件格式(wmf)
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程序】
- /*------------------------------------------------------------
- METAFILE.C -- Metafile Demonstration Program
- (c) Charles Petzold, 1998
- ------------------------------------------------------------*/
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("Metafile") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ;
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = ;
- wndclass.cbWndExtra = ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- if (!RegisterClass (&wndclass))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return ;
- }
- hwnd = CreateWindow (szAppName, // window class name
- TEXT ("Metafile Demonstration"), // window caption
- WS_OVERLAPPEDWINDOW, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, , ))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps ;
- static HMETAFILE hmf;
- static int cxClient, cyClient;
- HDC hdc,hdcMeta;
- HBRUSH hBrush;
- int x, y;
- switch (message)
- {
- case WM_CREATE:
- //创建图元文件设备环境(内存中)
- hdcMeta = CreateMetaFile(NULL);
- //创建蓝色画刷
- hBrush = CreateSolidBrush(RGB(, , ));
- Rectangle(hdcMeta, , , , );
- MoveToEx(hdcMeta, , , NULL); //左上
- LineTo(hdcMeta, , ); //右下
- MoveToEx(hdcMeta, , , NULL);//左下
- LineTo(hdcMeta, , ); //右上
- SelectObject(hdcMeta, hBrush);
- Ellipse(hdcMeta, , , , );
- //关闭图元文件设备环境,并返回图元文件句柄
- hmf = CloseMetaFile(hdcMeta);
- DeleteObject(hBrush);
- return ;
- case WM_SIZE:
- cxClient = LOWORD(lParam);
- cyClient = HIWORD(lParam);
- return ;
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- //设置图元文件里面对象的坐标单位。
- SetMapMode(hdc, MM_ANISOTROPIC);
- SetWindowExtEx(hdc, , , NULL);
- SetViewportExtEx(hdc, cxClient, cyClient, NULL);
- //重复画图元文件100次,按10*10排列
- for (y = ; y < ; y++)
- for (x = ; x < ; x++)
- {
- SetWindowOrgEx(hdc, - * x, - * y, NULL);
- PlayMetaFile(hdc, hmf);
- }
- EndPaint (hwnd, &ps) ;
- return ;
- case WM_DESTROY:
- DeleteMetaFile(hmf);
- PostQuitMessage () ;
- return ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
- void PrepareMetaFile(HDC hdc, LPMETAFILEPICT pmfp, int cxClient,int cyClient)
- {
- int xScale, yScale, iScale;
- SetMapMode(hdc, pmfp->mm); //根据mm字段设置映射模式
- //处理MM_ISOTROPIC和MM_ANISOTROPIC情况
- if (pmfp->mm == MM_ISOTROPIC || pmfp->mm == MM_ANISOTROPIC)
- {
- if (pmfp->xExt == ) //xExt\yExt表示不指定图像的大小时
- {
- //在图元文件内部己经会自己调用SetWindowExtEx函数,这里无须设置。
- SetViewportExtEx(hdc, cxClient, cyClient, NULL);
- }
- else if (pmfp->xExt >) //xExt\yExt表示图像的大小,单位是0.01mm
- {
- SetViewportExtEx(hdc,
- pmfp->xExt* GetDeviceCaps(hdc, HORZRES) /
- GetDeviceCaps(hdc, HORZSIZE) / , //将逻辑单位转为像素大小
- pmfp->yExt* GetDeviceCaps(hdc, VERTRES) /
- GetDeviceCaps(hdc, VERTSIZE) / , //将yExt*0.01mm转为像素大小
- NULL);
- }
- else if (pmfp->xExt < ) //xExt、yExt表示图像的比值表示纵横比。
- {
- //将图像显示区域除以图像的大小,获得缩放比
- //首先cxClient的单位为像素,乘以HORZSIZE/HORZRES,转换为像素规模所对应的毫米总数,再乘以100
- //转为单位为0.01毫米,最后再除以图像的大小,得到缩放比
- xScale = * cxClient * GetDeviceCaps(hdc, HORZSIZE) / //单位都化为0.01毫米进行比较
- GetDeviceCaps(hdc, HORZRES) / -pmfp->xExt;
- yScale = * cyClient * GetDeviceCaps(hdc, VERTSIZE) / //单位都化为0.01毫米进行比较
- GetDeviceCaps(hdc, VERTRES) / -pmfp->yExt;
- iScale = min(xScale, yScale);
- //设置视口范围,将图像大小映射到整个显示区域
- SetViewportExtEx(hdc, -pmfp->xExt *iScale* GetDeviceCaps(hdc, HORZRES) /
- GetDeviceCaps(hdc, HORZSIZE) /,
- -pmfp->yExt *iScale* GetDeviceCaps(hdc, VERTRES) /
- GetDeviceCaps(hdc, VERTSIZE) /,
- NULL);
- }
- }
- //如果不是MM_ISOTROPIC或MM_ANISOTROPIC模式,则xExt和yExt的值表示图像的宽度和
- //高度,单位由mm字段的设置决定。
- }
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)创建图元文件并复制到剪贴板
- //创建图元文件设备环境
- hdcMeta = CreateMetaFile(NULL); //基于内存的
- SetWindowExtEx(hdcMeta,…); //在图元文件内部设置映射模式,但不包含
- SetWindowOrgEx(hdcMeta,…); // SetMapMode或SetViewportExtEx函数。
- //获取该图元文件的句柄
- hmf = CloseMetaFile(hdcMeta);
- //复制到剪贴板
- GLOBALHANDLE hGlobal;
- LPMETAFILEPICT pMFP; //指向METAFILEPICT结构的指针
- hGlobal = GlobalAlloc(GHND|GMEM_SHARE,sizeof(METAFILEPICT));
- pMFP = (LPMETAFILEPICT)GlobalLock(hGlobal);
- //设置结构体设置
- pMFP->mm = MM_...; //使用的映射模式;
- pMFP->xExt = …; //设置图像的宽度(逻辑单位)
- pMFP->yExt =…;
- pMPF->hMF = hmf;
- GlobalUnlock(hGlobal);
- //传送到剪贴板
- OpenClipboard(hwnd);
- EmptyClipboard();
- SetClipboardData(CF_METAFILEPICT,hGlobal);//这里传入的是METAFILEPIC结构,而不是hmf;
- CloseClipboard(); //至此,hGlobal和hmf句柄失效,不能再使用它们了。
(4)从剪贴板中获取图元文件,并显示。
- //获取METAFILEPICT结构体
- OpenClipboard(hwnd);
- hGlobal = GetClipboardData(CF_METAFILEPICT);
- pMFP->(LPMETAFILEPICT)GlobalLock(hGlobal);
- SaveDC(hdc);
- //根据mm、xExt、yExt设置映射模式
- PrepareMetaFile(hdc,pMFP,cxClient,cyClient); //其中cxClient,cyClient为图元文件要显示的像素宽度和高度。该函数是自定义的,见后面的代码实现。
- PlayMetaFile(pMFP->hMF);
- RestoreDC(hdc,-);
- GlobalUnlock(hGlobal);
- CloseClipboard();
- ()PrepareMetaFile函数的分析
- void PrepareMetaFile(HDC hdc, LPMETAFILEPICT pmfp, int cxClient,int cyClient)
- {
- int xScale, yScale, iScale;
- SetMapMode(hdc, pmfp->mm); //根据mm字段设置映射模式
- //处理MM_ISOTROPIC和MM_ANISOTROPIC情况
- if (pmfp->mm == MM_ISOTROPIC || pmfp->mm == MM_ANISOTROPIC)
- {
- if (pmfp->xExt == ) //xExt\yExt表示不指定图像的大小时
- {
- //在图元文件内部己经会自己调用SetWindowExtEx函数,这里无须设置。
- SetViewportExtEx(hdc, cxClient, cyClient, NULL);
- }
- else if (pmfp->xExt >) //xExt\yExt表示图像的大小,单位是0.01mm
- {
- SetViewportExtEx(hdc,
- pmfp->xExt* GetDeviceCaps(hdc, HORZRES) /
- GetDeviceCaps(hdc, HORZSIZE) / , //将逻辑单位转为像素大小
- pmfp->yExt* GetDeviceCaps(hdc, VERTRES) /
- GetDeviceCaps(hdc, VERTSIZE) / , //将yExt*0.01mm转为像素大小
- NULL);
- }
- else if (pmfp->xExt < ) //xExt、yExt表示图像的比值表示纵横比。
- {
- //将图像显示区域除以图像的大小,获得缩放比
- //首先cxClient的单位为像素,乘以HORZSIZE/HORZRES,转换为像素规模所对应的毫米总数,再乘以100
- //转为单位为0.01毫米,最后再除以图像的大小,得到缩放比
- xScale = * cxClient * GetDeviceCaps(hdc, HORZSIZE) / //单位都化为0.01毫米进行比较
- GetDeviceCaps(hdc, HORZRES) / -pmfp->xExt;
- yScale = * cyClient * GetDeviceCaps(hdc, VERTSIZE) / //单位都化为0.01毫米进行比较
- GetDeviceCaps(hdc, VERTRES) / -pmfp->yExt;
- iScale = min(xScale, yScale);
- //设置视口范围,将图像大小映射到整个显示区域
- SetViewportExtEx(hdc, -pmfp->xExt *iScale* GetDeviceCaps(hdc, HORZRES) /
- GetDeviceCaps(hdc, HORZSIZE) /,
- -pmfp->yExt *iScale* GetDeviceCaps(hdc, VERTRES) /
- GetDeviceCaps(hdc, VERTSIZE) /,
- NULL);
- }
- }
- //如果不是MM_ISOTROPIC或MM_ANISOTROPIC模式,则xExt和yExt的值表示图像的宽度和
- //高度,单位由mm字段的设置决定。
- }
(5)Windows剪贴板会自动进行老格式和增强型格式之间的转换。是否转换,要看用户从剪贴板请求的文件格式。
第18章 图元文件_18.1 老式图元文件格式(wmf)的更多相关文章
- 第18章 图元文件_18.2 增强型图元文件(emf)(2)
18.2.7 增强型图元文件的查看和打印程序 (1)传递EMF到剪贴板,剪贴板类型应为:CF_ENHMETAFILE (2)CopyEnhMetaFile用于复制图元文件 (3)剪贴板中的图元文件会自 ...
- 第18章 图元文件_18.2 增强型图元文件(emf)(1)
18.2 增强型图元文件(emf) 18.2.1 创建并显示增强型图元文件的步骤 (1)创建:hdcEMF = CreateEnhMetaFile(hdcRef,szFilename,lpRect,l ...
- 第18章 集合框架(2)-Set接口
第18章 集合框架(2)-Set接口 Set是Collection子接口,模拟了数学上的集的概念 Set集合存储特点 1.不允许元素重复 2.不会记录元素的先后添加顺序 Set只包含从Collecti ...
- Java 第18章 多态
18 章 --> 多态 继承: extends 抽象类 abstract (限制类的实例化) 抽象方法 public abstract void show(); //抽象方法只有方法的声明,没 ...
- LPTHW 笨方法学python 18章
看完18章以后,发现第一个练习中,使用了*args读取全部的的输入参数作为一个元组,但是在他的练习中只给了两个变量去赋值,当用户不清楚这个函数的定义时,就可能会给出过多的变量进这个函数,那么就会出现如 ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(2)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- Linux就这个范儿 第18章 这里也是鼓乐笙箫 Linux读写内存数据的三种方式
Linux就这个范儿 第18章 这里也是鼓乐笙箫 Linux读写内存数据的三种方式 P703 Linux读写内存数据的三种方式 1.read ,write方式会在用户空间和内核空间不断拷贝数据, ...
- 【C#4.0图解教程】笔记(第9章~第18章)
第9章 语句 1.标签语句 ①.标签语句由一个标识符后面跟着一个冒号再跟着一条语句组成 ②.标签语句的执行完全如同标签不存在一样,并仅执行冒号后的语句. ③.给语句添加一个标签允许控制从代码的另一部分 ...
随机推荐
- WAF指纹识别和XSS过滤器绕过技巧
[译文] -- “Modern Web Application Firewalls Fingerprinting and Bypassing XSS Filters” 0x1 前言 之前在乌云drop ...
- SharePoint 2013 为用户组自定义EventReceiver
前 言 在SharePoint的开发中,EventReceiver是很重要的一个部分,但是,常常遇到有些需要事件的时候,却没有相应的模板,因为EventReceiver创建时的模板只有那几个,除此之外 ...
- TextView显示颜色高亮的问题
TextView textView = (TextView) findViewById( R.id.tv ); String text = "<font color=\"#d ...
- 电脑公司最新GHOST WIN7系统32,64位优化精简版下载
系统来自系统妈:http://www.xitongma.com 电脑公司最新GHOST win7系统32位优化精简版V2016年3月 系统概述 电脑公司ghost win7 x86(32位)万能装机版 ...
- 在【Xamarin+Prism开发详解三:Visual studio 2017 RC初体验】中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很是感兴趣。于是发时间深入研究了一下Visual Studio 2017RC 是不是和微软Connect()://2016上说得一样神。
总共列出了12点,耐心点慢慢看! 1,添加了不少[代码样式]的设置项目. 通过合理的设置每个人都能写出优美的代码,而且团队项目也可以达到统一代码风格. this首选项:可以设置[字段,属性,方法,事件 ...
- 使用sql server profilter跟踪sql
最近在研究EF延迟加载和贪婪加载的用法时,想要查看Linq生成的sql.一开始通过VS-->调试-->窗口-->IntelliTrace事件,来查看生成的sql,并不是十分准确.然后 ...
- Oracle 外连接和 (+)号的用法
对于外连接,Oracle中可以使用“(+)”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN,下面将配合实例一一介绍.1. LEFT OUTER JOIN:左外关联 SELEC ...
- C#语言——类
C#——类 一.String 类 系统内置的处理字符串类型的函数方法类.方便我们对字符串类型进行一系列的处理. 1.Length:获取字符串的长度,返回一个int类型的值 string x=Conso ...
- MYSQL的JOB
要让JOB顺利运行,必须要打开MYSQL的定时器. -- 查看是否开启定时器 SHOW VARIABLES LIKE '%sche%'; -- 开启定时器 0:off 1:on -- 这个需要最高权限 ...
- mybatis oracle BLOB类型字段保存与读取
一.BLOB字段 BLOB是指二进制大对象也就是英文Binary Large Object的所写,而CLOB是指大字符对象也就是英文Character Large Object的所写.其中BLOB是用 ...