博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 导出一个控件的矢量图
阅读量:6679 次
发布时间:2019-06-25

本文共 2800 字,大约阅读时间需要 9 分钟。

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

 

一、两个概念

Windows MetaFile

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

绘图表面 ( 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. 。

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。
    本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5845889.html,如需转载请自行联系原作者
你可能感兴趣的文章
c# 判断文件是否发生了变化
查看>>
Remove menucool tooltip trial version
查看>>
模板 数据结构
查看>>
【Search a 2D Matrix】cpp
查看>>
POJ 1741 Tree(树的点分治,入门题)
查看>>
Opencv3.1.0 & Win10/Win7 64位 contrib编译
查看>>
MPMoviePlayerController播放远程视频存在问题
查看>>
List/Vector
查看>>
黄聪:FFmpeg 使用指南
查看>>
能否不同udp socket绑定到同一IP地址和port
查看>>
C#:CodeSmith根据数据库中的表创建C#数据模型Model + 因为没有钱买正版,所以附加自己写的小代码...
查看>>
乐视4.14硬件免费日de用户体验
查看>>
有选择的复制对象,即根据客户端传值来复制对象属性值
查看>>
随机输入一个数字,判断这个数字是不是5的倍数
查看>>
C — 对C语言的认识
查看>>
linkin大话数据结构--Set
查看>>
接口測试-HAR
查看>>
$.each 和$(selector).each()的区别
查看>>
45435
查看>>
JSON格式自动解析遇到的调用方法问题.fromJson() ..readValue()
查看>>