Invalidate и DrawRectangle не работают вместе

Представьте себе простую Windows-форму .Net 2.0 с многострочным текстовым полем, которое заполняет всю форму. Я хочу (повторно) рисовать прямоугольник каждый раз, когда нажимается клавиша. В реальном приложении гораздо больше логики в отношении положения и прочего прямоугольника, но не усложняйте его.

Я подумал: «Давайте сначала аннулируем TextBox, а затем нарисуем прямоугольник». Но это не работает. Кратковременно мерцает экран - вот и все. Если я удалю строку «invaliate», будет нарисован прямоугольник, но старые сохранят свою позицию.

Что случилось? И как перекрасить с нуля?

Заранее спасибо за ваши ответы!

private void OnKeyDown(object sender, KeyEventArgs e)
{
        textBox1.Invalidate();

        using (Graphics g = this.textBox1.CreateGraphics())
        {
            int startX = 100;
            int startY = 300;
            int height = 200;

            Brush brush = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

            Pen myPen = new Pen(Color.Black, 2);
            myPen.DashStyle = DashStyle.Dash;

            g.DrawRectangle(myPen, startX, startY, this.textBox1.Width, height);

            g.FillRectangle(brush, startX, startY, this.textBox1.Width, height);
        }
}

person user799821    schedule 08.08.2013    source источник


Ответы (3)


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

Коротким (но неправильным) решением будет замена Invalidate() на Update(), но не делайте этого.

Вам придется переместить логику рисования в событие textBox1.Paint. И ваша форма нуждается в (логическом) свойстве, чтобы решить, рисовать ли прямоугольник или нет.

Ваш KeyDown должен выглядеть так:

private void OnKeyDown(object sender, KeyEventArgs e)
{
    this.DrawRect = true;
    textBox1.Invalidate();
}
person Henk Holterman    schedule 08.08.2013
comment
Мне нравится короткое (неправильное) исправление, потому что оно работает — что в нем не так? - person user799821; 08.08.2013
comment
Очень неэффективно, и вы потеряете Rect, когда что-то еще сделает форму недействительной. - person Henk Holterman; 08.08.2013
comment
Если я нажимаю клавишу, ничего не происходит. Если я нажимаю клавишу и перемещаю мышь по области или вне области - рисуется прямоугольник - странно ... - person user799821; 08.08.2013

Вызовите this.Invalidate(); при нажатии клавиши и переместите свой код рисования в событие OnPaint, куда он должен идти. Если вы хотите полностью избежать мерцания, вам нужно рисовать в соответствии со следующим руководством: C#, двойной буфер в WinForms?.

Вы также должны хранить List<> всех ваших прямоугольников и рисовать каждый OnPaint, так как нажатие клавиши — не единственное, что может сделать форму недействительной и вызвать перерисовку.

person bizzehdee    schedule 08.08.2013
comment
И как это должно помочь? Я этого не вижу. - person Henk Holterman; 08.08.2013

Мне сказали использовать "textBox1.Refresh()" вместо "textBox1.Invalidate();" и это работает!

private void OnKeyDown(object sender, KeyEventArgs e)
{
    //textBox1.Invalidate(); - Dont do that
    textBox1.Refresh(); //Dominik Schelenz, my internet Hero for today!

    using (Graphics g = this.textBox1.CreateGraphics())
    {
        int startX = 100;
        int startY = 300;
        int height = 200;

        Brush brush = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

        Pen myPen = new Pen(Color.Black, 2);
        myPen.DashStyle = DashStyle.Dash;

        g.DrawRectangle(myPen, startX, startY, this.textBox1.Width, height);

        g.FillRectangle(brush, startX, startY, this.textBox1.Width, height);
    }
}
person user799821    schedule 12.08.2013
comment
Обновить() — это то же самое, что и Обновить(). Это означает, что это не эффективный способ сделать это. - person Henk Holterman; 12.08.2013
comment
Да, я знаю - blogs.msdn.com/b/ subhagpo/archive/2005/02/22/378098.aspx — но Refresh Works и другие решения не помогли — поэтому я придерживаюсь этого. - person user799821; 12.08.2013
comment
Вы тестировали его с Invalidate, вызванным другими событиями? - person Henk Holterman; 12.08.2013