2009-07-01 8 views
22

Ich benutze winforms, und ich aktualisiere ein Textfeld gelegentlich (zeigt Nachrichten). Wenn der Text jedoch das Ende der Box erreicht, erzeugt er Bildlaufleisten und ich weiß nicht, wie man nach unten scrollt. Das einzige, was ich sehe, ist ScrollToCaret, aber Caret steht am Anfang des Textes. Was ist der Befehl zum Scrollen?Wie scrollen Sie in einem Textfeld nach Code in C#

+0

Es wäre nützlich: Erkennen, wenn TextArea- Scroll den unteren Knopf, damit erreicht hat. Ich möchte eine Lizenzvereinbarung in einem Scroll-Textbereich anzeigen und erkennen, wenn der Benutzer zum Ende des Textbereichs gescrollt hat, und dann die Schaltfläche zum Senden aktivieren. Gibt es eine Möglichkeit, das zu tun? – Kiquenet

Antwort

32

Sie können dies durch die Verwendung einer Funktion namens ScrollToCaret machen. Sie müssen zuerst die Einfügemarke an das Ende des Textfelds setzen, und dann können Sie zu ihr hinblättern. Hier ist, wie es zu tun:

 //move the caret to the end of the text 
     textBox.SelectionStart = textBox.TextLength; 
     //scroll to the caret 
     textBox.ScrollToCaret(); 
+1

ScrollToCaret() funktioniert nur, wenn das fragliche Textfeld den Fokus hat. Siehe unten für eine Lösung, die das Textfeld behandelt, das nicht den Fokus hat: http: // stackoverflow.com/questions/1069497/2585177 # 2585177 – Nailuj

+0

Sicher, wenn das tatsächlich der Fall ist, dann würde vorher ein Aufruf von TextBox.Focus funktionieren. Keine Notwendigkeit, Pinvoke zu verwenden. –

+0

Ja, das ist möglich. Aber es könnte sehr gut Fälle geben, in denen Sie den Fokus irgendwo anders in Ihrem Formular behalten möchten, während Sie die TextBox scrollen. Und wenn das der Fall ist, müßten Sie eine zusätzliche Logik implementieren, um das richtige Objekt nach der Ausführung neu zu fokussieren. Aber jetzt bin ich nur wählerisch;) – Nailuj

4

Sie benötigen caret am Ende des Textes zu setzen:

textBox1.Text += "your new text"; 
textBox1.Select(textBox1.Text.Length - 1, 0); 
textBox1.ScrollToCaret(); 
0

Sie die SetScrollPos API verwenden können:

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

[DllImport("user32.dll")] 
static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos); 

const int SB_HORZ = 0; 
const int SB_VERT = 1; 
const int SB_CTL = 2; 


... 

void ScrollToBottom(Control ctl) 
{ 
    int min; 
    int max; 
    if (GetScrollRange(ctl.Handle, SB_VERT, out min, out max)) 
    { 
     SetScrollPos(ctl.Handle, SB_VERT, max, true); 
    } 
} 

(ungetestet)

+0

Dies scrollt nicht wirklich durch die Textbox, es ändert nur die Position der kleinen Taste auf der Bildlaufleiste. –

14

Wenn Sie die AppendText() -Methode der Textbox verwenden, wird der Text sein am unteren Rand eines vorhandenen Textes hinzugefügt und das Steuerelement wird zur Anzeige blättern.

+1

Dies funktioniert auch, wenn die Textbox keinen Fokus hat. –

26

Dies ist ein bisschen eine alte Frage, aber keine der vorgeschlagenen Antworten funktionierte für mich (ScrollToCaret() funktioniert nur, wenn die TextBox den Fokus hat). Also, falls mehr sollte irgendwann dafür wird gesucht, dachte ich, ich würde teilen, was ich die Lösung gefunden werden:

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

    private const int WM_VSCROLL = 0x115; 
    private const int SB_BOTTOM = 7; 

    /// <summary> 
    /// Scrolls the vertical scroll bar of a multi-line text box to the bottom. 
    /// </summary> 
    /// <param name="tb">The text box to scroll</param> 
    public static void ScrollToBottom(TextBox tb) 
    { 
     SendMessage(tb.Handle, WM_VSCROLL, (IntPtr)SB_BOTTOM, IntPtr.Zero); 
    } 
} 

Kredit für die Lösung zu diesem Beitrag an bytes.com gehen sollte: http://bytes.com/topic/c-sharp/answers/248500-scroll-bottom-textbox#post1005377

+2

Es funktioniert !!!!! Ich habe eine Menge Posts gefunden, die ScrollToCaret verwenden, was natürlich nicht funktioniert, wenn das Steuerelement keinen Fokus hat. Das funktioniert! –

+1

Ich wünschte, ich hätte 100 upvotes zu geben. Das ist fantastisch!! –

+0

Es funktioniert aber das Problem ist, die Bildlaufleiste springt auf und ab, kein benutzerfreundliches Aussehen !!! (Gleiches Problem oder noch schlimmer mit dieser ScrollToCarret Solution) –

2

C# Verwenden Scroll Up/Down von Windows-API (user32.dll)

Zuerst müssen wir einen konstanten Wert definieren:

const int EM_LINESCROLL = 0x00B6; 
const int SB_HORZ = 0; 
const int SB_VERT = 1; 

Dann müssen wir zwei externe Methoden der user32.dll erklären:

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

[DllImport("user32.dll")] 
static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); 

Schließlich nutzen diese Methoden, um die reale Sache zu tun:

SetScrollPos(myTextBox.Handle,SB_VERT,myTextBox.Lines.Length-1,true); 
SendMessage(myTextBox.Handle,EM_LINESCROLL,0,myTextBox.Lines.Length-1); 

Fertig! Simpel und einfach! Geprüft! original post

0

Nach der Suche und nie eine legitime Lösung zu finden, als auch horizontal mit und ohne Fokus arbeitet und vertikal, ich über eine API-Lösung gestolpert, die (zumindest für meine Plattform - Win7/.Net4 WinForms) arbeitet.

using System; 
using System.Runtime.InteropServices; 

namespace WindowsNative 
{ 
    /// <summary> 
    /// Provides scroll commands for things like Multiline Textboxes, UserControls, etc. 
    /// </summary> 
    public static class ScrollAPIs 
    { 
     [DllImport("user32.dll")] 
     internal static extern int GetScrollPos(IntPtr hWnd, int nBar); 

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

     [DllImport("user32.dll")] 
     internal static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); 

     public enum ScrollbarDirection 
     { 
      Horizontal = 0, 
      Vertical = 1, 
     } 

     private enum Messages 
     { 
      WM_HSCROLL = 0x0114, 
      WM_VSCROLL = 0x0115 
     } 

     public static int GetScrollPosition(IntPtr hWnd, ScrollbarDirection direction) 
     { 
      return GetScrollPos(hWnd, (int)direction); 
     } 

     public static void GetScrollPosition(IntPtr hWnd, out int horizontalPosition, out int verticalPosition) 
     { 
      horizontalPosition = GetScrollPos(hWnd, (int)ScrollbarDirection.Horizontal); 
      verticalPosition = GetScrollPos(hWnd, (int)ScrollbarDirection.Vertical); 
     } 

     public static void SetScrollPosition(IntPtr hwnd, int hozizontalPosition, int verticalPosition) 
     { 
      SetScrollPosition(hwnd, ScrollbarDirection.Horizontal, hozizontalPosition); 
      SetScrollPosition(hwnd, ScrollbarDirection.Vertical, verticalPosition); 
     } 

     public static void SetScrollPosition(IntPtr hwnd, ScrollbarDirection direction, int position) 
     { 
      //move the scroll bar 
      SetScrollPos(hwnd, (int)direction, position, true); 

      //convert the position to the windows message equivalent 
      IntPtr msgPosition = new IntPtr((position << 16) + 4); 
      Messages msg = (direction == ScrollbarDirection.Horizontal) ? Messages.WM_HSCROLL : Messages.WM_VSCROLL; 
      SendMessage(hwnd, (int)msg, msgPosition, IntPtr.Zero); 
     } 
    } 
} 

Mit einem mehrzeiligen Textfeld (tbx_main) verwenden wie:

 int horzPos, vertPos; 
     ScrollAPIs.GetScrollPosition(tbx_main.Handle, out horzPos, out vertPos); 

     //make your changes 
     //something like the following where m_buffer is a string[] 
     tbx_main.Text = string.Join(Environment.NewLine, m_buffer); 

     tbx_main.SelectionStart = 0; 
     tbx_main.SelectionLength = 0; 

     ScrollAPIs.SetScrollPosition(tbx_main.Handle, horzPos, vertPos); 
Verwandte Themen