Как предотвратить мигание текстового поля Windows Forms при изменении размера? - PullRequest
18 голосов
/ 26 августа 2009

В Windows Forms есть множество статей, посвященных мерцанию. Большинство рекомендует установить DoubleBuffered = true или установить набор ControlStyle флагов. Однако ни один из них не помогает уменьшить мерцание TextBox.

Вот несколько связанных вопросов:

Чтобы воспроизвести проблему, создайте новый проект WinForms, добавьте TextBox, включите несколько строк, отключите перенос слов, добавьте кучу текста, установите Anchor влево + вправо + сверху + снизу. Теперь запустите и измените размер. Текст мерцает. Для текстовых полей внутри пары вложенных TableLayoutPanel с мерцание при изменении размера еще хуже.

Применение решений, предложенных в вышеупомянутых вопросах, в лучшем случае не устраняет мерцание; если я проведу эксперимент и установлю защищенное значение ControlStyle на TextBox, я смогу полностью его отключить (включив UserPaint), но не устраню мерцание.

Так, есть ли способ исправить мерцание текста в TextBox?

Ответы [ 4 ]

15 голосов
/ 15 апреля 2011

Я обычно использую RichTextBox вместо многострочного TextBox. Установив свойства DetectUrls- и ShortcutsEnabled в false, RTB ведет себя очень похоже на TextBox и ... он не мерцает .

4 голосов
/ 26 августа 2009

В Windows Forms свойство DoubleBuffered не влияет на дочерние элементы управления, такие как текстовые поля. Вместо этого он влияет только на форму или панель, для которой он установлен.

Если вы хотите двойную буферизацию для дочерних элементов в форме, вам нужно будет реализовать двойную буферизацию вручную.

Боб Пауэлл написал хорошую статью (и другие) о том, как это сделать.

Кроме того, из ответа на форуме Боб также говорит:

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

Единственный способ сделать это правильно - создать единый элемент управления, который делает весь рисунок с использованием формы графическая система с сохранением режима.

Поэтому, чтобы изменить размер текстового поля без мерцания, используя двойную буферизацию вручную, вам необходимо каким-то образом визуализировать текстовое поле в задний буфер, а затем отобразить его как часть буферизованного обновления. Если возможно, я не ожидаю, что это будет легко.

[Обновить]

В некоторых других ответах говорилось, что это проблема именно с Windows Forms. Это не правильно, это на самом деле глубже, чем это и вызвано Windows GDI. Например, откройте Блокнот / Wordpad и т. Д., Вставьте большой кусок текста, измените размер окна и обратите внимание на ту же проблему мерцания.

Вот базовое решение, которое я использовал несколько лет назад, чтобы сделать нечто подобное. Это простая форма, содержащая многострочное текстовое поле и пользовательский класс, наследуемый от Panel. Оба элемента управления имеют одинаковое расположение и размер. Он использует формы ResizeBegin и ResizeEnd для отображения панели при изменении размера, а текстовое поле - в противном случае. Это не идеально, но оно устраняет мерцание.

   public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Bitmap bm = null;

        private void textBox1_Resize(object sender, EventArgs e)
        {

            Graphics g = textBox1.CreateGraphics();

            if (g.VisibleClipBounds.IsEmpty == false)
            {
                bm = new Bitmap((int)g.VisibleClipBounds.Width, (int)g.VisibleClipBounds.Height);

                textBox1.DrawToBitmap(bm, new Rectangle(0, 0, (int)g.VisibleClipBounds.Width, (int)g.VisibleClipBounds.Height));

            }

            g.Dispose();


        }

        private void panelDB1_Paint(object sender, PaintEventArgs e)
        {
            if (bm != null)
            {
                e.Graphics.DrawImageUnscaled(bm, 0, 0,bm.Width,bm.Height );
            }
        }

        private void Form1_ResizeBegin(object sender, EventArgs e)
        {
            panelDB1.BringToFront();  
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            panelDB1.SendToBack();   
        }
}

class PanelDB : Panel
{
    public PanelDB()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer,true);       
        //this.DoubleBuffered = true; 

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
    }
}
0 голосов
/ 01 декабря 2015

ФУНКЦИЯ LockWindow КАК ДОЛГО КОНТРОЛЬ ОТПРАВИТЬ ghDlg,% TEXT_UPPER,% WM_SETREDRAW, 0,0 CLEARBuffers КОНЕЧНАЯ ФУНКЦИЯ

ФУНКЦИЯ UnlockWindow AS LONG ClearBuffers КОНТРОЛЬ ОТПРАВИТЬ ghDlg,% TEXT_UPPER,% WM_SETREDRAW, 1,0 КОНЕЦ ФУНКЦИИ

0 голосов
/ 26 августа 2009

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

...