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

本文介绍了一种方法,通过使用.NET Framework的绘图功能将WinForm控件的内容导出为Windows Metafile (WMF) 格式的矢量图像。此过程包括创建EMF文件、将控件内容绘制到Graphics对象上以及将EMF复制到剪贴板等步骤。

 

  调用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文件

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()函数中。

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复制到剪切板上面去.

        [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 控件界面的矢量图

 

转载于:https://www.cnblogs.com/arxive/p/5845889.html

21世纪什么最重要?通用!想让你的控件和主流软件共享同一种编辑结果吗,那就选择我吧!国内唯一全面基于国际矢量图形标准SVG的专业开发控件,提供全面的矢量编辑能力,能适应组态软件和其他形软件开发需要。能够和其他主流的编辑软件如illustrator,Visio等共享最终编辑结果。使用VectorControl.Net,您可以:> 基本形状绘制,支持圆、椭圆、矩形、正方形、直线、多边形、折线的绘制> 像和文本构造,支持导入像和文本构造> 扩展形状绘制,支持星形形状和扇形的构造> 钢笔工具绘制,支持任意形状的曲线构造(贝赛尔曲线)> 二维变换,支持缩放、扭曲、平移和旋转等二维变换,并可以启用或禁用这些操作。> 形的成组和解组> 形的层次调整> 支持多个形之间的对齐> 支持多个形之间的分布功能> 调整多个形的尺寸以达到相同高度或宽度> 网格、参考线、标尺等完整视环境并支持吸附。> 支持外部自定义形状和元文件,给与用户自由扩展功能的能力,并能将当前绘内容导出为形状和元> 支持连接线,可以在对象之间保持联系> 无限制的撤销/重作> 支持SVG文件的导入> Bmp,Jpg,Gif,Tiff等多种栅格像格式的导出> SVG文件代码预览> VectorControl.Net还提供了许多Windows界面开发组件,包括弹出菜单时容器,形状和组件库选择器等> 打印支持> 两套完整的示例程序以及源代码(C#和VB.Net),全面全面展现了如何利用VectorControl.Net控件实现简单的矢量应用(不需要任何手工编码实现SVG浏览器)和利用VectorControl实现一个完整的矢量编辑环境(具备所有矢量图形编辑功能)的能力,您甚至可以直接将我们提供的示例程序用作您默认的矢量图形的编辑器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值