Предотвратите мигание, печатая / копируя в расширенное текстовое поле - PullRequest
0 голосов
/ 04 июня 2011

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

RTB, похоже, не поддерживает двойную буферизацию, но я не уверен, поможет ли это в любом случае. Преодоление события на краске также кажется неэффективным. После исследования Интернета лучшее «решение», которое я нашел до сих пор, - это использование встроенного взаимодействия Windows (LockWindowUpdate и т. Д.). Это вылечило ситуацию, когда печатание за пределами прокрутки было абсолютно ужасным. К сожалению, сейчас все еще наблюдается (меньшее) мерцание.

Приведенный ниже код можно сразу скомпилировать (просто создайте консольный проект и создайте ссылку на System.Windows.Forms и System.Drawing). Если вы это сделаете, нажмите клавишу и удерживайте ее, скажем, на 10 строк. Если вы это сделаете, вы заметите все больше и больше мерцания. Чем больше вы печатаете, тем хуже становится мерцание.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace FlickerTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        [DllImport("user32.dll")]
        public static extern bool LockWindowUpdate(IntPtr hWndLock);
        private void rtb_TextChanged(object sender, EventArgs e)
        {
            String s = rtb.Text;
            LockWindowUpdate(rtb.Handle);
            rtb.Text = s;
            rtb.Refresh(); ////Forces a synchronous redraw of all controls
            LockWindowUpdate(IntPtr.Zero);
        }
    }

    //////////////////////////////////////////////////
    // Ignore below:
    static class Program    {
        [STAThread]
        static void Main()      {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null)) components.Dispose();
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            this.rtb = new System.Windows.Forms.RichTextBox();
            this.SuspendLayout();
            // rtb
            this.rtb.BackColor = System.Drawing.Color.Black;
            this.rtb.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.rtb.ForeColor = System.Drawing.SystemColors.Window;
            this.rtb.Location = new System.Drawing.Point(24, 20);
            this.rtb.Name = "rtb";
            this.rtb.Size = new System.Drawing.Size(609, 367);
            this.rtb.TabIndex = 0;
            this.rtb.Text = "";
            this.rtb.TextChanged += new System.EventHandler(this.rtb_TextChanged);
            // Form1
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1088, 681);
            this.Controls.Add(this.rtb);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
        }
        #endregion
        private System.Windows.Forms.RichTextBox rtb;
    }
}

Ответы [ 2 ]

1 голос
/ 26 марта 2014

Недавно я столкнулся с подобной проблемой.Метод, который я выбрал, заключался в добавлении методов расширения в richtextbox.Мне нравится этот подход, потому что он чистый, автономный и легко используется повторно.

Это делает паузу перерисовки таким же простым, как

richtextbox.SuspendDrawing();

и возобновляет

richtextbox.ResumeDrawing()

public static class RichTextBoxExtensions
{
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    private const int WM_SETREDRAW = 0x0b;

    public static void SuspendDrawing(this System.Windows.Forms.RichTextBox richTextBox)
    {
        SendMessage(richTextBox.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
    }

    public static void ResumeDrawing(this System.Windows.Forms.RichTextBox richTextBox)
    {
        SendMessage(richTextBox.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
        richTextBox.Invalidate();
    }
}
1 голос
/ 07 июня 2011

Вам не нужно обновлять RTB для каждого нажатия клавиши, что происходит, когда вы обрабатываете TextChanged без какого-либо вызова Application.DoEvents ().

Я обнаружил, что лучший способ получить приемлемую производительность - это обработать событие KeyDown. Если код клавиши (с модификатором) является печатным символом, я запускаю таймер, чей обработчик события Tick проверяет текст richtextbox после, скажем, 100 мс.

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

Наконец, изменение поведения RichTextBox - это сприал, как только вы отклонитесь от нормы, вы начнете использовать собственный код для всех видов задач (таких как копирование / вставка, отмена / повтор и прокрутка), которые обычно выполняются с использованием контролирует собственные функции. После этого вы решаете, продолжать ли вам самим или выбрать стороннего редактора. Также обратите внимание, что, хотя вы уже начали использовать Windows API, этого будет гораздо больше, в частности для прокрутки, печати и рисования событий, хотя есть хорошие онлайн-ресурсы, документирующие их.

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

...