【问题标题】:How to scroll down in a textbox by code in C#如何通过C#中的代码在文本框中向下滚动
【发布时间】:2009-07-01 14:38:20
【问题描述】:

我正在使用 winforms,并且我偶尔会更新一个文本框(显示消息)。 但是,当文本到达框的末尾时,它会产生滚动条,我不知道如何向下滚动到底部。我唯一看到的是 ScrollToCaret,但 Caret 在文本的开头。滚动的命令是什么?

【问题讨论】:

  • 这将很有用:检测 textarea 滚动何时到达底部以启用按钮。我想在滚动文本区域中显示许可协议并检测用户何时滚动到文本区域底部,然后启用提交按钮。有没有办法做到这一点?

标签: c# winforms textbox scroll


【解决方案1】:

您可以通过使用名为 ScrollToCaret 的函数来做到这一点。您需要先将插入符号的位置设置到文本框的末尾,然后才能滚动到它。操作方法如下:

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

【讨论】:

  • ScrollToCaret() 仅在相关文本框具有焦点时才有效。请参阅下面的解决方案来处理没有焦点的文本框:stackoverflow.com/questions/1069497/2585177#2585177
  • 当然,如果确实如此,那么事先调用 TextBox.Focus 就可以了。无需使用 pinvoke。
  • 是的,这是可能的。但在某些情况下,您可能希望在滚动 TextBox 时将焦点保持在表单中的其他位置。如果是这种情况,您必须在完成此操作后实现额外的逻辑以“重新聚焦”正确的项目。但现在我只是挑剔;)
  • 投反对票的人能解释一下他们的投票吗?如果您有一些建设性的反馈,请与小组分享。
【解决方案2】:

这是一个老问题,但没有一个建议的答案对我有用(ScrollToCaret() 仅在 TextBox 具有焦点时才有效)。因此,如果在某个时候应该再搜索这个,我想我会分享我发现的解决方案:

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

解决方案的功劳应转至 bytes.com 上的此帖子:http://bytes.com/topic/c-sharp/answers/248500-scroll-bottom-textbox#post1005377

【讨论】:

  • 它有效!!!!我发现大量帖子说要使用 ScrollToCaret,如果控件没有焦点,这当然不起作用。这行得通!
  • 它可以工作,但问题是,滚动条上下跳动,不是用户友好的样子!!! (同样的问题,甚至更糟糕的 ScrollToCarret 解决方案)
【解决方案3】:

如果您使用文本框的 AppendText() 方法,文本将添加到任何现有文本的底部,并且控件将滚动显示它。

【讨论】:

    【解决方案4】:

    您需要在文本末尾设置插入符号:

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

    【讨论】:

      【解决方案5】:

      C# 通过 Windows API (user32.dll) 使用向上/向下滚动

      首先,我们要定义一个常量值:

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

      然后,我们要声明 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);
      

      最后,用这些方法做实事:

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

      完成!简单易行!经测试! original post

      【讨论】:

        【解决方案6】:

        您可以使用 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);
            }
        }
        

        (未经测试)

        【讨论】:

        • 这不会真正滚动文本框,它只是改变滚动条上小按钮的位置。
        【解决方案7】:

        在搜索并没有找到一个合法的解决方案后,我偶然发现了一个有效的 API 解决方案(至少对于我的平台 - 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);
                }
            }
        }
        

        使用多行文本框 (tbx_main) 使用如下:

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

        【讨论】:

          猜你喜欢
          • 2014-10-26
          • 1970-01-01
          • 1970-01-01
          • 2011-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多