我有一个继承自 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);
}
这样就成功了,富文本框不再抖动了。
这就是我想要实现的目标,除了一件事:
每次我在控件中输入文本时,滚动条仍然会卡顿。
现在我的问题是:
有谁知道如何防止滚动条在挂起/恢复布局期间重绘?
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 也可以完全删除滚动条。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)