2009-07-01 22 views
22

Estoy usando winforms, y actualizo un cuadro de texto de vez en cuando (mostrando mensajes). sin embargo, cuando el texto llega al final del cuadro produce barras de desplazamiento y no sé cómo desplazarse hacia abajo hasta la parte inferior. Lo único que veo es ScrollToCaret, pero Caret está al comienzo del texto. ¿Cuál es el comando para desplazarse?Cómo desplazarse hacia abajo en un cuadro de texto por código en C#

+0

Sería útil: Detección de desplazamiento cuando área de texto ha llegado a la parte inferior botón para activar. Quiero mostrar un acuerdo de licencia en un área de texto desplazable y detectar cuando el usuario se haya desplazado hasta la parte inferior del área de texto y luego habilitar el botón Enviar. ¿Hay una manera de hacer eso? – Kiquenet

Respuesta

32

Usted puede hacer esto mediante el uso de una función llamada ScrollToCaret. Primero debe establecer la posición de intercalación al final del cuadro de texto, luego puede desplazarse hacia ella. He aquí cómo hacerlo:

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

ScrollToCaret() solo funcionará si el cuadro de texto en cuestión tiene foco. Vea a continuación una solución que maneja el cuadro de texto sin foco: http: // stackoverflow.com/questions/1069497/2585177 # 2585177 – Nailuj

+0

Seguramente si ese es realmente el caso, una llamada a TextBox.Focus de antemano funcionaría. No es necesario usar pinvoke. –

+0

Sí, eso es posible. Pero podría haber casos en los que le gustaría mantener el foco en otro lugar en su forma mientras se desplaza el TextBox. Y si ese es el caso, tendría que implementar lógica extra para "reenfocar" el elemento correcto después de haber hecho esto. Pero ahora solo estoy siendo exigente;) – Nailuj

4

Es necesario configurar el cursor al final de su texto:

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

Usted puede utilizar el SetScrollPos API:

[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); 
    } 
} 

(no probado)

+0

Esto no hace que se mueva manualmente el cuadro de texto, simplemente cambia la posición del pequeño botón en la barra de desplazamiento. –

14

Si se utiliza el método AppendText() del cuadro de texto, el texto se agregado a la parte inferior de cualquier texto existente y el control se desplazará para mostrarlo.

+1

Esto funciona incluso cuando el cuadro de texto no tiene foco. –

26

Esta es una pregunta un tanto antigua, pero ninguna de las respuestas sugeridas me funcionó (ScrollToCaret() solo funciona cuando TextBox tiene foco). Por lo que en caso de que alguno más deberían buscar esto en algún momento, pensé que me gustaría compartir lo que he encontrado para ser la solución:

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); 
    } 
} 

de crédito para la solución debe ir a esta entrada a bytes.com: http://bytes.com/topic/c-sharp/answers/248500-scroll-bottom-textbox#post1005377

+2

Funciona !!!!! Encontré un montón de mensajes que dicen usar ScrollToCaret, que por supuesto no funciona si el control no tiene foco. ¡Esto funciona! –

+1

Ojalá tuviera 100 votos favorables para dar. ¡Esto es asombroso! –

+0

Funciona, pero el problema es que la barra de desplazamiento salta hacia arriba y hacia abajo, no es fácil de usar. (Mismo problema o incluso peor con la solución ScrollToCarret) –

2

C# uso desplazamiento ascendente/descendente por la API de Windows (user32.dll)

en primer lugar, tenemos que definir un valor constante:

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

Entonces, tenemos que declarar dos métodos externos de user32.dll:

[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); 

Por último, utilizar estos métodos para hacer la cosa real:

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

hecho! ¡Simple y fácil! ¡Probado! original post

0

Después de buscar y no encontrar nunca una solución legítima que funciona con y sin foco, así como en horizontal y en vertical, me encontré con una solución API que funciona (al menos para mi plataforma - Win7/.Net4 WinForms).

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); 
     } 
    } 
} 

Con un cuadro de texto de líneas múltiples (tbx_main) utilizan como:

 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); 
Cuestiones relacionadas