Подтвердить что ты не робот

Как предотвратить изменение текстового поля Windows Forms TextBox при изменении размера?

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

Кроме того, из ответа Bob также говорит:

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

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

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

[Обновить]

Некоторые другие ответы говорят, что это проблема с 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);
    }
}

Ответ 3

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

Ответ 4

ФУНКЦИЯ LockWindow AS LONG CONTROL SEND ghDlg,% TEXT_UPPER,% WM_SETREDRAW, 0,0 CLEARBuffers END FUNCTION

ФУНКЦИЯ UnlockWindow AS LONG ClearBuffers CONTROL SEND ghDlg,% TEXT_UPPER,% WM_SETREDRAW, 1,0 END FUNCTION