zoukankan      html  css  js  c++  java
  • 如何导出WinForm 控件界面的矢量图

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

      I.  Windows MetaFile.

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

      II. 绘图表面 ( drawing surfaces )

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

      首先我们来创建一个新的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();

      Graphics g2 = Graphics.FromImage(mf);

      调用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);
            }

      到这里已经得到了这个控件的矢量图了。下面附加一段代码把这个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;
            }

      运行这段代码以后, 就可以吧控件的矢量图粘贴到图像编辑软件上面了(CorelDraw, Word, Excel等)。 可以无限放大不失真, 还能够编辑里面的文本哦!

  • 相关阅读:
    Balanced Substring
    解决vscode可以编译通过c++项目,但头文件有红色波浪线的问题
    Poj2299---Ultra-QuickSort
    树状数组
    内置函数
    函数式编程,尾调用,map函数,filter函数,reduce函数
    函数作用域和匿名函数
    函数参数/局部变量与全局变量/前向引用(函数即变量)
    函数的定义
    字符串格式化
  • 原文地址:https://www.cnblogs.com/jacker1979/p/1715482.html
Copyright © 2011-2022 走看看