Sto usando winforms e aggiorno una casella di testo una volta ogni tanto (mostrando messaggi). tuttavia, quando il testo raggiunge la fine della scatola produce barre di scorrimento e non so come scorrere verso il basso. L'unica cosa che vedo è ScrollToCaret, ma Caret è all'inizio del testo. Qual è il comando per scorrere?Come scorrere verso il basso in una casella di testo per codice in C#
risposta
Si può fare questo facendo uso di una funzione chiamata ScrollToCaret. È necessario prima impostare la posizione del punto di inserimento fino alla fine della casella di testo, quindi è possibile scorrere ad essa. Ecco come fare:
//move the caret to the end of the text
textBox.SelectionStart = textBox.TextLength;
//scroll to the caret
textBox.ScrollToCaret();
ScrollToCaret() funziona solo se la casella di testo in questione è attiva. Vedi sotto per una soluzione che gestisce anche la casella di testo che non ha il focus: http: // StackOverflow.it/questions/1069497/2585177 # 2585177 – Nailuj
Sicuramente se questo è davvero il caso, allora una chiamata a TextBox.Focus in anticipo funzionerebbe. Non c'è bisogno di usare Pinvoke. –
Sì, è possibile. Ma ci potrebbero benissimo essere casi in cui ti piacerebbe mantenere l'attenzione da qualche altra parte nel tuo modulo durante lo scorrimento del TextBox. E se questo è il caso, dovresti implementare una logica extra per "ri-focalizzare" l'elemento corretto dopo averlo fatto. Ma ora sono solo schizzinoso;) – Nailuj
è necessario impostare il vostro punto di inserimento alla fine del testo:
textBox1.Text += "your new text";
textBox1.Select(textBox1.Text.Length - 1, 0);
textBox1.ScrollToCaret();
È possibile utilizzare il 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);
}
}
(non testato)
Questo non scorre acutamente la casella di testo, ma modifica semplicemente la posizione del piccolo pulsante sulla barra di scorrimento. –
Se si utilizza il metodo AppendText() della casella di testo, il testo sarà aggiunto in fondo a qualsiasi testo esistente e il controllo scorrerà per visualizzarlo.
Funziona anche quando la casella di testo non ha il focus. –
Questa è una domanda un po 'vecchia, ma nessuna delle risposte suggerite ha funzionato per me (ScrollToCaret() funziona solo quando il controllo TextBox è attivo). Quindi, nel caso in cui più dovrebbe essere alla ricerca di questo ad un certo punto, ho pensato di condividere quello che ho trovato essere la soluzione:
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);
}
}
di credito per la soluzione dovrebbe andare a questo post a bytes.com: http://bytes.com/topic/c-sharp/answers/248500-scroll-bottom-textbox#post1005377
Funziona !!!!! Ho trovato un messaggio di miliardi che diceva di usare ScrollToCaret che ovviamente non funziona se il controllo non ha il focus. Funziona! –
Vorrei avere 100 voti positivi da dare. Questo e spettacolare!! –
Funziona ma il problema è che la barra di scorrimento salta su e giù, non un aspetto user friendly !!! (stesso problema o anche peggio con quella ScrollToCarret soloution) –
C# Usa scorrere su/giù da Windows API (user32.dll)
In primo luogo, dobbiamo definire un valore costante:
const int EM_LINESCROLL = 0x00B6;
const int SB_HORZ = 0;
const int SB_VERT = 1;
Poi, dobbiamo dichiarare due metodi esterni di 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);
Infine, utilizzare questi metodi per fare la cosa vera:
SetScrollPos(myTextBox.Handle,SB_VERT,myTextBox.Lines.Length-1,true);
SendMessage(myTextBox.Handle,EM_LINESCROLL,0,myTextBox.Lines.Length-1);
Fatto! Semplice e facile! Provato! original post
Dopo aver cercato e mai trovare una soluzione legittima che funziona con e senza messa a fuoco così come orizzontalmente e verticalmente, mi sono imbattuto in una soluzione di API che funziona (almeno per la mia piattaforma - 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 una casella di testo multilinea (tbx_main) utilizzare come:
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);
Sarebbe utile: rilevare quando textarea di scorrimento ha raggiunto il fondo pulsante per abilitare. Voglio visualizzare un accordo di licenza in un'area di testo a scorrimento e rilevare quando l'utente ha spostato fino alla fine dell'area di testo, quindi attivare il pulsante di invio. C'è un modo per farlo? – Kiquenet