Suppressing line breaks in RichTextBox at specific positions

I need to suppress some lines in a RichTextBox.

For example, consider d6+ . There should be no line break between 6 and + . Basically I am looking for something like <nobr> in HTML.

So far I have confused with the insert \ u + FEFF, etc. (which worked on some machines, but some showed vertical lines, possibly a font problem, although the standard font is Windows). I also tried to directly manipulate rtf, i.e. box.rtf = ... with putting some \zwnbo in it, but I never understand it.

Help evaluate.

+4
source share
4 answers

Yes, you can use the entire RichText API with your RichTextBox control.

You may be interested in reading the following sites:

http://www.pinvoke.net/default.aspx/user32.sendmessage - how to send messages to windows using p / invoke.

You can use the Handle property of a RichTextBox to get the window handle of this control, and then send messages to it.

Also look at these files that come with the Microsoft SDK, which will not be used directly in C #, but these files contain all the constants you might need, such as WB_ISDELIMITER , WB_CLASSIFY and others.

  • winuser.h
  • richedit.h

In the following example, I will demonstrate how to use the API provided.

EDIT:

This new sample has code marked as unsafe, but this is better because it does not suffer from a single character string problem, since I can have the char* parameter and manipulate it. The old sample follows this:

This is C # code, not C ++ ... to compile it, you need to go to the project settings and check the box to enable unsafe code .

Right-click the project -> Properties (Alt + Enter) -> Build -> General -> Allow Insecure Code (must be verified)

 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; } } } 

Old sample code

The sample consists of a class that inherits from RichTextBox and places a custom handler using EM_SETWORDBREAKPROC . This class will only break lines exactly when the "-" character. Not earlier and not later.

 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; } } } 

This is just a draft, so you may need to improve it so that you can achieve your goals.

Place the control on the window shape and run.

Resize the window and see what you want to do!

You will need to look for word boundaries ... I have not yet managed to get it to work.

+4
source

I'm not sure, but if the RichTextBox actually wraps the Windows editing editor, you might be lucky to read this:

http://msdn.microsoft.com/en-us/library/hh270412%28v=vs.85%29.aspx

More precisely, this:

http://msdn.microsoft.com/en-us/library/bb787877%28v=vs.85%29.aspx

Hope this helps.

+2
source

I quickly tried this, it seems to work:

 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); 
0
source

Here is my solution (based on @Miguel Angelo, but modified and fixed a bit):

 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; } } } 

Please note that you need to support the delegate method, otherwise it will fail because it will be collected from the garbage collector (which was painful to debug).

Basically, this subclass only breaks into spaces, which is good enough for my needs at the moment.

0
source

All Articles