Adorners для C# Windows Forms

У меня есть холст (панель управления) в моем приложении WinForms, где пользователи могут перетаскивать такие вещи, как текстовые поля, метки и т. Д. Но я хочу, чтобы им было проще более точно выравнивать объекты. Я читал об этом, и Adorners, кажется, путь? Но, видимо, это только для WPF. К сожалению, WPF для меня не вариант.

Я пытаюсь добиться того, чтобы линии появлялись каждый раз, когда пользователь перетаскивает объект на холсте... Как они работают в представлении конструктора Windows Forms.

Я был бы признателен за любую помощь.

Спасибо.


person Community    schedule 11.02.2010    source источник


Ответы (4)


Спасибо всем за ваши ответы.


Мне удалось придумать собственное решение. Код внизу. "Очередей" пока нет, но когда-нибудь я этим займусь...

Label l = (Label)sender;
foreach (Control control in Canvas.Controls)
{
    if (l.Location.X > control.Location.X + control.Size.Width && l.Location.X < control.Location.X + control.Size.Width + 5)
        l.Location = new Point(control.Location.X + control.Size.Width + 5, l.Location.Y);
    else if (l.Location.X < control.Location.X - l.Size.Width && l.Location.X > control.Location.X - l.Size.Width - 5)
        l.Location = new Point(control.Location.X - l.Size.Width - 5, l.Location.Y);
    else if (l.Location.Y > control.Location.Y + control.Size.Height && l.Location.Y < control.Location.Y + control.Size.Height + 5)
        l.Location = new Point(l.Location.X, control.Location.Y + control.Size.Height + 5);
    else if (l.Location.Y < control.Location.Y - control.Size.Height && l.Location.Y > control.Location.Y - control.Size.Height - 5)
        l.Location = new Point(l.Location.X, l.Location.Y - 5);

    this.Update();
}

Приведенный выше код должен быть помещен внутри события Control_MouseMove, и, конечно же, вам по-прежнему нужен собственный код, который фактически перемещает элементы управления.

Приведенный выше код привязывает элемент управления, который вы перетаскиваете, на 5 пикселей вправо, влево, вверх или вниз от ближайшего элемента управления.

person Community    schedule 12.02.2010

Здесь был похожий вопрос: строки Snap-To, когда выравнивание элементов управления во время выполнения

Где я предложил что-то вроде:

left = (left/10)*10;
top = (top/10)*10;

Для оснастки часть. Другой пользователь указал на конструктор форм, который может вам помочь.

person Cory Charlton    schedule 11.02.2010

Это вполне возможно сделать. Посмотрите на метод DrawReversibleLine в MSDN. А пока я попытаюсь найти какой-нибудь код, в котором я делал то же самое.

bool AllowResize;
bool DoTracking;  

private void MyControl_MouseDown(object sender, MouseEventArgs e)
{
    if (AllowResize)
    {
        DoTracking = true;
                ControlPaint.DrawReversibleFrame(new Rectangle(this.PointToScreen(new Point(1,1)),
        this.Size), Color.DarkGray, FrameStyle.Thick);
    }
}

Я знаю, что это очень общее и в основном грубое начало, но, как уже упоминалось, это может быть утомительной задачей. Особенно когда речь идет об отслеживании движения и т.д. Помните, что в событии MyControl_MouseUp нужно вызвать ControlPaint.DrawReversibleFrame(...) для стирания кадра. Также во время контрольного движения. Все, что вам нужно сделать, это снова вызвать функцию с теми же параметрами. Надеюсь, это поможет.

Кроме того, чтобы уменьшить мерцание, как указывает Джош, добавьте следующее после InitializeComponents();

//  To reduce redraw flicker
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
person IAbstract    schedule 11.02.2010

Если я правильно понимаю, вы хотите настроить свой элемент управления так, чтобы он действовал как другие элементы управления контейнером (GroupBox, Panel и т. д.)?

Если это так, я думаю, что DisplayRectangle - это то, что вам нужно. Вы меняете его на прямоугольник, к которому хотите привязать другие элементы управления. Например, у меня есть элемент управления в стиле GroupBox, и я устанавливаю DisplayRectangle следующим образом:

public override Rectangle DisplayRectangle
{
    get
    {
        return Rectangle.FromLTRB(base.DisplayRectangle.Left,
            base.DisplayRectangle.Top + Font.Height + 4,
            base.DisplayRectangle.Right,
            base.DisplayRectangle.Bottom);
    }
}

Теперь любой элемент управления, который я размещаю в качестве дочернего элемента, будет привязан к этому прямоугольнику, когда я перетащу его к краям.

ХТХ!

person Community    schedule 28.06.2010