电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

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


发布日期:2023/11/20
 

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

I Windows MetaFile

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

II 绘图表面 ( drawing surfaces )

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

首先我们来创建一个新的EMF文件

SystemDrawingImagingMetafile mf;

Graphics g = controlCreateGraphics();

IntPtr hdc = gGetHdc();

mf = new Metafile(hdc new Rectangle( controlWidth controlHeight) MetafileFrameUnitPixel EmfTypeEmfOnly);

gReleaseHdc(hdc);

gDispose();

Graphics g = GraphicsFromImage(mf);

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

const int WM_PRINT = x;

const int PRF_CHECKVISIBLE = x

PRF_NONCLIENT = x

PRF_CLIENT = x

PRF_ERASEBKGND = x

PRF_CHILDREN = x;

[DllImport(userdll CharSet = CharSetAuto)]

private static extern IntPtr SendMessage(HandleRef hWnd int msg int wParam int lParam);

public static void DrawControl(Control control Graphics g)

{

if (!controlCreated)

controlCreateControl();

IntPtr hDc = gGetHdc();

SendMessage(new HandleRef(control controlHandle) WM_PRINT (int)hDc

(int)(PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT));

gReleaseHdc(hDc);

}

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

[DllImport(userdll)]

static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport(userdll)]

static extern bool EmptyClipboard();

[DllImport(userdll)]

static extern IntPtr SetClipboardData(uint uFormat IntPtr hMem);

[DllImport(userdll)]

static extern bool CloseClipboard();

[DllImport(gdidll)]

static extern IntPtr CopyEnhMetaFile(IntPtr hemfSrc IntPtr hNULL);

[DllImport(gdidll)]

static extern bool DeleteEnhMetaFile(IntPtr hemf);

static public bool PutEnhMetafileOnClipboard(IntPtr hWnd Metafile mf)

{

bool bResult = false;

IntPtr hEMF hEMF;

hEMF = mfGetHenhmetafile(); // invalidates mf

if (!hEMFEquals(new IntPtr()))

{

hEMF = CopyEnhMetaFile(hEMF new IntPtr());

if (!hEMFEquals(new IntPtr()))

{

if (OpenClipboard(hWnd))

{

if (EmptyClipboard())

{

IntPtr hRes = SetClipboardData( /*CF_ENHMETAFILE*/ hEMF);

bResult = hResEquals(hEMF);

CloseClipboard();

}

}

} DeleteEnhMetaFile(hEMF);

} return bResult;

}

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

上一篇:如何实现用返回值重载

下一篇:为BlogEngine的分类增加自定义Url别名功能