[英]Suppress line break in a RichTextBox at certain positions
我需要在RichTextBox中抑制一些换行符。
例如,考虑d6+
。 6
和+
之间不能有换行符。 基本上我正在寻找HTML中的<nobr>
类的东西。
到目前为止,我已经搞乱了插入\\ u + FEFF等(在一些机器上工作,但有些显示垂直线,可能是字体问题,虽然windows标准字体)。 我也尝试直接操纵rtf,即box.rtf = ...
并在其中加入一些\\zwnbo
,但我似乎从来没有把它\\zwnbo
。
非常感谢。
是的,您可以将所有RichText API与RichTextBox控件一起使用。
您可能有兴趣看看以下网站:
http://www.pinvoke.net/default.aspx/user32.sendmessage - 如何使用p / invoke向Windows发送消息。
您可以使用RichTextBox
的Handle
属性来获取该控件的窗口句柄,然后向其发送消息 。
另请查看这些包含来自Microsoft的SDK的包含文件,它们不会直接在C#中使用,但这些文件会WB_ISDELIMITER
您可能必须使用的所有常量,例如WB_ISDELIMITER
, WB_CLASSIFY
等。
在以下示例中,我演示了如何使用提供的API。
编辑:
这个新样本的代码标记为不安全,但它更好,因为它没有单字符串的问题,因为我可以有一个char*
参数并操纵它。 旧样本遵循以下内容:
这是C#代码 ,而不是C ++ ...要编译它,你必须转到项目选项并标记复选框以允许运行不安全的代码 。
右键单击项目 - >属性(Alt + Enter) - >构建 - >常规 - >允许不安全代码(必须选中)
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace q6359774
{
class MyRichTextBox : RichTextBox
{
const int EM_SETWORDBREAKPROC = 0x00D0;
const int EM_GETWORDBREAKPROC = 0x00D1;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
this.Text = "abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz";
NewMethod();
}
unsafe private void NewMethod()
{
if (!this.DesignMode)
SendMessage(this.Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, Marshal.GetFunctionPointerForDelegate(new EditWordBreakProc(MyEditWordBreakProc)));
}
[DllImport("User32.DLL")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
unsafe delegate int EditWordBreakProc(char* lpch, int ichCurrent, int cch, int code);
unsafe int MyEditWordBreakProc(char* lpch, int ichCurrent, int cch, int code)
{
const int WB_ISDELIMITER = 2;
const int WB_CLASSIFY = 3;
if (code == WB_ISDELIMITER)
{
char ch = *lpch;
return ch == '-' ? 0 : 1;
}
else if (code == WB_CLASSIFY)
{
char ch = *lpch;
var vResult = Char.GetUnicodeCategory(ch);
return (int)vResult;
}
else
{
var lpch2 = lpch;
// in this case, we must find the begining of a word:
for (int it = ichCurrent; it < cch; it++)
{
char ch = *lpch2;
if (it + 1 < cch && lpch2[0] == '-' && lpch2[1] != '-')
return it;
if (lpch2[0] == '\0')
return 0;
lpch2++;
}
}
return 0;
}
}
}
旧样本代码
该示例包含一个继承自RichTextBox的类,并使用EM_SETWORDBREAKPROC
放置一个自定义处理程序。 这个类只会在超过' - '字符时完全断行。 不是之前,也不是之后。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace q6359774
{
class MyRichTextBox : RichTextBox
{
const int EM_SETWORDBREAKPROC = 0x00D0;
const int EM_GETWORDBREAKPROC = 0x00D1;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
this.Text = "abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz";
if (!this.DesignMode)
SendMessage(this.Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, Marshal.GetFunctionPointerForDelegate(new EditWordBreakProc(MyEditWordBreakProc)));
}
[DllImport("User32.DLL")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
delegate int EditWordBreakProc(string lpch, int ichCurrent, int cch, int code);
int MyEditWordBreakProc(string lpch, int ichCurrent, int cch, int code)
{
const int WB_ISDELIMITER = 2;
const int WB_CLASSIFY = 3;
if (code == WB_ISDELIMITER)
{
if (lpch.Length == 0 || lpch == null) return 0;
char ch = lpch[ichCurrent];
return ch == '-' ? 0 : 1;
}
else if (code == WB_CLASSIFY)
{
if (lpch.Length == 0 || lpch == null) return 0;
char ch = lpch[ichCurrent];
var vResult = Char.GetUnicodeCategory(ch);
return (int)vResult;
}
else
{
if (lpch.Length == 0 || lpch == null) return 0;
for (int it = ichCurrent; it < lpch.Length; it++)
{
char ch = lpch[it];
if (ch != '-') return it;
}
}
return 0;
}
}
}
这只是一个草案,所以你可能需要进一步改进它,这样你才能实现目标。
将控件放在窗体中,然后运行。
调整窗口大小,看看这是否是您想要做的!
你将不得不寻求单词边界...我还没有设法让它工作。
我不确定,但如果RichTextBox
实际上包装了一个Windows丰富的编辑控件,你可能会看到这个:
http://msdn.microsoft.com/en-us/library/hh270412%28v=vs.85%29.aspx
或者更具体地说:
http://msdn.microsoft.com/en-us/library/bb787877%28v=vs.85%29.aspx
我希望这有帮助。
我很快就尝试了这个,似乎有效:
this.userControl.richTextBox1.LoadFile("C:\\test.rtf");
this.userControl.richTextBox1.Rtf = this.userControl.richTextBox1.Rtf.Replace(@"\par", String.Empty);
this.userControl.richTextBox1.SaveFile("C:\\test2.rtf", RichTextBoxStreamType.RichText);
这是我的解决方案(基于@Miguel Angelo,但经过修改和纠正):
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class SpaceBreakingRichTextBox : RichTextBox
{
const int EM_SETWORDBREAKPROC = 0x00D0;
const int EM_GETWORDBREAKPROC = 0x00D1;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
AddDelegate();
}
[DllImport("User32.DLL")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
unsafe delegate int EditWordBreakProc(char* lpch, int ichCurrent, int cch, int code);
EditWordBreakProc myDelegate;
unsafe private void AddDelegate()
{
if (!this.DesignMode)
{
myDelegate = new EditWordBreakProc(MyEditWordBreakProc);
SendMessage(this.Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, Marshal.GetFunctionPointerForDelegate(myDelegate));
}
}
unsafe int MyEditWordBreakProc(char* lpch, int ichCurrent, int cch, int code)
{
const int WB_ISDELIMITER = 2;
const int WB_CLASSIFY = 3;
const int WB_MOVEWORDLEFT = 4;
const int WB_MOVEWORDRIGHT = 5;
const int WB_LEFTBREAK = 6;
const int WB_RIGHTBREAK = 7;
const int WB_LEFT = 0;
const int WB_RIGHT = 1;
if (code == WB_ISDELIMITER)
{
char ch = *lpch;
return ch == ' ' ? 1 : 0;
}
else if (code == WB_CLASSIFY)
{
char ch = *lpch;
var vResult = Char.GetUnicodeCategory(ch);
return (int)vResult;
}
else if (code == WB_LEFTBREAK)
{
for (int it = ichCurrent; it >= 0; it--)
{
if (lpch[it] == ' '/* && lpch2[1] != ' '*/)
{
if (it > 0 && lpch[it - 1] != ' ')
return it;
}
}
}
else if (code == WB_RIGHT)
{
for (int it = ichCurrent; ; it++)
{
if (lpch[it] != ' ')
return it;
}
}
else
{
// There might be more cases to handle (see constants)
}
return 0;
}
}
}
请注意,您需要保留委托方法,否则它将从垃圾收集器收集时崩溃(这很难调试)。
基本上,这个子类只在空格处断开,这对我目前的需求来说已经足够了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.