C# 导出一个控件的矢量图

简介:

  调用Control.DrawToBitmap(Bitmap) 方法是很容易得到控件的图形的。 但是bitmap是栅格化图形。栅格化图形有很多缺点,比如文件体积比较大、 放大后失真、 不易编辑等等。 这里将给出导出一个控件的矢量图的过程。

 

一、两个概念

Windows MetaFile
windows MetaFile 是windows 下面的一种矢量图形格式。 事实上WMF 只是记录下来的一串GDI 命令,重新调用一次这一串GDI命令就可以重建之前记录下来的图像。而大部分windows应用程序的界面都是用GDI绘制的,所以理论上都可以导出他们 界面的矢量图。 详细去看:http://en.wikipedia.org/wiki/Windows_Metafile

绘图表面 ( drawing surfaces )
用GDI+绘图的时候,基本上你会把图形绘制到 屏幕上的窗体、传到打印机的打印文档、内存里的图像文件等等。 这些叫做绘图表面。

 

二、导出的基本过程

2.1 首先创建一个新的EMF文件

1
2
3
4
5
6
System.Drawing.Imaging.Metafile mf;
Graphics g1 = control.CreateGraphics();
IntPtr hdc = g1.GetHdc();
mf =  new  Metafile(hdc,  new  Rectangle(0, 0, control.Width, control.Height), MetafileFrameUnit.Pixel, EmfType.EmfOnly);
g1.ReleaseHdc(hdc);
g1.Dispose();

 2.2 将控件上的内容打印到Graphics 对象上

调用WinApi把控件打印到此Graphics 对象上面。这个Graphics对象会作为参数传递给下面一级一级的子控件的OnPaint()函数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const  int  WM_PRINT = 0x0317;
 
const  int  PRF_CHECKVISIBLE = 0x00000001,
PRF_NONCLIENT = 0x00000002,
PRF_CLIENT = 0x00000004,
PRF_ERASEBKGND = 0x00000008,
PRF_CHILDREN = 0x00000010;
[DllImport( "user32.dll" , CharSet = CharSet.Auto)]
private  static  extern  IntPtr SendMessage(HandleRef hWnd,  int  msg,  int  wParam,  int  lParam);
 
public  static  void  DrawControl(Control control, Graphics g)
{
     if  (!control.Created)
          control.CreateControl();
 
     IntPtr hDc = g.GetHdc();
     SendMessage( new  HandleRef(control, control.Handle), WM_PRINT, ( int )hDc,( int )(PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT));
     g.ReleaseHdc(hDc);
}

 2.3  将EMF复制到剪切板上

 到这里已经得到了这个控件的矢量图了。下面附加一段代码把这个EMF复制到剪切板上面去.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[DllImport( "user32.dll" )]
static  extern  bool  OpenClipboard(IntPtr hWndNewOwner);
[DllImport( "user32.dll" )]
static  extern  bool  EmptyClipboard();
[DllImport( "user32.dll" )]
static  extern  IntPtr SetClipboardData( uint  uFormat, IntPtr hMem);
[DllImport( "user32.dll" )]
static  extern  bool  CloseClipboard();
[DllImport( "gdi32.dll" )]
static  extern  IntPtr CopyEnhMetaFile(IntPtr hemfSrc, IntPtr hNULL);
[DllImport( "gdi32.dll" )]
static  extern  bool  DeleteEnhMetaFile(IntPtr hemf);
 
static  public  bool  PutEnhMetafileOnClipboard(IntPtr hWnd, Metafile mf)
{
     bool  bResult =  false ;
     IntPtr hEMF, hEMF2;
     hEMF = mf.GetHenhmetafile();  // invalidates mf
     if  (!hEMF.Equals( new  IntPtr(0)))
     {
         hEMF2 = CopyEnhMetaFile(hEMF,  new  IntPtr(0));
         if  (!hEMF2.Equals( new  IntPtr(0)))
         {
             if  (OpenClipboard(hWnd))
             {
                 if  (EmptyClipboard())
                 {
                     IntPtr hRes = SetClipboardData(14  /*CF_ENHMETAFILE*/ , hEMF2);
                     bResult = hRes.Equals(hEMF2);
                     CloseClipboard();
                 }
             }
         } DeleteEnhMetaFile(hEMF);
     return  bResult;
}

 

 

 

 

 

 

参考文章

1. 如何导出WinForm 控件界面的矢量图

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。






    本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5845889.html,如需转载请自行联系原作者

相关文章
|
C# 数据库 开发者
44.c#:combobox控件
44.c#:combobox控件
240 1
|
SQL 开发框架 .NET
C#一分钟浅谈:数据绑定与数据源控件
在Web开发中,数据绑定和数据源控件是实现动态网页的关键技术。本文从基础概念入手,详细讲解数据绑定的原理及其在ASP.NET中的应用,并介绍常见数据绑定方式:手动绑定和自动绑定。接着,文章重点介绍了ASP.NET中的数据源控件,如`SqlDataSource`、`ObjectDataSource`、`XmlDataSource`和`LinqDataSource`,并通过具体示例演示如何使用`SqlDataSource`和`GridView`进行数据绑定。最后,还列举了一些常见问题及其解决办法,帮助读者更好地理解和应用这些技术。
191 4
|
SQL C# 数据库
EPPlus库的安装和使用 C# 中 Excel的导入和导出
本文介绍了如何使用EPPlus库在C#中实现Excel的导入和导出功能。首先,通过NuGet包管理器安装EPPlus库,然后提供了将DataGridView数据导出到Excel的步骤和代码示例,包括将DataGridView转换为DataTable和使用EPPlus将DataTable导出为Excel文件。接着,介绍了如何将Excel数据导入到数据库中,包括读取Excel文件、解析数据、执行SQL插入操作。
EPPlus库的安装和使用 C# 中 Excel的导入和导出
|
11月前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
103 1
|
C# Windows
49.c#:StatusStrip 控件
49.c#:StatusStrip 控件
374 1
49.c#:StatusStrip 控件
|
SQL 存储 Oracle
C# Web控件与数据感应之 Control 类
C# Web控件与数据感应之 Control 类
|
SQL 存储 C#
C# Web控件与数据感应之 TreeView 类
C# Web控件与数据感应之 TreeView 类
|
SQL 存储 Oracle
C# Web控件与数据感应之 CheckBoxList 类
C# Web控件与数据感应之 CheckBoxList 类
|
SQL 存储 Oracle
C# Web控件与数据感应之 ListControl 类
C# Web控件与数据感应之 ListControl 类