【发布时间】:2010-03-04 13:55:08
【问题描述】:
我正在做一个自定义控件(继承自 VisualBasic.PowerPacks.LineShape),它应该像标准控件一样绘制,但附近还显示了一个图标。
所以,我只是像这样覆盖了OnPaint:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
base.OnPaint(e);
}
现在,一切正常,但是当我的控件移动时,图标仍然绘制在古老的地方。
有没有办法正确地绘制它?
alt text http://lh4.ggpht.com/_1TPOP7DzY1E/S5gXmp7xYiI/AAAAAAAADHI/pa1OhpKYSoM/Untitled-2.png 真实项目情况
代码:测试示例代码
alt text http://lh6.ggpht.com/_1TPOP7DzY1E/S5jSluxvtDI/AAAAAAAADHw/EUz0Tfet-rw/s800/Capture2.png
using Microsoft.VisualBasic.PowerPacks;
using System.Windows.Forms;
using System.Drawing;
namespace LineShapeTest
{
///
/// Test Form
///
public class Form1 : Form
{
IconLineShape myLine = new IconLineShape();
ShapeContainer shapeContainer1 = new ShapeContainer();
Panel panel1 = new Panel();
public Form1()
{
this.panel1.Dock = DockStyle.Fill;
// load your back image here
this.panel1.BackgroundImage =
global::WindowsApplication22.Properties.Resources._13820t;
this.panel1.Controls.Add(shapeContainer1);
this.myLine.StartPoint = new Point(20, 30);
this.myLine.EndPoint = new Point(80, 120);
this.myLine.Parent = this.shapeContainer1;
MouseEventHandler panelMouseMove =
new MouseEventHandler(this.panel1_MouseMove);
this.panel1.MouseMove += panelMouseMove;
this.shapeContainer1.MouseMove += panelMouseMove;
this.Controls.Add(panel1);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
myLine.StartPoint = e.Location;
}
}
}
///
/// Test LineShape
///
public class IconLineShape : LineShape
{
Icon myIcon = SystemIcons.Exclamation;
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
base.OnPaint(e);
}
}
}
Nota Bene,对于 lineShape:
Parent = ShapeContainer
Parent.Parent = Panel
更新 1 跟踪
在这个 OnPaint 变体中,我们有痕迹:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
Graphics g = Parent.Parent.CreateGraphics();
g.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
base.OnPaint(e);
}
alt text http://lh4.ggpht.com/_1TPOP7DzY1E/S5j29lutQ0I/AAAAAAAADH4/4yEnZd_hPjA/s800/Capture3.png
更新 2 次闪烁
在这个 OnPaint 变体中,我们有一个闪烁的图像:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
Parent.Parent.Invalidate(this.Region, true);
Graphics g = Parent.Parent.CreateGraphics();
g.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
base.OnPaint(e);
}
alt text http://lh5.ggpht.com/_1TPOP7DzY1E/S5j4Bam7hiI/AAAAAAAADIA/1hQWKyV8Fr0/s800/Capture4.png
更新 3:外部失效
这个变体效果很好,但是...来自 IconLineShape 类的外部:
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Region r = myLine.Region;
myLine.StartPoint = e.Location;
panel1.Invalidate(r);
}
}
///
/// Test LineShape
///
public class IconLineShape : LineShape
{
Icon myIcon = SystemIcons.Exclamation;
Graphics parentGraphics;
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
parentGraphics.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
base.OnPaint(e);
}
protected override void OnParentChanged(System.EventArgs e)
{
// Parent is a ShapeContainer
// Parent.Parent is a Panel
parentGraphics = Parent.Parent.CreateGraphics();
base.OnParentChanged(e);
}
}
即使这样解决了测试示例的问题,我还需要在控件内部完成此控件,因为我不能强制此控件的外部“客户端”不要忘记保存旧区域并使父级无效每次换个位置...
【问题讨论】:
-
失效仅发生在您的线路区域(自定义控件)。我看到您在控件的父级上调用 .Invalidate ,但是是在父级或父级的父级上绘制的图标。或者,您的父母是否设置了剪辑区域?
-
我认为您必须使您的 .Parent 无效两次。一次使用图标的旧位置(擦除它),一次使用图标的新位置(绘制它)。
-
@stewbob:我怎么知道父母身上是否有剪报?自定义控件继承自 VisulBasic.PowerPacks.LineShape 控件,该控件有一个 ShapeContainer 作为父级,而作为父级的 ShapeContainer 有一个面板。
-
@serhio:对不起,我以为你也在画父级。我对 PowerPacks.LineShape 一无所知。
-
CW 由于编辑次数。
标签: c# .net vb.net gdi+ powerpacks