WPF RichTextBox 當前光標後一個字符是文檔的第幾個字符

WPF RichTextBox 當前光標後一個字符是文檔的第幾個字符

運行環境:Win10 x64, NetFrameWork 4.8, 做者:烏龍哈里,日期:2019-05-05
數組


參考:

 

 

章節:

  1. 挑選顯示數據容器歷程
  2. 讀取文本到 RichTextBox
  3. 計算第幾個字符

1、挑選顯示數據容器歷程

最近想寫一個相似 UltraEdit 查看文件內容,以16進制顯示每字節。首先碰到的問題就是下面這個界面:


ui

在 WPF 下嘗試了很多方法,同時讀一個28k byte 的文件,利弊以下:

方法一:用 Canvas 作容器,一個字節一個 Textbox,寫入、修改、變色等操做是很方便,結果載入數據顯示的時候要停頓10多秒,並且內存佔用達到了1g 以上,一樣的文件 UltraEdit 才佔用 28m 左右。放棄;

方法二:把 TextBox 換成輕量些的 TextBlock,內存佔用達 120m左右,載入數據也比較慢,放棄;

方法三:還用 TextBox ,可是隻用顯示頁面上能擺放的數量,再也不一個字節一個,佔用才60多兆,但用鼠標滾動翻頁時,停頓感很強,不流暢。放棄;

方法三:用 一個字節一個 GlyphRun 直接在 Canvas上畫出來,內存佔用也很大,比方法二還要大,不明因此,放棄;

方法四:用 一個字節一個 FormattedText 畫在 Canvas 上,直接在 Canvas 的 OnRender() 裏生成也佔用內存 80多兆。不在 OnRender() 裏須要把 FormattedText 轉化成 FrameworkElement,佔用直接上到120多兆。放棄

最後發現用 一個 RichTextBox 來載入數據又快又省,佔用內存才28m,和 UltraEdit 至關。(不用單個 TextBox 是由於改動時想標記不一樣顏色,TextBox 很難作到)。
之後把這些實驗的心得也記錄下來。

spa

2、讀取文本到 RichTextBox

StringBuilder sb = new StringBuilder();
for (int i = 0; i < CntData.Length; i++)//CntData是讀取文件的字節數組
{
    if (i % NumInLine == 0 && i != 0) //NumInLine=16 每行顯示16個字節
    {
        sb.Append("\r\n");
    }
    sb.Append(CntData[i].ToString("X2"));
    sb.Append(" ");
}
//--TextRange.Text=sb.ToString()方法比下面用 Paragraph 的要慢好多
//TextRange tr = new TextRange(rtbShow.Document.ContentStart, rtbShow.Document.ContentEnd);
//tr.Text = sb.ToString();
Paragraph p = new Paragraph();
p.Inlines.Add(new Run(sb.ToString()));
rtbShow.Document.Blocks.Add(p);//rtbShow RichTextBox 控件的名稱
InputMethod.SetIsInputMethodEnabled(rtbShow, false);//關掉輸入法
//把輸入改爲 overwrite 模式
PropertyInfo textEditorProperty = typeof(RichTextBox).GetProperty("TextEditor", BindingFlags.NonPublic | BindingFlags.Instance);
object textEditor = textEditorProperty.GetValue(rtbShow, null);
// set _OvertypeMode on the TextEditor
PropertyInfo overtypeModeProperty = textEditor.GetType().GetProperty("_OvertypeMode", BindingFlags.NonPublic | BindingFlags.Instance);
overtypeModeProperty.SetValue(textEditor, true, null);

3、計算第幾個字符

//---計算當前鼠標後一個字符從文檔開始字符起算是第幾個字符
private int GetCharOffset(RichTextBox rtb)
{
    TextPointer start = rtb.CaretPosition;//當前鼠標位置
     int n = 0;
    TextPointerContext tpc = start.GetPointerContext(LogicalDirection.Backward);
    while (tpc!=TextPointerContext.None)
    {
        if (tpc == TextPointerContext.Text) n++;
        start = start.GetPositionAtOffset(-1, LogicalDirection.Backward);//注意是 -1
        tpc = start.GetPointerContext(LogicalDirection.Backward);
    }
    return n-1;//從0起算
}

看了 MS 關於 GetPositionAtOffset() 的解釋:
參數
offset
Int32
偏移量(以符號數爲單位),使用它計算並返回位置。 若是偏移量爲負,則返回的 TextPointer 位於當前 TextPointer 以前;不然,位於它以後。
direction
LogicalDirection
LogicalDirection 值之一,它指定返回的 TextPointer 的邏輯方向。

上面那段程序中只能寫-1,要是是 1的話,永遠得不到 TextPointerContext.None 。orm

相關文章
相關標籤/搜索