2009-03-09 9 views
9

J'ai une fenêtre de consignation de données en lecture seule que j'ai implémentée à l'aide du contrôle RichTextBox. Je voudrais être en mesure de désactiver le défilement automatique qui se produit lorsque l'utilisateur clique dans le contrôle afin que l'utilisateur puisse sélectionner un journal spécifique pour les opérations de copier/coller ou autre. Cependant, dès que l'utilisateur clique dans la RichTextBox, il défile automatiquement vers le bas, ce qui rend la tâche difficile.Empêcher l'auto-défilement dans RichTextBox

Quelqu'un sait comment contourner ce problème?

Merci!

Répondre

6

Vous pouvez jeter un oeil à faire quelque chose comme ceci:

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
private static extern IntPtr LockWindowUpdate(IntPtr Handle); 

puis dans votre méthode qui ajoute des données de log (je fais quelques hypothèses ici) que vous pourriez faire quelque chose comme ceci:

LockWindowUpdate(this.Handle); 
int pos = richTextBox1.SelectionStart; 
int len = richTextBox1.SelectionLength; 
richTextBox1.AppendText(yourText); 
richTextBox1.SelectionStart = pos; 
richTextBox1.SelectionLength = len; 
LockWindowUpdate(IntPtr.Zero); 

J'ai fait une petite application de test avec une minuterie qui a fait l'ajout sur la riche zone de texte et l'a empêché de défiler afin que je puisse faire la sélection de texte. Il a quelques problèmes de position et n'est pas parfait, mais peut-être que cela vous aidera à trouver votre propre solution.

Tout le meilleur!

11

Le contrôle RichTextBox défile automatiquement jusqu'à la sélection en cours, si la sélection n'est pas masquée. RichTextBox.AppendText(), en plus de l'ajout de texte, modifie également la sélection en cours, et déclenche donc indirectement le comportement "autoscrolling". Notez que si RichTextBox.HideSelection est défini sur true, la sélection sera masquée lorsque le contrôle n'est pas actif; cela explique le comportement que vous avez décrit, où le défilement automatique se produit uniquement lorsque l'utilisateur clique sur le contrôle. (Ce qui lui confère mise au point) Pour éviter cela, vous devez faire ce qui suit lors de l'ajout du texte:

  1. Sauvegarde de la sélection initiale
  2. Unfocus le contrôle
  3. Cacher la sélection (par un message Windows)
  4. AppendText
  5. Restaurer la sélection initiale
  6. Unhide sélection
  7. Recentrer le contrôle

Vous pouvez également vérifier si la sélection est déjà à la fin du texte et autoriser le comportement de défilement automatique s'il est - cela émule essentiellement le comportement de la fenêtre Sortie de Visual Studio. Par exemple:

[System.Runtime.InteropServices.DllImport("user32.dll")] 
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam); 
    const int WM_USER = 0x400; 
    const int EM_HIDESELECTION = WM_USER + 63; 

    void OnAppend(string text) 
    { 
     bool focused = richTextBox1.Focused; 
     //backup initial selection 
     int selection = richTextBox1.SelectionStart; 
     int length = richTextBox1.SelectionLength; 
     //allow autoscroll if selection is at end of text 
     bool autoscroll = (selection==richTextBox1.Text.Length); 

     if (!autoscroll) 
     { 
      //shift focus from RichTextBox to some other control 
      if (focused) textBox1.Focus(); 
      //hide selection 
      SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 1, 0); 
     } 

     richTextBox1.AppendText(text); 

     if (!autoscroll) 
     { 
      //restore initial selection 
      richTextBox1.SelectionStart = selection; 
      richTextBox1.SelectionLength = length; 
      //unhide selection 
      SendMessage(richTextBox1.Handle, EM_HIDESELECTION, 0, 0); 
      //restore focus to RichTextBox 
      if(focused) richTextBox1.Focus(); 
     } 
    } 
+0

Votre solution fonctionne comme un charme! J'ai essayé tant d'autres approches pour empêcher mon RichTextBox de défiler après avoir apporté des changements de mise en forme, et c'était le seul qui fonctionnait. Cela semblait alambiqué au début, mais ça a marché :) –

0

solution de SytS a un problème, quand un texte est « en annexe », les mouvements de la barre de défilement de telle sorte que la sélection vers le haut du panneau. Une solution est de sauvegarder/restaurer la position de défilement avec:

[System.Runtime.InteropServices.DllImport("User32.dll")] 
    extern static int GetScrollPos(IntPtr hWnd, int nBar); 

    [System.Runtime.InteropServices.DllImport("user32.dll")] 
    static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw); 

This solution est plus complet pour moi.