0

私はカスタムコントロール(から継承VisualBasic.PowerPacks.LineShape)を実行しています。これは標準のコントロールと同じようにペイントする必要がありますが、その近くにアイコンが表示されています。

だから、私はこのようにオーバーライドOnPaintしました:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    e.Graphics.DrawIcon(myIcon, StartPoint.X, StartPoint.Y);
    base.OnPaint(e);
}

これですべて問題ありませんが、コントロールが移動しても、アイコンは古い場所に描画されたままになります。

正しくペイントする方法はありますか?

代替テキストhttp://lh4.ggpht.com/_1TPOP7DzY1E/S5gXmp7xYiI/AAAAAAAADHI/pa1OhpKYSoM/Untitled-2.png 実際のプロジェクトの状況

CODE:テスト用のサンプルコード

代替テキスト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);
}        

代替テキスト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);
}  

代替テキスト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);
    }
}

これでテスト例の問題は解決しますが、このコントロールをコントロール内で実行する必要があります。このコントロールの外部の「クライアント」は、変更するたびに古い領域を保存して親を無効にすることを忘れないでください。場所...

4

6 に答える 6

1

バッファをクリアしてみましたか(背景色で塗りつぶしの長方形を描画します)?また、クリッピング領域をコントロールのサイズにリセットしてから、アイコンを描画してから、親のペイントを呼び出してください。

于 2010-03-08T10:12:34.853 に答える
1

フォームの次の機能を変更して、アイコンが前にあったバッファを無効にし、それによって残りを削除してみてください(アンテステコード):

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Point oldPos = myLine.StartPoint;
            myLine.StartPoint = e.Location;
            this.Invalidate(new Recangle(oldPos.X, oldPos.Y, myLine.Width, myLine.Height));
        }
    }

これが機能しない場合は、次を試してください。

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            myLine.StartPoint = e.Location;
            this.Refresh();
        }
    }

この方法は、パフォーマンスの問題(バッファ全体がクリアされる)のために推奨されない場合がありますが、他に何も機能していません...

于 2010-03-11T15:19:46.477 に答える
1

別の完全に異なる(うまくいけば再び機能する:-)ソリューションを追加するだけです。「コードはクラス内にある必要がある」という要件を認識していなかったため、これがフォローアップです。

公理: OnPaintInvalidate()またはRefresh()OnPaintBackgroundを呼び出さないでください。これは、(常に)無限ループになるためです。

だから私たちは彼らのために別の場所を見つけなければなりません。Visual Studio内でクラスをコンパイルしようとしましたが、クラスLineShapeが見つかりませんでした(Microsoft.VisualBasic.PowerPacks.Vs.dllはうまくいきませんでした)。そのため、コードをテストしません。

私は何をしましたか?

  1. FormからMouseMoveハンドラーを削除し、IconLineShapeクラス内に配置しました。顧客がドラッグアンドドロップを希望する場合は問題ないので、大丈夫です。説明されている解決策の1つを試してください。
  2. IconLineShapeでドラッグアンドドロップを無効にするプロパティを追加しました(顧客がそれでうまくいかない場合:-)。ドラッグアンドドロップがなければ、そもそも問題は発生しません。

-

    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;

           this.Controls.Add(panel1);
       }
   }

   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);
       }

       protected override void OnMouseMove(MouseEventArgs e)
       {
           if (draggable && 
               e.Button == MouseButtons.Left &&
               !this.StartPoint.Equals(e.Location))
           {
               Region r = this.Region.Clone();

               this.StartPoint = e.Location;

               // try solution 1
               this.Invalidate(r);

               // solution 2; walk up to the upmost parent and refresh
               // as said before, this.Invalidate() is to be preferred
               Control currentParent = this.Parent;
               while (currentParent.Parent != null)
               {
                   currentParent = currentParent.Parent;
               }
               currentParent.Refresh();
           } 
       }

       private bool draggable = true;

       public bool Draggable
       {
           get { return this.draggable; }
           set { this.draggable = value; }
       }
   }

フィードバックをお願いします。

于 2010-03-11T21:41:25.393 に答える
0

カスタムコントロールでこれを行いましたか?

「ストロボスコープ」効果を削除するには

Public Sub New()
    Me.SetStyle(ControlStyles.ResizeRedraw Or _
                ControlStyles.DoubleBuffer Or _
                ControlStyles.UserPaint Or _
                ControlStyles.AllPaintingInWmPaint, _
                True)
    Me.UpdateStyles()

End Sub
于 2010-03-10T14:12:59.157 に答える
0

最後に、PictureBox自分でアイコンを描く代わりに追加することになりました。

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.BackColor = Color.White;
            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;
        PictureBox pictureBox = new PictureBox();

        public IconLineShape()
        {
            pictureBox.Image = Bitmap.FromHicon(myIcon.Handle);
            pictureBox.Size = myIcon.Size;
            pictureBox.Visible = true;
        }

        protected override void OnMove(System.EventArgs e)
        {
            base.OnMove(e);
            pictureBox.Location = this.StartPoint;
        }

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            pictureBox.Invalidate();
        }

        public override bool HitTest(int x, int y)
        {            
            return base.HitTest(x, y) |
                pictureBox.RectangleToScreen(
                    pictureBox.DisplayRectangle).Contains(new Point(x, y));
        }

        protected override void OnParentChanged(System.EventArgs e)
        {
            // Parent is a ShapeContainer
            // Parent.Parent is a Panel
            pictureBox.Parent = Parent.Parent;
            base.OnParentChanged(e);
        }
    }
}

参加してくれてありがとう!

于 2010-03-04T16:46:40.490 に答える
-1

これは役に立ちますか?LineShapeに追いついているようです。私にとって、RectangleShapeから派生することはより理にかなっています。私は細部を世話するヘルパーですべてを包みました。このヘルパーは、「複合コントロール」を作成せずにコントロールを関連付けるために使用する標準的な手法です。これは通常、より簡単です。

using Microsoft.VisualBasic.PowerPacks;
using System.Windows.Forms;
using System.Drawing;

namespace LineShapeTest {

    public partial class Form1 : Form {

        /*  Designer support through
         *  Create Panel
         *  Set panel's background image
         *  Add LineShape
         *  Add IconShape
         *  Create IconicLineShapeHelper
         */
        public Form1() {
            InitializeComponent();
            IconicLineShapeHelper arbitrary1 = new IconicLineShapeHelper(lineShape1, iconShape1);
            IconicLineShapeHelper arbitrary2 = new IconicLineShapeHelper(lineShape2, iconShape2);
        }

        private Panel panel1;
        private ShapeContainer shapeContainer1;
        private LineShape lineShape1;
        private IconShape iconShape1;
        private ShapeContainer shapeContainer2;
        private LineShape lineShape2;
        private IconShape iconShape2;

    #region [ Form1.Designer.cs ]
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        private void InitializeComponent() {
            this.lineShape1 = new Microsoft.VisualBasic.PowerPacks.LineShape();
            this.panel1 = new System.Windows.Forms.Panel();
            this.shapeContainer1 = new Microsoft.VisualBasic.PowerPacks.ShapeContainer();
            this.iconShape1 = new LineShapeTest.IconShape();
            this.shapeContainer2 = new Microsoft.VisualBasic.PowerPacks.ShapeContainer();
            this.lineShape2 = new Microsoft.VisualBasic.PowerPacks.LineShape();
            this.iconShape2 = new LineShapeTest.IconShape();
            this.panel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // lineShape1
            // 
            this.lineShape1.Name = "lineShape1";
            this.lineShape1.X1 = 13;
            this.lineShape1.X2 = 88;
            this.lineShape1.Y1 = 11;
            this.lineShape1.Y2 = 34;
            // 
            // panel1
            // 
            this.panel1.BackgroundImage = global::LineShapeTest.Properties.Resources._13820t;
            this.panel1.Controls.Add(this.shapeContainer1);
            this.panel1.Location = new System.Drawing.Point(27, 24);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(162, 122);
            this.panel1.TabIndex = 1;
            // 
            // shapeContainer1
            // 
            this.shapeContainer1.Location = new System.Drawing.Point(0, 0);
            this.shapeContainer1.Margin = new System.Windows.Forms.Padding(0);
            this.shapeContainer1.Name = "shapeContainer1";
            this.shapeContainer1.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
            this.iconShape1,
            this.lineShape1});
            this.shapeContainer1.Size = new System.Drawing.Size(162, 122);
            this.shapeContainer1.TabIndex = 0;
            this.shapeContainer1.TabStop = false;
            // 
            // iconShape1
            // 
            this.iconShape1.BorderStyle = System.Drawing.Drawing2D.DashStyle.Custom;
            this.iconShape1.Location = new System.Drawing.Point(88, 64);
            this.iconShape1.Name = "iconShape1";
            this.iconShape1.Size = new System.Drawing.Size(32, 32);
            // 
            // shapeContainer2
            // 
            this.shapeContainer2.Location = new System.Drawing.Point(0, 0);
            this.shapeContainer2.Margin = new System.Windows.Forms.Padding(0);
            this.shapeContainer2.Name = "shapeContainer2";
            this.shapeContainer2.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
            this.iconShape2,
            this.lineShape2});
            this.shapeContainer2.Size = new System.Drawing.Size(292, 266);
            this.shapeContainer2.TabIndex = 2;
            this.shapeContainer2.TabStop = false;
            // 
            // lineShape2
            // 
            this.lineShape2.Name = "lineShape2";
            this.lineShape2.X1 = 48;
            this.lineShape2.X2 = 123;
            this.lineShape2.Y1 = 187;
            this.lineShape2.Y2 = 210;
            // 
            // iconShape2
            // 
            this.iconShape2.Location = new System.Drawing.Point(136, 220);
            this.iconShape2.Name = "iconShape2";
            this.iconShape2.Size = new System.Drawing.Size(75, 23);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.shapeContainer2);
            this.Name = "Form1";
            this.Text = "Form1";
            this.panel1.ResumeLayout(false);
            this.ResumeLayout(false);

        }
        #endregion
    }
    #endregion

    public class IconicLineShapeHelper {
        ShapeContainer _container;
        LineShape _line;
        IconShape _icon;
        public IconicLineShapeHelper(LineShape line, IconShape icon) {
            _container = line.Parent;
            _line = line;
            _icon = icon;
            _container.MouseMove += new MouseEventHandler(_container_MouseMove);
        }
        void _container_MouseMove(object sender, MouseEventArgs e) {
            if (e.Button == MouseButtons.Left) {
                _line.StartPoint = e.Location;
                _icon.Location = e.Location;
            }
        }
    }
    public class IconShape : RectangleShape {
        Icon _icon = SystemIcons.Exclamation;
        public IconShape() {
            this.Size = new System.Drawing.Size(32, 32);
            this.BorderStyle = System.Drawing.Drawing2D.DashStyle.Custom;
        }
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
            e.Graphics.DrawIcon(_icon, this.Location.X, this.Location.Y);
            base.OnPaint(e);
        }
    }
}
于 2010-03-11T21:08:22.073 に答える