Вопрос по winforms, c#, mouseevent, drawing – Как нарисовать прямоугольник в зависимости от движения мыши?

0

Я нашел пример кода здесь для рисования на форме:

http://msdn.microsoft.com/en-us/library/aa287522(v=vs.71).aspx

В качестве продолжения этого требования (выяснение того, какие элементы управления находятся ниже прямоугольника, описанного пользователь перетаскивает мышь):

Кажется, существует несоответствие между расположением моих элементов управления и местоположением событий MouseDown и -Up.

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

Я думаю, что событие MouseMove в сочетании с кодом из двух ссылок выше может помочь, но происходит ли оно слишком часто / будет ли это плохо влиять на производительность? Если это так, что было бы предпочтительным событием, чтобы перехватить, или таймер будет путь сюда?

UPDATE

Этот код, адаптированный из приведенного ниже примера Джона (единственное отличие состоит в том, что вызываемые StackOverflow вызовы base. * Закомментированы, и я изменил цвет с красного на черный (ссылки на Стендала не предназначены)), работаетexcept что ранее нарисованные прямоугольники отображаются снова после отпускания мыши. IOW, первый прямоугольник отлично рисует - он исчезает при щелчке мыши вверх (как и предполагалось). Однако, когда я опишу второй прямоугольник, нажав левую клавишу мыши и потянув вниз и вправо,first прямоугольник отображается снова! И это продолжает происходить -every ранее нарисованный прямоугольник запоминается и возвращается на передний план при рисовании нового прямоугольника.

public partial class Form1 : Form { private Point? _start; private Rectangle _previousBounds;

<code>public Form1()
{
    InitializeComponent();
}

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    _start = e.Location;
    //base.OnMouseDown(e); 

}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (_start.HasValue)
        DrawFrame(e.Location);

    //base.OnMouseMove(e); 

}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    ReverseFrame();
    _start = null;
    //base.OnMouseUp(e); 
}

private void ReverseFrame() 
{ 
    ControlPaint.DrawReversibleFrame(_previousBounds, Color.Black, FrameStyle.Dashed); 
} 

private void DrawFrame(Point end) 
{ 
    ReverseFrame(); 

    var size = new Size(end.X - _start.Value.X, end.Y - _start.Value.Y); 
    _previousBounds = new Rectangle(_start.Value, size); 
    _previousBounds = this.RectangleToScreen(_previousBounds); 
    ControlPaint.DrawReversibleFrame(_previousBounds, Color.Black, FrameStyle.Dashed); 
} 
</code>

}

Ваш Ответ

1   ответ
1

ControlPaint.DrawReversibleFrame() будет делать то, что вы хотите. Производительность, как правило, не проблема - просто держите ее маленькой и чистой.

-- EDIT: Added a code sample. StackOverflowException indicates something is wrong - but without seeing yours, can't answer directly.

private Point? _start;
private Rectangle _previousBounds;

protected override void OnMouseDown(MouseEventArgs e)
{
    _start = e.Location;
    base.OnMouseDown(e);
}

protected override void OnMouseMove(MouseEventArgs e)
{
    if( _start.HasValue ) {
        ReverseFrame();
        DrawFrame(e.Location);
    }

    base.OnMouseMove(e);
}

protected override void OnMouseUp(MouseEventArgs e)
{
    ReverseFrame();
    _start = null;
    base.OnMouseUp(e);
}

private void ReverseFrame()
{
    ControlPaint.DrawReversibleFrame(_previousBounds, Color.Red, FrameStyle.Dashed);

}
private void DrawFrame(Point end)
{
    ReverseFrame();

    var size = new Size(end.X - _start.Value.X, end.Y - _start.Value.Y);
    _previousBounds = new Rectangle(_start.Value, size);
    _previousBounds = this.RectangleToScreen(_previousBounds);
    ControlPaint.DrawReversibleFrame(_previousBounds, Color.Red, FrameStyle.Dashed);
}
Обратите внимание на мое обновление к моему оригинальному сообщению: с звонками на базу. * Закомментирован, ваш кодalmost работает (если только он "забудет" предыдущие нарисованные прямоугольники). B. Clay Shannon
Спасибо, однако, я получаю переполнение стека и с вашим образцом - при этом ничего больше не добавляется и ничего в форме - настолько, насколько это возможно (без вашего кода): исключение System.StackOverflowException не обрабатывается B. Clay Shannon
Попробуйте пример здесь:switchonthecode.com/tutorials/…  ... Я получаю & quot; исключение System.StackOverflowException не обработано в событии MouseMove (). & Quot; Когда я закомментирую все «базы», он больше не выдает сообщение об ошибке, НО он также не работает (левая кнопка мыши, перетаскивание, mouseup не отображает прямоугольник) B. Clay Shannon
@Clay Shannon: вы используете события (form.MouseMove + = ...). В этом случае базовые вызовы вызовут переполнение и не нужны. Но там, где это возможно, лучше использовать переопределения методов базового класса.
DrawReversibleFrame требует второго вызова с точно такими же границами - чтобы отрисовать себя. Два вызова подряд приводят к тому, что ничего не отображается (без прямоугольника)

Похожие вопросы