2009-03-09 2 views
9

Ho una finestra di registrazione dei dati in sola lettura che ho implementato utilizzando il controllo RichTextBox. Mi piacerebbe essere in grado di disabilitare lo scorrimento automatico che si verifica quando l'utente fa clic nel controllo in modo che l'utente possa selezionare un registro specifico per le operazioni di copia/incolla o altro. Tuttavia, non appena l'utente fa clic nel RichTextBox, scorre automaticamente verso il basso, rendendo così difficile.Impedire lo scorrimento automatico in RichTextBox

Qualcuno conosce un modo per ignorare questo comportamento?

Grazie!

risposta

6

si potrebbe dare un'occhiata a fare qualcosa di simile:

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

poi nel metodo che aggiunge dati di log (sto facendo alcune ipotesi qui) si potrebbe fare qualcosa di simile:

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

Ho fatto una piccola app di test con un timer che ha fatto l'append sul Richtextbox e l'ha impedito di scorrere, così ho potuto fare la selezione del testo. Ha alcuni problemi posizionali e non è perfetto, ma forse ti aiuterà a muoverti verso una soluzione tutta tua.

Tutto il meglio!

11

Il controllo RichTextBox scorre automaticamente alla selezione corrente, se la selezione non è nascosta. RichTextBox.AppendText(), oltre ad aggiungere testo, modifica anche la selezione corrente, attivando così indirettamente il comportamento di "autoscrolling". Si noti che se RichTextBox.HideSelection è impostato su true, la selezione verrà nascosta quando il controllo non è a fuoco; questo spiega il comportamento che hai descritto, in cui lo scorrimento automatico avviene solo quando l'utente fa clic nel controllo. (Dando in tal modo messa a fuoco) Per evitare questo, è necessario effettuare le seguenti operazioni quando si aggiunge il testo:

  1. Backup la selezione iniziale
  2. unfocus il controllo
  3. Nascondi selezione (attraverso un messaggio di Windows)
  4. AppendText
  5. ripristinare la selezione iniziale selezione
  6. Unhide
  7. Refocus controllo

Si potrebbe anche voler verificare se la selezione è già alla fine del testo e consentire il comportamento di autoscrettatura se questo è - questo essenzialmente emula il comportamento della finestra di output di Visual Studio. Ad esempio: soluzione

[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

La tua soluzione funziona come un fascino! Ho provato tanti altri approcci per impedire al mio RichTextBox di scorrere dopo aver apportato modifiche alla formattazione, e questo era l'unico che funzionava. All'inizio sembrava complicato, ma ha funzionato :) –

0

delle SytS presenta un problema, quando un testo viene "aggiunto", la barra di scorrimento si sposta in modo tale che la selezione andare alla parte superiore del pannello. Una soluzione è quella di salvare/ripristinare la posizione di scorrimento con:

[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 è più completo per me.