C#删除行后在RichTextBox中丢失字体样式
我有一个C#删除行后在RichTextBox中丢失字体样式,c#,winforms,visual-studio,C#,Winforms,Visual Studio,我有一个RichTextBox用于简单的聊天,通过编程方式添加行。 我将用户名设置为粗体,并将消息设置为常规样式。 在几行之后,我想删除第一行,以使聊天保持在可接受的长度。但当我这样做时,我会丢失文本格式,所有内容都显示为粗体。我做错了什么?我怎样才能解决这个问题 编辑 我可以解决无法删除第一行的问题。 我必须将只读属性设置为false。即使我能够添加新行,它也阻止删除行。因此,下面的代码用于删除行。感谢@TaW if (ChatText.Lines.Length >= 10) {
RichTextBox
用于简单的聊天,通过编程方式添加行。
我将用户名设置为粗体,并将消息设置为常规样式。
在几行之后,我想删除第一行,以使聊天保持在可接受的长度。但当我这样做时,我会丢失文本格式,所有内容都显示为粗体。我做错了什么?我怎样才能解决这个问题
编辑
我可以解决无法删除第一行的问题。
我必须将只读属性设置为false。即使我能够添加新行,它也阻止删除行。因此,下面的代码用于删除行。感谢@TaW
if (ChatText.Lines.Length >= 10)
{
int p = 0; int count = 0;
do
{
p = ChatText.Text.IndexOf("\n\r");
if (p >= 0)
{
ChatText.SelectionStart = p;
ChatText.SelectionLength = 2; // length of "\n\r"
ChatText.SelectedText = "\n";
count++;
}
}
while(p >= 0);
int nll = 1; // <<=== pick the length of your new line character(s)!!
int pS = ChatText.Lines.Take(0).Select(x => x.Length + nll).Sum() - nll;
int pL = ChatText.Lines.Take(1).Select(x => x.Length + nll).Sum() - nll;
if (pS < 0) { pS = 0; pL++; }
ChatText.SelectionStart = pS;
ChatText.SelectionLength = pL - pS;
ChatText.Cut();
}
//////////////////////////////////
// now add new lines
//////////////////////////////////
string[] chatstr;
// string text is given as method parameter
chatstr = text.Split(new string[] { ": " }, 2, StringSplitOptions.None);
// go to the end of the text
ChatText.SelectionStart = ChatText.Text.Length;
ChatText.SelectionLength = 0;
// make text bold
ChatText.SelectionFont = new Font(ChatText.Font, FontStyle.Bold);
// add username (chatstr[0]) and colon
ChatText.AppendText(chatstr[0] + ": ");
// make text regular
ChatText.SelectionFont = new Font(ChatText.Font, FontStyle.Regular);
// add message (chatstr[1])
ChatText.AppendText(chatstr[1] + "\n");
// and finaly scroll down
ChatText.ScrollToCaret();
if(ChatText.Lines.Length>=10)
{
int p=0;int count=0;
做
{
p=ChatText.Text.IndexOf(“\n\r”);
如果(p>=0)
{
chatterxt.SelectionStart=p;
ChatterText.SelectionLength=2;//长度为“\n\r”
ChatterText.SelectedText=“\n”;
计数++;
}
}
而(p>=0);
int nll=1;//x.Length+nll).Sum()-nll;
如果(pS<0){pS=0;pL++;}
chatterxt.SelectionStart=pS;
chatterxt.SelectionLength=pL-pS;
ChatText.Cut();
}
//////////////////////////////////
//现在添加新行
//////////////////////////////////
字符串[]chatstr;
//字符串文本作为方法参数提供
chatstr=text.Split(新字符串[]{“},2,StringSplitOptions.None);
//转到课文末尾
ChatText.SelectionStart=ChatText.Text.Length;
ChatText.SelectionLength=0;
//使文本加粗
ChatText.SelectionFont=新字体(ChatText.Font,FontStyle.Bold);
//添加用户名(chatstr[0])和冒号
AppendText(chatstr[0]+“:”);
//使文本规则化
ChatText.SelectionFont=新字体(ChatText.Font、FontStyle.Regular);
//添加消息(chatstr[1])
ChatText.AppendText(chatstr[1]+“\n”);
//最后向下滚动
ChatText.ScrollToCaret();
因此,删除行将起作用,并按预期添加新行。终于
已解决:)如果RichtTextBox
包含任何格式,则从不更改其文本
更改行
属性(通过跳过
)只是更改文本
的另一种方法
相反,只使用RTB提供的功能:始终从选择要格式化的部分开始,然后应用一个或多个功能和/或设置一个或多个属性
要删除部分,请使用剪切
下面是一个函数,它将删除许多整行:
void DeleteLines(RichTextBox rtb, int fromLine, int count)
{
int p1 = rtb.GetFirstCharIndexFromLine(fromLine);
int p2 = rtb.GetFirstCharIndexFromLine(fromLine + count);
rtb.SelectionStart = p1;
rtb.SelectionLength = p2 - p1;
bool readOnly = rtb.ReadOnly; // allow change even when the RTB is readonly
rtb.ReadOnly = false; ;
rtb.Cut();
rtb.ReadOnly = readOnly;
}
试图自己保持格式化是一种乏味且容易出错的浪费时间的行为
除了字体属性外,您还必须重新设置所有其他可以使用SelectedXXX
属性设置的内容,如颜色、对齐方式、间距等
要删除前3行,请使用:
DeleteLines(yourRTB, 0, 3);
DeleteLines(yourRTB, 0, yourRTB.Lines.Length - 10);
要将文本限制为10行,请使用:
DeleteLines(yourRTB, 0, 3);
DeleteLines(yourRTB, 0, yourRTB.Lines.Length - 10);
注意,上面的函数应该有一些有效输入的检查;我忽略了它们,因为检查不知何故需要决定怎么做,如果count
或fromLine
大于行。Length
或fromLine
为负数
当我们进行此操作时,下面是如何添加粗体行:
yourRTB.SelectionStart = yourRTB.Text.Length;
yourRTB.SelectionLength = 0;
using (Font font = new Font(yourRTB.SelectionFont, FontStyle.Bold))
yourRTB.SelectionFont = font;
yourRTB.AppendText(yourNewLine + textOfNewLine);
当然,它真的应该进入一个可重用的函数,将粗体作为一个参数
更新:
由于您使用的是WordWrap
,因此您可能更喜欢此功能。它将删除实际行,而不是可见行:
void DeleteLinesWW(RichTextBox rtb, int fromLine, int count)
{
int nll = 1; // <<=== pick the length of your new line character(s)!!
int pS = rtb.Lines.Take(fromLine).Select(x => x.Length + nll).Sum() - nll;
int pL = rtb.Lines.Take(fromLine + count).Select(x => x.Length + nll).Sum() - nll;
if (pS < 0) { pS = 0; pL++; }
rtb.SelectionStart = pS;
rtb.SelectionLength = pL - pS ;
bool readOnly = rtb.ReadOnly;
rtb.ReadOnly = false; // allow change even when the RTB is readonly
rtb.Cut();
rtb.ReadOnly = readOnly;
}
这样称呼:
RTBReplace(yourrichTextBox, "\r\n", "\n");
更新2:
下面是一个如何添加聊天线路的示例:
private void button1_Click(object sender, EventArgs e)
{
string cLine = "Taw: Hello World"; // use your own lines!
var chatstr = cLine.Split(new string[] { ": " }, 2, StringSplitOptions.None);
AppendLineBold(yourrichTextBox, "\n" + chatstr[0], true);
AppendLineBold(yourrichTextBox, chatstr[1], false);
yourrichTextBox.ScrollToCaret();
}
void AppendLineBold(RichTextBox rtb, string text, bool bold)
{
rtb.SelectionStart = richTextBox1.Text.Length;
rtb.SelectionLength = 0;
using (Font font = new Font(rtb.SelectionFont,
bold ? FontStyle.Bold : FontStyle.Regular))
rtb.SelectionFont = font;
rtb.AppendText(text);
}
更新3:
看起来ReadOnly
属性不允许使用Cut
。因此,我们需要暂时允许改变
有趣的是:SelectedText
也不能设置,但是AppendText
可以很好地工作。要保持文本格式,您还可以尝试以下操作(它稍微短一点,也应该可以做到这一点)
正确的方法不是跳过
行或重新格式化周围的行,而是首先选择要删除的行,然后使用剪切
删除它们。对不起,我不明白。我该怎么做?我找不到string[]
的Cut
方法。请参阅我的答案。剪切是RichTextBox操作其内容和格式所需的多种方法之一。索引自动文本异常是因为之后没有文本:“
。我在新答案中插入了一个复选框。在“:”之后不应出现文本,因为不可能发送空消息。我想我是在摆弄WordWrap属性。谢谢你,但不知怎么的,它还是不起作用。现在第一行(应该删除的那一行)变为粗体(用户名和消息),直到WordWrap插入换行符。新的生产线是完全正常的。此外,第一行不会被删除:(@St.Helen——确保正确调用该方法。然后新行必须像通常那样格式化。我只是在if
部分中使用它,而不是调用函数。我使用0表示fromLine
,1表示fromLine+count
。应该也能工作吗?我没有更改if
下面的任何内容,所以我不会更改为什么新行是完全规则的。现在有点难说你的代码是什么样子。我在你的文章中没有看到任何代码进行任何选择。这可能是问题所在!-没有它,你就不能正确格式化RTB!!附加文本将在它前面得到文本的格式,如果并且只有当文本格式正确!我如果格式化在换行符之前停止,它将不会继续。。也可以通过几个示例查看我的更新。@TaW我只想在每次执行lin时删除第一行