मैं अपने आप एक बहुस्तरीय टेक्स्ट बॉक्स के नीचे कैसे स्क्रॉल कर सकता हूं?


295

मेरे पास एक टेक्स्टबॉक्स है। म्यूटिलिन संपत्ति सत्य पर सेट है। नियमित अंतराल पर, मैं इसमें पाठ की नई लाइनें जोड़ रहा हूं। जब भी कोई नई लाइन जोड़ी जाती है, मैं टेक्स्टबॉक्स को स्वचालित रूप से सबसे नीचे प्रवेश (सबसे नया) में स्क्रॉल करना चाहूंगा। मैं इसे कैसे पूर्ण करूं?


6
उत्तर के लिए यहाँ देखा, यह नहीं मिल सका, इसलिए जब मुझे लगा, तो मुझे लगा कि मैं इसे भविष्य के उपयोगकर्ताओं के लिए यहाँ रख दूंगा, या हो सकता है कि किसी और के पास बेहतर दृष्टिकोण हो।
GWLlosa

2
मुझे VBA में वही काम करने की ज़रूरत थी, जिसमें ये सभी फैंसी-पैंट नए .NET तरीके नहीं हैं। भविष्य के गूगल-फू के लिए, यहाँ है: पाठ बॉक्स 1। पाठ = पाठ बॉक्स 1। पाठ और "जो कुछ भी"; TextBox1.SelStart = लेन (TextBox1.Text); TextBox1.SetFocus; ... और फिर एक .Setocus जो भी नियंत्रण से पहले ध्यान केंद्रित किया था। TextBox1 पर ध्यान दिए बिना, यह अपने स्क्रॉलबार को कभी भी अपडेट नहीं करेगा चाहे मैंने कुछ भी किया हो।
गॉर्डन ब्रूम

1
@GordonBroom Whelp, इसके लिए धन्यवाद कि मैं अब "कोड स्निपेट" "झुकाव" को कॉल करना शुरू करने जा रहा हूं। अच्छा कार्य। : डी
सिडनी

जवाबों:


425

नियमित अंतराल पर, मैं इसमें पाठ की नई लाइनें जोड़ रहा हूं। जब भी कोई नई लाइन जोड़ी जाती है, मैं टेक्स्टबॉक्स को स्वचालित रूप से सबसे नीचे प्रवेश (सबसे नया) में स्क्रॉल करना चाहूंगा।

यदि आप उपयोग करते हैं TextBox.AppendText(string text), तो यह स्वचालित रूप से नए संलग्न पाठ के अंत तक स्क्रॉल करेगा। यदि आप इसे लूप में बुला रहे हैं तो यह टिमटिमाता स्क्रॉलबार से बचा जाता है।

यह .Textसंपत्ति पर सहमति से अधिक परिमाण का क्रम होता है । हालाँकि यह इस पर निर्भर हो सकता है कि आप इसे कितनी बार बुला रहे हैं; मैं एक तंग पाश के साथ परीक्षण कर रहा था।


यह स्क्रॉल नहीं होगा यदि इसे टेक्स्टबॉक्स दिखाए जाने से पहले कहा जाता है, या यदि टेक्स्टबॉक्स अन्यथा दिखाई नहीं देता है (उदाहरण के लिए एक TabPanel के अलग टैब में)। टेक्स्टबॉक्स देखें ।AppendText () ऑटोस्क्रोलिंग नहीं । यह महत्वपूर्ण हो सकता है या नहीं भी हो सकता है, यह इस बात पर निर्भर करता है कि जब उपयोगकर्ता टेक्स्टबॉक्स को नहीं देख सकता है, तो आपको ऑटोस्कोप की आवश्यकता होती है।

ऐसा लगता है कि अन्य उत्तरों से वैकल्पिक विधि भी इस मामले में काम नहीं करती है। इसके आसपास एक तरीका यह है कि VisibleChangedघटना पर अतिरिक्त स्क्रॉलिंग करें :

textBox.VisibleChanged += (sender, e) =>
{
    if (textBox.Visible)
    {
        textBox.SelectionStart = textBox.TextLength;
        textBox.ScrollToCaret();
    }
};

आंतरिक रूप से, AppendTextकुछ इस तरह से होता है:

textBox.Select(textBox.TextLength + 1, 0);
textBox.SelectedText = textToAppend;

लेकिन इसे मैन्युअल रूप से करने का कोई कारण नहीं होना चाहिए।

(यदि आप इसे स्वयं विघटित करते हैं, तो आप देखेंगे कि यह कुछ अधिक कुशल आंतरिक विधियों का उपयोग करता है, और ऐसा लगता है कि एक मामूली मामला है।)


7
यह तरीका ज्यादा तेज और स्मूथ है। स्क्रॉल बार की कोई 'टिमटिमा' नहीं है (जो तेजी से उत्तराधिकार में कई कॉल करते समय अधिक ध्यान देने योग्य है)।
टॉलग्य

3
यह एक है ज्यादा बेहतर समाधान।
जेफ

3
अपने आप को खाने के लिए tb.Text += ....और WndProc और मार्शलों के साथ बनाने की कोशिश कर रहा था अब मुझे बेवकूफ लगता है: D
Saeid Yazdani

3
टेक्सारिया पर भी ध्यान केंद्रित करने की आवश्यकता है, पहली बार जब मैंने ऐसा किया तो इसे स्क्रॉल नहीं किया गया क्योंकि इसमें फोकस नहीं था।
Qwerty01

3
AppendText ने स्वचालित रूप से मेरे ReadOnly TextBox को स्क्रॉल नहीं किया, लेकिन TextBox.ScrollToEnd () जोड़कर; AppendText कॉल के बाद चाल चली।
ब्रैंडन बार्कले

143

आप निम्नलिखित कोड स्निपेट का उपयोग कर सकते हैं:

myTextBox.SelectionStart = myTextBox.Text.Length;
myTextBox.ScrollToCaret();

जो स्वचालित रूप से अंत तक स्क्रॉल करेगा।


5
उत्तर के लिए यहाँ देखा, यह नहीं मिल सका, इसलिए जब मुझे लगा, तो मुझे लगा कि मैं इसे भविष्य के उपयोगकर्ताओं के लिए यहाँ रख दूंगा, या हो सकता है कि किसी और के पास बेहतर दृष्टिकोण हो।
GWLlosa

4
यह उस समय सबसे अच्छा जवाब हो सकता था, लेकिन अब मुझे लगता है कि बॉब का जवाब ओपी की समस्या का बेहतर समाधान है।
tomsv

38

ऐसा लगता है कि इंटरफ़ेस .NET में बदल गया है 4.0 । निम्नलिखित विधि है जो उपरोक्त सभी को प्राप्त करती है। जैसा कि टॉमी एनजबर्त्सेन ने सुझाव दिया, इसे टेक्स्टचेनड इवेंट हैंडलर में डालने से यह स्वचालित हो जाता है।

textBox1.ScrollToEnd();

21
ध्यान दें कि यह विधि नाम स्थान ( विधानसभा, WPF) TextBoxBaseमें कक्षा में है । यह विधि मौजूद नहीं है और WinForms में काम नहीं करेगी, जिसका वर्ग नामस्थान ( असेंबली, WinForms) से विरासत में मिला है । System.Windows.Controls.PrimitivesPresentationFrameworkTextBoxTextBoxBaseSystem.Windows.FormsSystem.Windows.Forms
बॉब

1
ध्यान दें कि ScrollToEnd()बेहद खराब प्रदर्शन हो सकता है। मेरे ऐप में यह प्रोफाइलिंग समय के 50% से अधिक के लिए जिम्मेदार है।
ergohack

16

सुझाए गए कोड को TextChanged इवेंट में जोड़ने का प्रयास करें:

private void textBox1_TextChanged(object sender, EventArgs e)
{
  textBox1.SelectionStart = textBox1.Text.Length;
  textBox1.ScrollToCaret();
}

10
textBox1.Focus()
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();

मेरे लिए काम नहीं किया (विंडोज 8.1, जो भी कारण हो)।
और जब से मैं अभी भी .NET 2.0 पर हूं, तब तक मैं ScrollToEnd का उपयोग नहीं कर सकता।

लेकिन यह काम करता है:

public class Utils
{
    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern int SendMessage(System.IntPtr hWnd, int wMsg, System.IntPtr wParam, System.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(System.Windows.Forms.TextBox tb)
    {
        if(System.Environment.OSVersion.Platform != System.PlatformID.Unix)
             SendMessage(tb.Handle, WM_VSCROLL, new System.IntPtr(SB_BOTTOM), System.IntPtr.Zero);
    }


}

VB.NET:

Public Class Utils
    <System.Runtime.InteropServices.DllImport("user32.dll", CharSet := System.Runtime.InteropServices.CharSet.Auto)> _
    Private Shared Function SendMessage(hWnd As System.IntPtr, wMsg As Integer, wParam As System.IntPtr, lParam As System.IntPtr) As Integer
    End Function

    Private Const WM_VSCROLL As Integer = &H115
    Private Const SB_BOTTOM As Integer = 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 Shared Sub ScrollToBottom(tb As System.Windows.Forms.TextBox)
        If System.Environment.OSVersion.Platform <> System.PlatformID.Unix Then
            SendMessage(tb.Handle, WM_VSCROLL, New System.IntPtr(SB_BOTTOM), System.IntPtr.Zero)
        End If
    End Sub


End Class

विंडोज 10 के साथ भी यही समस्या थी, आपका वर्कअॉर्न यहां भी ठीक काम करता है।
हेंस

कोई भी मेरे लिए काम नहीं कर रहा था, लेकिन यह। भगवान आपकी आत्मा को शांति दे
Emirhan lenzlen

9

मुझे एक ताज़ा जोड़ने की ज़रूरत थी:

textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();

4

मुझे एक साधारण अंतर मिला, जिसे इस धागे में संबोधित नहीं किया गया है।

यदि आप ScrollToCarat()अपने फॉर्म के Load()ईवेंट के हिस्से के रूप में सभी कॉल कर रहे हैं , तो यह काम नहीं करता है। मैंने सिर्फ ScrollToCarat()अपने फॉर्म के Activated()ईवेंट में अपना कॉल जोड़ा , और यह ठीक काम करता है।

संपादित करें

केवल पहली बार फ़ॉर्म की Activatedघटना को स्क्रॉल करना महत्वपूर्ण है (बाद में सक्रियणों पर नहीं), या यह हर बार स्क्रॉल करेगा कि आपका फ़ॉर्म सक्रिय है, जो कुछ ऐसा है जो आप शायद नहीं चाहते हैं।

इसलिए यदि आप केवल Activated()अपने कार्यक्रम को स्क्रॉल करने के लिए इवेंट को ट्रैप कर रहे हैं जब आपका प्रोग्राम लोड होता है, तो आप ईवेंट हैंडलर के अंदर ईवेंट को अनसब्सक्राइब कर सकते हैं, इस प्रकार:

Activated -= new System.EventHandler(this.Form1_Activated);

यदि आपके पास अन्य चीजें हैं जो आपको अपने फॉर्म के सक्रिय होने पर हर बार करने की आवश्यकता होती हैं, तो आप boolपहली बार अपने सच को सेट कर सकते हैंActivated() , तो आप ईवेंट को निकाल दिए , इसलिए आप बाद की सक्रियताओं पर स्क्रॉल नहीं करते हैं, लेकिन फिर भी सकती है, जिनकी आपको आवश्यकता है करना।

इसके अलावा, अगर आपका TextBoxटैब किसी ऐसे टैब पर है SelectedTab, जिसका ScrollToCarat()कोई प्रभाव नहीं है। इसलिए आपको स्क्रॉल करते समय कम से कम इसे चयनित टैब बनाने की आवश्यकता है। जब आप ऐसा करते हैं तो आप कोड को एक YourTab.SuspendLayout();और YourTab.ResumeLayout(false);जोड़ी में लपेट सकते हैं ।

संपादन का अंत

उम्मीद है की यह मदद करेगा!


1

जब पाठ बदला जाता है तो यह टेक्स्टबॉक्स के अंत तक स्क्रॉल करेगा, लेकिन फिर भी उपयोगकर्ता को स्क्रॉल करने की अनुमति देता है

outbox.SelectionStart = outbox.Text.Length;
outbox.ScrollToEnd();

विजुअल स्टूडियो एंटरप्राइज 2017 पर परीक्षण किया गया


1

किसी अन्य व्यक्ति द्वारा यहां वेबफॉर्म के कार्यान्वयन को देखने की अपेक्षा में लैंडिंग के लिए, आप पेज अनुरोध प्रबंधक के अंतिम घटना हैंडलर ( https://stackoverflow.com/a/1388170/1830512 ) का उपयोग करना चाहते हैं । यहाँ मैंने एक मास्टर पेज से कंटेंट पेज में अपने टेक्स्टबॉक्स के लिए क्या किया, कृपया इस तथ्य को अनदेखा करें कि मैंने नियंत्रण के लिए एक चर का उपयोग नहीं किया:

var prm = Sys.WebForms.PageRequestManager.getInstance();

function EndRequestHandler() {
    if ($get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>') != null) {
        $get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>').scrollTop = 
        $get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>').scrollHeight;
    }
}

prm.add_endRequest(EndRequestHandler);

0

यह केवल मेरे लिए काम किया ...

txtSerialLogging-> पाठ = "";

txtSerialLogging-> AppendText (रों);

मैंने उपरोक्त सभी मामलों की कोशिश की, लेकिन समस्या यह है कि मेरे मामले में पाठ में कमी, वृद्धि हो सकती है और यह लंबे समय तक स्थिर भी रह सकता है। स्थैतिक का अर्थ है, स्थैतिक लंबाई (लाइनें) लेकिन सामग्री अलग है।

इसलिए, मैं अंत में एक पंक्ति कूदने की स्थिति का सामना कर रहा था जब लंबाई (रेखाएं) कुछ समय के लिए समान रहती हैं ...


मुझे पता है, यह बॉब के जवाब के समान है, लेकिन एक विशिष्ट मामले की व्याख्या करता है। और मैं बॉब के जवाब पर टिप्पणी नहीं कर सकता ...
स्टैकओवरफ्लो

0

मैं इसके लिए एक फ़ंक्शन का उपयोग करता हूं:

private void Log (string s) {
    TB1.AppendText(Environment.NewLine + s);
    TB1.ScrollToCaret();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.