Помогите перекрасить линию

Я делаю настраиваемый элемент управления (унаследованный от 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 Реальная ситуация с проектом

КОД: пример кода для тестов.

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 TRACES

В этом варианте 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);
    }
}

Даже это решает проблему тестового примера, мне нужно, чтобы этот элемент управления выполнялся внутри элемента управления, потому что я не могу заставить внешних «клиентов» этого элемента управления не забывать сохранять старую область и аннулировать родительский элемент каждый раз при изменении местоположение...


person Community    schedule 04.03.2010    source источник
comment
Аннулирование происходит только в области вашей строки (настраиваемый элемент управления). Я вижу, что вы вызываете .Invalidate для родительского элемента вашего элемента управления, но это значок, нарисованный на родительском элементе или родительском элементе родительского элемента. Или для вашего родителя установлена ​​область отсечения?   -  person Stewbob    schedule 04.03.2010
comment
Я думаю, вам нужно дважды аннулировать свой .Parent. Один раз со старым местоположением значка (для его стирания) и один раз с новым местоположением значка (для его рисования).   -  person Stewbob    schedule 04.03.2010
comment
@stewbob: как я могу узнать, есть ли у родителя отсечение или нет? настраиваемый элемент управления унаследован от элемента управления VisulBasic.PowerPacks.LineShape, у которого в качестве родительского элемента есть ShapeContainer, а у ShapeContainer в качестве родительского элемента есть панель.   -  person serhio    schedule 05.03.2010
comment
@serhio: Извините, я предполагал, что вы тоже рисуете родителя. Я ничего не знаю о PowerPacks.LineShape.   -  person Stewbob    schedule 05.03.2010
comment
Возможно, VisualBasic.PowerPacks.LineShape не раскрашен так, как должен быть. Из описания на странице msdn.microsoft.com/en-us/vbasic/bb735936. aspx он говорит, что помогает рисовать элементы, не уверенный в их перемещении.   -  person call me Steve    schedule 11.03.2010
comment
@ Стив: Неважно. вы можете унаследовать Winform Label или TextBox (элементы управления) аналогичным образом: LabelWithIcon : Label. Я унаследовал LineShape (компонент).   -  person serhio    schedule 11.03.2010
comment
CW из-за количества правок.   -  person AMissico    schedule 11.03.2010
comment
Я увидел заголовок Help Repainting a Line, затем посмотрел, написал ли его Том Сойер ... :)   -  person Mark Schultheiss    schedule 12.03.2010
comment
Почему, черт возьми, здесь все так плохо проигрывают?   -  person mlvljr    schedule 22.03.2010


Ответы (6)


Вы пробовали очистить буфер (нарисовать прямоугольник заливки с цветом фона)? Также не забудьте сбросить области обрезки до размера вашего элемента управления, затем нарисуйте свой значок и затем вызовите рисование родителей.

person Johannes Rudolph    schedule 08.03.2010
comment
не могли бы вы посоветовать, как я могу сбросить регионы отсечения? - person serhio; 11.03.2010

попробуйте изменить следующую функцию вашей формы, чтобы аннулировать буфер, в котором раньше находился значок, и тем самым удалить остальное (непроверенный код):

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

Этот метод не может быть рекомендован из-за проблем с производительностью (весь буфер очищается), но больше ничего не работает ...

person Community    schedule 11.03.2010
comment
@henchman: Спасибо, это сработало, посмотрите мое обновление 3. Однако я не могу оставить эту логику вне контроля, мне нужно, чтобы сам элемент управления правильно перерисовывался. - person serhio; 11.03.2010
comment
@serhio: когда вы рисуете линию, запишите позицию в другой переменной. Затем, в следующий раз, когда вы будете рисовать, если положение будет другим, вы можете аннулировать старую область. - person John Fisher; 11.03.2010
comment
@John: см. Обновление 2. Когда я аннулирую старую область, которая может пересекать новую, начинается бесконечный цикл перерисовки. - person serhio; 11.03.2010
comment
@serhio: У вас вообще не должно получиться бесконечного цикла перекраски. Даже не выполняя работу, чтобы убедиться, что вы не аннулируете часть, которую собираетесь нарисовать. Почему? Потому что вы должны проверить, нарисовали ли вы линию в текущей позиции. Если линия не переместилась, и вы ее перерисовываете, вам не нужно аннулировать старую позицию. - person John Fisher; 12.03.2010

просто добавляю еще одно, совершенно другое (надеюсь, снова работающее :-) решение. Поскольку я не знал о требовании «код должен находиться внутри класса», это продолжение.

Аксиома: НИКОГДА не вызывайте Invalidate() или Refresh() в OnPaint или OnPaintBackground, потому что вы (всегда) окажетесь в бесконечный цикл.

Поэтому нам нужно найти для них другое место. Я попытался скомпилировать ваши классы в Visual Studio, но мне не удалось найти класс LineShape (Microsoft.VisualBasic.PowerPacks.Vs.dll не помогло), поэтому снова непроверенный код.

что я сделал?

  1. Удален обработчик MouseMove из формы и помещен в класс IconLineShape. Все будет в порядке, потому что, если клиент хочет перетащить его, все в порядке. Попробуйте одно из описанных решений.
  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; }
       }
   }

Пожалуйста, оставьте отзыв.

person Community    schedule 11.03.2010
comment
MS PowerPacks (2,7 МБ) msdn.microsoft.com/en-us/vbasic/ bb735936.aspx не включены в платформу .NET, поэтому должны устанавливаться отдельно. MouseMove не будет работать с lineShape, причина очень тонкая, и когда пользователь быстро перемещает мышь, линия теряется, и событие mousemove заканчивается. - person serhio; 12.03.2010
comment
это было бы странно. не может быть разницы, перезаписываете ли вы onmousemove-метод или назначаете обработчик события mousemove «извне», поскольку этот обработчик событий вызывается только так, как это делает onmousemove. ты это тестировал? - person Phil Rykoff; 12.03.2010
comment
ShapeContainer обнаруживает движения мыши только тогда, когда указатель мыши находится над содержащимися фигурами (в нашем случае одна линия). Итак, чтобы переместить линию, используя только ShapeContainer mouseMove, мы должны перемещать указатель мыши очень медленно - не покидая области линии. - person serhio; 12.03.2010

вы сделали это на настраиваемом элементе управления?

убрать эффекты «стробоскопа»

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

End Sub
person Community    schedule 10.03.2010
comment
к сожалению, базовый класс (PowerPacks.LineShape) не имеет такого метода (SetStyle) - person serhio; 11.03.2010

Наконец, закончилось тем, что я добавил 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);
        }
    }
}

Спасибо всем за участие!

person serhio    schedule 04.03.2010
comment
Вам не нужен метод OnPaint. Обратите внимание, что фон PictureBox закрашивает вашу линию. Удалите OnPaint и вызовите pictureBox.Invalidate () после pictureBox.Location = this.StartPoint; Это решит проблему. - person AMissico; 16.03.2010
comment
Вызов pictureBox.Invalidate (); в OnPaint - не лучшая идея, как отмечают приспешники. - person AMissico; 16.03.2010
comment
pictureBox.Image = Bitmap.FromHicon (myIcon.Handle); не лучшая идея. Этот метод предназначен для создания растровых изображений из дескрипторов, возвращаемых Windows API. Вам следует использовать SystemIcons.Exclamation.ToBitmap (); Вам не нужно поддерживать значок. Это поможет сэкономить ресурсы - person AMissico; 16.03.2010
comment
@AMissico: если я не вызываю pictureBox.Invalidate (), я вижу следы линий поверх изображения. Это потому, что я это называю. Что касается значка, то в реальном проекте я, конечно же, не использую SystemIconsExcamation, а использую пользовательский значок, предназначенный только для демонстрационных целей. - person serhio; 17.03.2010
comment
@serhio: в вашем примере кода вы должны вызвать Invalidate, потому что вы не связываете PictureBox с коллекцией элементов управления. Я предлагаю вам вызвать Invalidate только после установки местоположения графического окна. Это устранит необходимость в OnPaint и решит проблему рисования графическим блоком поверх формы линии. - person AMissico; 17.03.2010
comment
@AMissico: Почему я не связываю pictureBox с коллекцией элементов управления? Я делаю это: pictureBox.Parent = Parent.Parent; (это перенесет pictureBox в коллекцию элементов управления Panel). Что касается Invaliadting после смены местоположения - возможно, если это местоположение не будет установлено несколько раз в разных местах. - person serhio; 18.03.2010
comment
@serhio; Ах, я вижу, что вы сейчас делаете. - person AMissico; 18.03.2010
comment
Вы замечали, что за принятые ответы без видимых причин резко падает количество голосов? - person AMissico; 18.03.2010

Это помогает? Похоже, вы слишком увлечены 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);
        }
    }
}
person Community    schedule 11.03.2010
comment
Спасибо за идею. Однако LineShape необходимо. См. Добавленный мной экран реального проекта. Пользователь может перемещать линии, а не прямоугольники (здесь LineShape используется для проверки результатов - щелчки, наведение курсора - всплывающая подсказка и логика перерисовки - прозрачность) - person serhio; 12.03.2010
comment
Я все еще использую LineShape. Я только связываю значок с линией. Вспомогательный класс только поддерживает перемещение значка вместе с линией. RectangeShape умеет правильно обновлять фон при движении. Следовательно, это хороший кандидат для наследования. - person AMissico; 12.03.2010
comment
Вы все еще можете использовать IconLineShape. Просто создайте IconShape и IconicLineShapeHelper в конструкторе для внутреннего использования. - person AMissico; 12.03.2010
comment
Я понимаю. Следует отметить, что контейнер как ShapeContainer не подходит для управления событиями MouseMove, потому что MouseCursor легко покидает область тонкой линии и движущиеся концы. Я думаю, что просто добавлю PictureBox, наконец :) Я даже тестировал и вроде работает. - person serhio; 12.03.2010
comment
Я как можно лучше продублировал то, что у вас было, и старался сделать это как можно более простым и гибким. Я подумал, что когда у вас что-то заработает, вы сможете приспособиться к своим потребностям. - person AMissico; 12.03.2010
comment
Почему бы просто не переопределить HitTest и не увеличить область? - person AMissico; 12.03.2010