2009-03-09 16 views
9

Mam okno do odczytu danych tylko do odczytu, które zaimplementowałem za pomocą formantu RichTextBox. Chciałbym móc wyłączyć automatyczne przewijanie, które ma miejsce, gdy użytkownik kliknie kontrolkę, aby użytkownik mógł wybrać określony dziennik do operacji kopiowania/wklejania lub cokolwiek innego. Jednak, gdy tylko użytkownik kliknie w RichTextBox, automatycznie przewinie się na dół, co utrudni to.Zapobieganie automatycznemu skanowaniu w RichTextBox

Ktoś wie, jak zmienić to zachowanie?

Dzięki!

Odpowiedz

6

Można przyjrzeć się robi coś takiego:

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

następnie w metodzie, która dołącza danych dziennika (robię pewne założenia tutaj) można zrobić coś takiego:

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

Zrobiłem małą aplikację testową z zegarem, który zrobił załącznik na richtextbox i zatrzymał go przed przewijaniem, dzięki czemu mogłem dokonać wyboru tekstu. Ma pewne problemy z pozycjonowaniem i nie jest doskonały, ale być może pomoże ci w rozwiązaniu problemu.

Wszystkiego najlepszego!

11

Formant RichTextBox automatycznie przewija do bieżącego wyboru, jeśli zaznaczenie nie jest ukryte. RichTextBox.AppendText(), oprócz dołączania tekstu, modyfikuje również bieżący wybór, a więc pośrednio uruchamia zachowanie "autoskradania". Zauważ, że jeśli RichTextBox.HideSelection jest ustawione na true, to wybór będzie ukryty, gdy kontrola nie będzie fokusowana; to wyjaśnia opisane zachowanie, w którym automatyczne przewijanie występuje tylko wtedy, gdy użytkownik kliknie kontrolkę. (Tym samym dając mu skupić) Aby temu zapobiec, należy wykonać następujące czynności podczas dopisywania tekstu:

  1. zapasowa wstępnej selekcji
  2. unfocus kontrola
  3. wybór Hide (poprzez wiadomości w systemie Windows)
  4. appendText
  5. przywrócenia pierwotnego wyboru wybór
  6. Unhide
  7. przeorientowania sterowania

Można również sprawdzić, czy zaznaczenie znajduje się już na końcu tekstu, i zezwolić na automatyczne przewijanie, jeśli tak - to zasadniczo emuluje zachowanie okna wyjściowego programu Visual Studio. Na przykład: rozwiązanie

[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

Twoje rozwiązanie działa jak urok! Próbowałem wielu innych podejść, aby uniemożliwić przewijanie RichTextBox po wprowadzeniu zmian formatowania i tylko on działał. Początkowo wydawało się zawiłe, ale zadziałało :) –

0

SytS koszulka ma problemu, gdy jakiś tekst jest „dołączony”, porusza paska przewijania, tak że wybór iść do górnej części panelu. Rozwiązaniem jest zapisać/przywrócić pozycję przewijania z:

[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 jest bardziej kompletny dla mnie.

Powiązane problemy