禁止在System.Windows.Forms.RichTextBox的VScrollbar的绘画Windows、System、Forms、VScrollbar

2023-09-04 00:51:20 作者:醉意流年

我有一个从RichTextBox中继承了一个自定义的控制。 这种控制却以禁用富文本编辑的能力。 我achive这仅通过设置TextChanged事件中的RTF属性text属性。

I have a custom control inherited from RichTextBox. This control has the ability to "disable" rich text editing. I achive this by just setting the Rtf property to the text property during the TextChanged event.

这是我的code是这样的:

this is how my code looks like:

        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行的控制抖动(您看到文字的眼色第一行)。

That worked well. However in a large text with like 200 lines the controls jitters (you see the first lines of text for the wink).

要prevent这种情况发生我筛选SuspendLayout()和ResumeLayout()之间的WM_PAINT

To prevent that from happening I filter the WM_PAINT between SuspendLayout() and ResumeLayout()

    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不会引起的颤动anymoe。 这就是我想要的只是一件事才达到,: 滚动条依然引起的颤动每次我键入文本到我的控制。

that did the trick, the RichTextBox isn't jittering anymoe. That's what I wanted to achive, except one thing: The scrollbar is still jittering everytime I type text to my control.

现在我的问题: 有没有人有一个线索,我怎么prevent滚动条的过程中重新绘制暂停/继续布局?

Now my question: Does anyone have a clue for me how to prevent the scrollbar from redrawing during Suspend/Resume Layout?

推荐答案

SuspendLayout()是不会产生效果,也有内部的RTB需要安排无子控件。 RTB缺少开始/ EndUpdate()方法,大多数控件都有,虽然它支持它。它暂停画画,虽然我不太确定它暂停更新滚动条。加入他们如下:

SuspendLayout() isn't going to have an effect, there are no child controls inside an RTB that need to be arranged. RTB is missing the Begin/EndUpdate() methods that most controls have, although it supports it. It suspends painting, although I'm not so sure it suspends updates to the scrollbar. Add them as follows:

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); 

更好的方法,以prevent从编辑短信用户设置只读属性为True。卸下滚动条完全是可能太受覆盖的CreateParams。

The better way to prevent the user from editing text is to set the ReadOnly property to True. Removing the scrollbar entirely is possible too by overriding CreateParams.