【问题标题】:Disable Painting of the VScrollbar in a System.Windows.Forms.RichTextBox在 System.Windows.Forms.RichTextBox 中禁用 VScrollbar 的绘制
【发布时间】:2010-04-25 05:23:38
【问题描述】:

我有一个继承自 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 不再抖动。
这就是我想要实现的目标,除了一件事:
每次我向控件输入文本时,滚动条仍然抖动。

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

【问题讨论】:

    标签: c# .net windows paint


    【解决方案1】:

    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 也可以完全移除滚动条。

    【讨论】:

    • 非常感谢这个提示。我会试一试(顺便说一句。用户应该能够编辑文本,但我会即时删除任何导致抖动的格式或 OLE 对象。消息是 0xb 是什么?
    • 这确实有效,非常感谢。而且我也可以放弃WndProc Method中对WM_PAINT方法的处理。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 2014-01-02
    • 1970-01-01
    相关资源
    最近更新 更多