2012-06-19 43 views
4

我有一个标签,它根据RichTextBox上的文本标记行号。我已经挂钩了Vscroll的事件来处理标签。禁用Richtextbox上的平滑滚动

private void rtbLogicCode_VScroll(object sender, EventArgs e) 
{ 
    Point pt = new Point(0, 1); 
    int firstIndex = rtbLogicCode.GetCharIndexFromPosition(pt); 
    int firstLine = rtbLogicCode.GetLineFromCharIndex(firstIndex); 

    pt.X = ClientRectangle.Width; 
    pt.Y = ClientRectangle.Height; 
    int lastIndex = rtbLogicCode.GetCharIndexFromPosition(pt); 
    int lastLine = rtbLogicCode.GetLineFromCharIndex(lastIndex); 

    // Small correction 
    if (rtbLogicCode.Text.EndsWith("\n")) 
     lastLine++; 

    labelLogicCode.ResetText(); 
    LabelLineNum(firstLine+1,lastLine); 
} 
#endregion 

private void LabelLineNum(int startNum, int lastNum) 
{ 
    labelLogicCode.Font = UIConstant.DDCLogicCodeFont; 
    for (int i = startNum; i < lastNum; i++) 
    { 
     labelLogicCode.Text += i + Environment.NewLine; 
    } 
} 

一切似乎除了RichTextBox的使用平滑滚动功能,它搞砸了我的行号在许多情况下,用户一路尚未滚动到下一行的正常工作。这会导致行号与RichTextBox上显示的实际文本不同步。

最后,我需要禁用平滑滚动功能来完成此操作。我被告知你可以重写RichTextBox的postMessage API以禁用所提到的功能,但是在搜索了很多文档后,我找不到任何好的文档。

我将不胜感激尽可能详细的解决方案,如何禁用平滑滚动功能。谢谢。

+0

不回答你的问题,但是从长远来看,更先进的编辑控制可能是为了... [Scintilla的(HTTP:// scintillanet .codeplex.com /)是一种可能性。 –

+0

您无法关闭此功能。 –

+0

'See this' - http://stackoverflow.com/a/4920372/763026'&this' - http://www.codeproject.com/Articles/7830/Scrolling-A-round-with-the-RichTextBox-Control –

回答

5

这是微软提供的VB example,建议您需要拦截WM_MOUSEWHEEL消息。

这里有一个快速原型在C#:

class MyRichTextBox : RichTextBox { 

    [DllImport("user32.dll")] 
    public static extern IntPtr SendMessage(
      IntPtr hWnd,  // handle to destination window 
      uint Msg,  // message 
      IntPtr wParam, // first message parameter 
      IntPtr lParam // second message parameter 
    ); 

    const uint WM_MOUSEWHEEL = 0x20A; 
    const uint WM_VSCROLL = 0x115; 
    const uint SB_LINEUP = 0; 
    const uint SB_LINEDOWN = 1; 
    const uint SB_THUMBTRACK = 5; 

    private void Intercept(ref Message m) { 
     int delta = (int)m.WParam >> 16 & 0xFF; 
     if((delta >> 7) == 1) { 
      SendMessage(m.HWnd, WM_VSCROLL, (IntPtr)SB_LINEDOWN, (IntPtr)0); 
     } else { 
      SendMessage(m.HWnd, WM_VSCROLL, (IntPtr)SB_LINEUP, (IntPtr)0); 
     } 
    } 

    protected override void WndProc(ref Message m) { 
     switch((uint)m.Msg) { 
      case WM_MOUSEWHEEL: 
       Intercept(ref m); 
       break; 
      case WM_VSCROLL: 
       if(((uint)m.WParam & 0xFF) == SB_THUMBTRACK) { 
        Intercept(ref m); 
       } else { 
        base.WndProc(ref m); 
       } 
       break; 
      default: 
       base.WndProc(ref m); 
       break; 
     } 
    } 
} 
+0

我查看了一段时间的代码,并且诚实地不理解代码是如何工作的,因为我对VB没有专业知识。也许我可以在C#中获得对代码的解释吗? – l46kok

+0

我在C#中添加了一个类似的例子 - 它的边缘有点粗糙,但应该让你开始。 – PhilMY

+0

这部分if(((uint)m.WParam&0xFF)== SB_THUMBTRACK){ Intercept(ref m); }'当按下滚动条时不会刷新内容的副作用。我不确定它的目的。 (好的,这是一个旧的答案。) –