5

RichTextBoxのテキストに基づいて行番号にラベルを付けるラベルがあります。ラベル付けを処理するためにVscrollのイベントをフックしました。

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のpostMessageAPIをオーバーライドして、前述の機能を無効にできると言われましたが、多くのドキュメントを検索したところ、適切なドキュメントが見つかりませんでした。

スムーズスクロール機能を無効にする方法について、可能な限り詳細な解決策をいただければ幸いです。ありがとう。

4

2 に答える 2

5

これはMicrosoftのVBの例で、メッセージを傍受する必要があることを示唆してい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;
        }
    }
}
于 2012-06-19T15:29:49.653 に答える
1

私はこれが古いことを知っていますが、Dan Sporiciのサイトがダウンした場合、私は彼の素晴らしい解決策を投稿すると思いました。シンプルで、コピー&ペーストするだけで簡単に動作します。

class editedRichTextBox : RichTextBox
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

    //this message is sent to the control when we scroll using the mouse
    private const int WM_MOUSEWHEEL = 0x20A;

    //and this one issues the control to perform scrolling
    private const int WM_VSCROLL = 0x115;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_MOUSEWHEEL)
        {
            int scrollLines = SystemInformation.MouseWheelScrollLines;
            for (int i = 0; i < scrollLines; i++)
            {
                if ((int)m.WParam > 0) // when wParam is greater than 0
                    SendMessage(this.Handle, WM_VSCROLL, (IntPtr)0, IntPtr.Zero); // scroll up 
                else  
                    SendMessage(this.Handle, WM_VSCROLL, (IntPtr)1, IntPtr.Zero); // else scroll down
            }
            return;
        }
        base.WndProc(ref m);
    }
}
于 2021-01-12T05:02:39.023 に答える