GDI+编程经验:滚动条、缩放、绘制闪烁
2010-04-21 09:37
295 查看
我们在使用GDI+实现类似画图板这样的系统时,经常需要支持平移、滚动条、缩放等功能、解决绘制时的闪烁,对于缺乏GDI+开发经验的朋友,经常
会在这些问题上纠缠一段或长或短的时间。在这里,我将自己的经验小结一下,给后来的朋友作个参考。
1.如何解决绘制闪烁?
(1)所有的绘制动作都应该Paint事件中完成。
比如,即使我们要拖动一个View
object,通常在MouseMove事件中处理拖动行为,但是不要在MouseMove事件中调用Graphics.Draw方法,而是应该采用
Command模式,将要绘制的动作封装为一个对象,传递到下一次的Paint事件中再绘制。
(2)设置双缓冲。
通常我们会选择在某个控件的表面进行绘制,那么在初始化时,可以通过执行下面的代码来启用双缓冲:
this
.SetStyle(
ControlStyles
.OptimizedDoubleBuffer
|
ControlStyles
.AllPaintingInWmPaint
|
ControlStyles
.UserPaint,
true
);
注意,SetStyle是一个Control基类的一个Protected方法,也就是说,只能在其派生类中才能调用该方法。
通常,我是定义一个从Control继承的自定义控件,然后在构造方法中进行双缓冲设置,如:
public
partial
class
ViewPanel
:
UserControl
{
public
ViewPanel()
{
InitializeComponent();
this
.SetStyle(
ControlStyles
.OptimizedDoubleBuffer
|
ControlStyles
.AllPaintingInWmPaint
|
ControlStyles
.UserPaint,
true
);
}
}
(3)重新绘制发生变化的区域,而不是整个区域全部重绘。
Control的Invalidate方法有一个重载接收Region
类
型的参数,表示下次paint时要重绘的区域。比如,当我们拖动一个对象时,只需要重绘比这个对象的Bounds大一点的区域即可。
2.滚动条与缩放
当需要支持滚动条和缩放时,就需要采用一系列的坐标变换来正确的记录坐标和绘制图像,这些过程是比较繁琐的。幸运的是,GDI+能为我们减轻一
部分这方面的负担。当绘制view
object时,只要我们指定Graphics对象的几个参数,Graphics对象就会自动采用正确的比例和偏移来绘制所有的view
object了。比如:
//Graphics g ;
g.PageUnit
=
GraphicsUnit
.Pixel;
//
GraphicsUnit.Pixel才支持缩放与偏移绘制。
g.TranslateTransform(
this
.hScrollValue,
this
.vScrollValue); //设置滚动条的当前位置
g.PageScale
=
this
.Scale; //
设置缩放比例
g.Draw(......);
会在这些问题上纠缠一段或长或短的时间。在这里,我将自己的经验小结一下,给后来的朋友作个参考。
1.如何解决绘制闪烁?
(1)所有的绘制动作都应该Paint事件中完成。比如,即使我们要拖动一个View
object,通常在MouseMove事件中处理拖动行为,但是不要在MouseMove事件中调用Graphics.Draw方法,而是应该采用
Command模式,将要绘制的动作封装为一个对象,传递到下一次的Paint事件中再绘制。
(2)设置双缓冲。
通常我们会选择在某个控件的表面进行绘制,那么在初始化时,可以通过执行下面的代码来启用双缓冲:
this
.SetStyle(
ControlStyles
.OptimizedDoubleBuffer
|
ControlStyles
.AllPaintingInWmPaint
|
ControlStyles
.UserPaint,
true
);
注意,SetStyle是一个Control基类的一个Protected方法,也就是说,只能在其派生类中才能调用该方法。
通常,我是定义一个从Control继承的自定义控件,然后在构造方法中进行双缓冲设置,如:
public
partial
class
ViewPanel
:
UserControl
{
public
ViewPanel()
{
InitializeComponent();
this
.SetStyle(
ControlStyles
.OptimizedDoubleBuffer
|
ControlStyles
.AllPaintingInWmPaint
|
ControlStyles
.UserPaint,
true
);
}
}
(3)重新绘制发生变化的区域,而不是整个区域全部重绘。
Control的Invalidate方法有一个重载接收Region
类
型的参数,表示下次paint时要重绘的区域。比如,当我们拖动一个对象时,只需要重绘比这个对象的Bounds大一点的区域即可。
2.滚动条与缩放
当需要支持滚动条和缩放时,就需要采用一系列的坐标变换来正确的记录坐标和绘制图像,这些过程是比较繁琐的。幸运的是,GDI+能为我们减轻一部分这方面的负担。当绘制view
object时,只要我们指定Graphics对象的几个参数,Graphics对象就会自动采用正确的比例和偏移来绘制所有的view
object了。比如:
//Graphics g ;
g.PageUnit
=
GraphicsUnit
.Pixel;
//
GraphicsUnit.Pixel才支持缩放与偏移绘制。
g.TranslateTransform(
this
.hScrollValue,
this
.vScrollValue); //设置滚动条的当前位置
g.PageScale
=
this
.Scale; //
设置缩放比例
g.Draw(......);
相关文章推荐
- GDI+编程经验:滚动条、缩放、绘制闪烁
- GDI+编程经验:滚动条、缩放、绘制闪烁
- Delphi下的GDI+编程[8] 绘制弧形-DrawArc
- C#中使用GDI+绘制形状时自动缩放文本
- GDI+ 绘制经验
- Delphi下的GDI+编程[4] 绘制直线-虚线样式
- Delphi下的GDI+编程[9] 绘制椭圆-DrawEllipse
- GDI+绘制矩形,并且实现可旋转、缩放、移动功能(基于MFC对话框)
- Delphi下的GDI+编程[5] 绘制直线-自定义虚线
- 基于mschart控件,绘制工控采集类曲线,可对图像进行缩放,拖动滚动条显示放大后的图像
- Delphi下的GDI+编程[10] 绘制饼形-DrawPie
- Delphi下的GDI+编程[6] 绘制矩形-DrawRectangle
- OpenGL绘制纹理,缩放相机导致纹理闪烁的解决方法gluPerspective ()
- GDI+编程---图形绘制概述
- Delphi下的GDI+编程[2] DrawLine - 绘制直线
- Delphi下的GDI+编程[3] 绘制直线-线帽
- 使用gdi+绘制缩放位图的问题
- 基于mfc的对话框编程中,实现控件随对话框大小自动缩放以及通过滚动条实现控件移动功能
- 利用 GDI+ 绘制旋转的太极
- 编程经验系列-Java学习杂谈(十)--Struts2