0

我有一个从 RichTextBox 继承的自定义控件。此控件具有“禁用”富文本编辑的能力。我通过在 TextChanged 事件期间将 Rtf 属性设置为 text 属性来实现这一点。

这就是我的代码的样子:

        private bool lockTextChanged;
        void RichTextBox_TextChanged(object sender, EventArgs e)
        {
            // prevent StackOverflowException
            if (lockTextChanged) return;

            // remember current position
            int rtbstart = rtb.SelectionStart;
            int len = rtb.SelectionLength;


            // prevent painting                
            rtb.SuspendLayout();

            // set the text property to remove the entire formatting.
            lockTextChanged = true;
            rtb.Text = rtb.Text;
            rtb.Select(rtbstart, len);
            lockTextChanged = false;

            rtb.ResumeLayout(true);
      }

效果很好。然而,在大约 200 行的大文本中,控件会抖动(您会看到第一行文本的眨眼)。

为了防止这种情况发生,我在 SuspendLayout() 和 ResumeLayout() 之间过滤了 WM_PAINT

    private bool layoutSuspended;
    public new void SuspendLayout()
    {
        layoutSuspended = true;
        base.SuspendLayout();
    }

    public new void ResumeLayout()
    {
        layoutSuspended = false;
        base.ResumeLayout();
    }

    public new void ResumeLayout(bool performLayout)
    {
        layoutSuspended = false;
        base.ResumeLayout(performLayout);
    }

    private const int WM_PAINT = 0x000F;
    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        if (!(m.Msg == WM_PAINT && layoutSuspended))
            base.WndProc(ref m);

    }

成功了,RichTextBox 不再抖动。
这就是我想要实现的目标,除了一件事:
每次我向控件输入文本时,滚动条仍然抖动。

现在我的问题:有没有人知道如何防止滚动条在暂停/恢复布局期间重绘?

4

1 回答 1

3

SuspendLayout() 不会产生影响,RTB 内没有需要排列的子控件。RTB 缺少大多数控件具有的 Begin/EndUpdate() 方法,尽管它支持它。它暂停绘画,虽然我不太确定它会暂停滚动条的更新。按如下方式添加它们:

public void BeginUpdate() {
  SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
}
public void EndUpdate() {
  SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); 
}

// P/invoke declarations
private const int WM_SETREDRAW = 0xb;
[System.Runtime.InteropServices.DllImport("user32.dll")]
private extern static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); 

防止用户编辑文本的更好方法是将 ReadOnly 属性设置为 True。通过覆盖 CreateParams 也可以完全删除滚动条。

于 2010-04-21T12:07:35.913 回答