我现在可以使用这段代码同步我的两个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 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,WM_VSCROLL,0); } }
我可以在按键,向上和Vscroll事件时同步RichTextBox.
确实这不是我的目标,我想根据内容同步我的RichTextBoxes,
我需要的:
>获取当前行形式的非选定RichTextBox.
>使用另一个RichTextBox中的行号设置滚动条位置(不会丢失当前焦点的焦点).
>从滚动条位置获取行号.
注意:欢迎您询问是否需要更多详细信息.
提前致谢.
解决方法
据我所知,您需要根据行号同步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() }