Scroll ligne par ligne d'un RichTextBox

cs_Zaghor Messages postés 3 Date d'inscription mercredi 7 février 2007 Statut Membre Dernière intervention 24 août 2007 - 23 août 2007 à 22:52
cs_Zaghor Messages postés 3 Date d'inscription mercredi 7 février 2007 Statut Membre Dernière intervention 24 août 2007 - 24 août 2007 à 13:44
Bonjour à tous,

Voici mon problème, qui peut-être est assez classique, néanmoins je n'ai trouvé qu'un seul exemple de code sur le net, et en plus il est en VB6.0 ...

J'aimerais forcer le VScroll de ma RichTextBox à défiler ligne par ligne plutôt que pixel par pixel, comme le ferait un TextBox en fait !

Le principe exposé par le programmeur VB6.0 est le suivant : récupérer le message WM_MOUSEWHEEL et le remplacer par EM_LINESCROLL.

Ce qui donne en VB6.0 :

Option Explicit

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
    ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
    ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As _
    Any, source As Any, ByVal bytes As Long)

Private Const GWL_WNDPROC = (-4)
Private Const WM_MOUSEWHEEL = &H20A
Private Const EM_LINESCROLL = &HB6

Private lPrevProc As Long

Public Sub SubClass(ByVal lhWnd As Long)
    lPrevProc = SetWindowLong(lhWnd, GWL_WNDPROC, AddressOf WndProc)
End Sub

Private Function WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim intDir As Integer
   
    If Msg = WM_MOUSEWHEEL Then
        CopyMemory intDir, ByVal VarPtr(wParam) + 2, 2
        intDir = -Sgn(intDir) * 3
        WndProc = CallWindowProc(lPrevProc, hWnd, EM_LINESCROLL, 0&, intDir)
    Else
        WndProc = CallWindowProc(lPrevProc, hWnd, Msg, wParam, lParam)
    End If
End Function

Public Sub UnSubClass(ByVal lhWnd As Long)
    SetWindowLong lhWnd, GWL_WNDPROC, lPrevProc
End Sub

Est-il possible de traduire ce code en C# ?? Et si oui, pouvez-vous me donner quelques pistes ?

Bien à vous

2 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
24 août 2007 à 09:31
Salut, dans ton exemple c'est uniquement sur le message WM_MOUSEWHEEL, c-a-d uniquement lorsque la roulette de la souris bouge que la RichTextBox est scrollé ligne par ligne.

public partial class Form1 : Form
{
    public Form1( )
    {
        InitializeComponent( );


        MyRichTextBox rtb = new MyRichTextBox( );
        rtb.Parent = this;
        rtb.Dock = DockStyle.Fill;
    }
}



public class MyRichTextBox : RichTextBox
{
    // using System.Runtime.InteropServices;
    [ DllImport( "User32.dll" ) ]
    private static extern IntPtr SendMessage
    (
        IntPtr hWnd,
        uint msg,
        UIntPtr wParam,
        IntPtr lParam
    );



    private const int WM_MOUSEWHEEL = 0x020A;
    private const int EM_LINESCROLL = 0x00B6;



    protected override void WndProc( ref Message m )
    {
        if ( m.Msg == WM_MOUSEWHEEL )
        {
            SendMessage
            (
                this.Handle,
                EM_LINESCROLL,
                UIntPtr.Zero,
                ( IntPtr )( -Math.Sign( ( short )( ( int )m.WParam >> 16 ) ) )
            );



            m.Result = IntPtr.Zero;
            return;
        }



        base.WndProc( ref m );
    }
}
0
cs_Zaghor Messages postés 3 Date d'inscription mercredi 7 février 2007 Statut Membre Dernière intervention 24 août 2007
24 août 2007 à 13:44
Merci Lutinore cela fonctionne parfaitement !

Mais effectivement tu as raison je me suis fait avoir il ne s'agit bien que d'un scroll de souris ...

Je suis en train de galérer depuis ce matin en m'inspirant de ton code mais c'est carrément la galère, j'ai récupéré un truc sur un site japonais en essayant de l'adapter mais je m'arrache les cheveux.

En plus du if(m.Msg = = WM_MOUSEWHEEL)
{ ... }

j'ai rajouté le code suivant qui ne fonctionne absolument pas :

private const int WM_VSCROLL = 0x0115;
private const uint SB_LINEDOWN = 1;
private const uint SB_LINEUP = 0;
private const uint SB_PAGEDOWN = 3;
private const uint SB_PAGEUP = 2;
private const uint SB_ENDSCROLL = 8;
private const uint SB_BOTTOM = 7;

if (m.Msg == WM_VSCROLL && m.WParam > SB_ENDSCROLL)
{
    int currentPos = m.WParam.ToInt32();
    UIntPtr wParam;

    if (currentPos > this.position)
        wParam = new UIntPtr(SB_LINEUP);
    else
        wParam = new UIntPtr(SB_LINEDOWN);

    SendMessage(this.Handle, Convert.ToUInt32(m.Msg), wParam, m.LParam);

    this.position = currentPos;

    m.Result = IntPtr.Zero;
    return;
}

L'idée c'est donc bien sûr de transformer un message WM_SCROLL en SCROLL de ligne ...

Je pédale peut-être dans la choucroute pour rien ?

Merci d'un petit coup de pouce svp !
0
Rejoignez-nous