我正在做一个自定义控件(继承自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 真实项目情况
CODE:测试的示例代码
替代文字 http://lh6.ggpht.com/_1TPOP7DzY1E/S5jSluxvtDI/AAAAAAADHw/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);
}        
替代文字 http://lh4.ggpht.com/_1TPOP7DzY1E/S5j29lutQ0I/AAAAAAADH4/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);
}  
替代文字 http://lh5.ggpht.com/_1TPOP7DzY1E/S5j4Bam7hiI/AAAAAAADIA/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);
    }
}
即使这样解决了测试示例的问题,我也需要在控件内部完成此控件,因为我不能强制此控件的外部“客户端”不要忘记保存旧区域并在每次更改时使父级无效一个位置...