You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RichTextBox切换Resize模式后仅首次生效,ContentsResized事件不再触发

问题:RichTextBox切换适配模式后ContentsResized事件失效

在Windows Forms应用中使用名为rtbEditor的RichTextBox,勾选复选框ckbResize时希望通过监听ContentsResized事件让控件根据内容自动调整大小,预期行为:

  • 勾选ckbResize时,RichTextBox适配内容尺寸;
  • 取消勾选时,RichTextBox占满窗体大小;
  • 再次勾选ckbResize后,仍能随内容变化自动调整。

但实际仅首次勾选有效,取消后再勾选,自动调整失效,ContentsResized事件不再触发。现有代码如下:

private void rtbEditor_ContentsResized(object sender, ContentsResizedEventArgs e)
{
    if (ckbResize.Checked)
    {
        rtbEditor.Height = e.NewRectangle.Height;
        rtbEditor.Width = e.NewRectangle.Width + 1;
        rtbEditor.Left = this.ClientSize.Width - rtbEditor.Width;
    }
    else
    {
        rtbEditor.Width = this.ClientSize.Width;
        rtbEditor.Height = this.ClientSize.Height;
        rtbEditor.Left = 0;
    }
}

private void ckbResize_CheckedChanged(object sender, EventArgs e)
{
    if (ckbResize.Checked)
    {
        // Force initial resize
        rtbEditor.Rtf = rtbEditor.Rtf;
    }
    else
    {
        rtbEditor.Width = this.ClientSize.Width;
        rtbEditor.Height = this.ClientSize.Height;
        rtbEditor.Left = 0;
    }
}

即使重置RTF内容或调用Invalidate(),重新启用复选框后ContentsResized事件仍不触发。


解决方案

问题根源在于当RichTextBox被设置为占满窗体时,控件内部尺寸计算逻辑被干扰,导致后续内容变化无法触发ContentsResized事件。以下是两种简洁修复方案:

方案一:手动计算内容尺寸并强制刷新

修改ckbResize_CheckedChanged方法,主动计算内容所需尺寸并设置,同时强制控件刷新以恢复事件响应:

private void ckbResize_CheckedChanged(object sender, EventArgs e)
{
    if (ckbResize.Checked)
    {
        // 手动计算内容实际占用尺寸(包含边距)
        using (Graphics g = rtbEditor.CreateGraphics())
        {
            SizeF contentSize = g.MeasureString(rtbEditor.Text, rtbEditor.Font, 
                int.MaxValue, StringFormat.GenericTypographic);
            int targetWidth = (int)Math.Ceiling(contentSize.Width) + 20; // 预留控件边距
            int targetHeight = (int)Math.Ceiling(contentSize.Height) + 20;
            
            rtbEditor.Width = targetWidth;
            rtbEditor.Height = targetHeight;
            rtbEditor.Left = this.ClientSize.Width - rtbEditor.Width;
        }
        // 强制控件重新布局,确保后续内容变化能触发ContentsResized
        rtbEditor.PerformLayout();
    }
    else
    {
        rtbEditor.Width = this.ClientSize.Width;
        rtbEditor.Height = this.ClientSize.Height;
        rtbEditor.Left = 0;
    }
}

同时简化ContentsResized事件处理,避免不必要的逻辑:

private void rtbEditor_ContentsResized(object sender, ContentsResizedEventArgs e)
{
    if (!ckbResize.Checked) return;
    
    rtbEditor.Height = e.NewRectangle.Height;
    rtbEditor.Width = e.NewRectangle.Width + 1;
    rtbEditor.Left = this.ClientSize.Width - rtbEditor.Width;
}

方案二:利用AutoSize属性重置触发逻辑

通过切换AutoSize属性并临时修改内容,强制触发ContentsResized事件:

private void ckbResize_CheckedChanged(object sender, EventArgs e)
{
    if (ckbResize.Checked)
    {
        rtbEditor.AutoSize = true;
        // 临时修改内容再恢复,强制触发ContentsResized事件
        string originalText = rtbEditor.Text;
        rtbEditor.Text = " ";
        rtbEditor.Text = originalText;
    }
    else
    {
        rtbEditor.AutoSize = false;
        rtbEditor.Width = this.ClientSize.Width;
        rtbEditor.Height = this.ClientSize.Height;
        rtbEditor.Left = 0;
    }
}

该方案依赖控件自身的AutoSize特性,代码更简洁,适合内容格式相对简单的场景。


内容的提问来源于stack exchange,提问作者Food plus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:29:54