禁用System.Windows.Forms.RichTextBox中VScrollbar的绘制

时间:2010-04-21 10:22:56

标签: c# .net windows paint

我有一个从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不会抖动任何东西 这就是我想要实现的目标,除了一件事: 每当我向控件输入文本时滚动条仍然抖动。

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

1 个答案:

答案 0 :(得分: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也可以完全删除滚动条。