Richtextbox如何将行号转换为滚动条位置

7

现在我能够使用以下代码片段同步我的两个RichTextBox:

private const int SB_HORZ = 0x0;
private const int SB_VERT = 0x1;
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
private const int SB_THUMBPOSITION = 4;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetScrollPos(int hWnd, int nBar);
[DllImport("user32.dll")]
private static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
private static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam);
internal int HScrollPos
{
    private get { return GetScrollPos((int)this.Handle, SB_HORZ); }
    set
    {
        SetScrollPos((IntPtr)this.Handle, SB_HORZ, value, true);
        PostMessageA((IntPtr)this.Handle, WM_HSCROLL, SB_THUMBPOSITION + 0x10000 * value, 0);
    }
}
internal int VScrollPos
{
    get { return GetScrollPos((int)this.Handle, SB_VERT); }
    set
    {
        SetScrollPos((IntPtr)this.Handle, SB_VERT, value, true);
        PostMessageA((IntPtr)this.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * value, 0);
    }
}

我可以在按下、弹起和滚动事件时同步 RichTextBoxes。 但事实上,我的目标不是这样,我想要根据内容同步我的 RichTextBoxes我需要做什么:
  • 从未选中的 RichTextBox 中获取当前行。
  • 使用另一个 RichTextBox 中的行号设置滚动条位置(无需从当前位置失去焦点)。
  • 使用滚动条位置获取行号。

注意: 如果您需要更多细节,请随时询问。
提前感谢。

我认为这个例子对你会有帮助 http://www.codeproject.com/Articles/12152/Numbering-lines-of-RichTextBox-in-NET - askeet
这是WinForm应用程序吗? - Ian
你想要根据焦点行(光标)或视图框的第一行来同步滚动两个RichTextBox吗? - Xiaoy312
我已经同步了两个“RichTextBox”,但是我使用了滚动条位置,但我需要使用行号来同步它们。 - Badro Niaimi
1个回答

1

据我所了解,您需要基于行号在2个RichTextBox上同步滚动。如果我理解有误,请留言告诉我。

RichTextBox扩展:

public class RichTextBoxEx : RichTextBox
{
    // combination of multiple events that may cause focus(caret) to change
    public event EventHandler FocusChanged;

    public RichTextBoxEx()
    {
        this.KeyPress += (s, e) => RaiseFocusChanged();
        this.KeyDown += (s, e) => RaiseFocusChanged();
        this.KeyUp += (s, e) => RaiseFocusChanged();
        this.MouseClick += (s, e) => RaiseFocusChanged();
    }

    private void RaiseFocusChanged()
    {
        var focusChanged = FocusChanged;
        if (focusChanged != null)
        {
            focusChanged(this, null);
        }
    }

    public int GetFirstSelectedLine()
    {
        var index = GetFirstCharIndexOfCurrentLine();
        return GetLineFromCharIndex(index);
    }
    public int GetFirstVisibleLine()
    {
        var index = GetCharIndexFromPosition(new Point(1, 1));
        return GetLineFromCharIndex(index);
    }

    public void ScrollToLine(int line)
    {
        if (line < 0)
            throw new ArgumentOutOfRangeException("line cannot be less than 0");

        // save the current selection to be restored later
        var selection = new { SelectionStart, SelectionLength };

        // select that line and scroll it to
        Select(GetFirstCharIndexFromLine(line) + 1, 0);
        ScrollToCaret();

        // restore selection
        Select(selection.SelectionStart, selection.SelectionLength);
    }
}

使用方法:

void Main()
{
    var mainScreenArea = Screen.PrimaryScreen.WorkingArea;

    var rich1 = new RichTextBoxEx() { Width = mainScreenArea.Width / 2 - 10, Dock = DockStyle.Left };
    var rich2 = new RichTextBoxEx() { Width = mainScreenArea.Width / 2 - 10, Dock = DockStyle.Right };
    rich1.LoadFile(__RTF_FILE_0__);
    rich2.LoadFile(__RTF_FILE_1__);

    // pick one :
    // synchronize by focus
    rich1.FocusChanged += (s, e) => rich2.ScrollToLine(rich1.GetFirstSelectedLine());
    // synchronize by viewbox
    // rich1.VScroll += (s, e) => rich2.ScrollToLine(rich1.GetFirstVisibleLine());

    var form = new Form();
    form.Controls.Add(rich1);
    form.Controls.Add(rich2);

    form.WindowState = FormWindowState.Maximized;
    form.ShowDialog()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接