调用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;
}
|
参考文章
没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。
本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5845889.html,如需转载请自行联系原作者