簡體   English   中英

在某些位置抑制RichTextBox中的換行符

[英]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發送消息。

您可以使用RichTextBoxHandle屬性來獲取該控件的窗口句柄,然后向其發送消息

另請查看這些包含來自Microsoft的SDK的包含文件,它們不會直接在C#中使用,但這些文件會WB_ISDELIMITER您可能必須使用的所有常量,例如WB_ISDELIMITERWB_CLASSIFY等。

  • WINUSER.H
  • richedit.h

在以下示例中,我演示了如何使用提供的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM