.Multiline 속성이 true로 설정된 텍스트 상자가 있습니다. 정기적으로 새로운 줄의 텍스트를 추가하고 있습니다. 새 줄이 추가 될 때마다 텍스트 상자가 가장 맨 아래 항목 (가장 최신 항목)으로 자동 스크롤되도록하고 싶습니다. 어떻게하면 되나요?
.Multiline 속성이 true로 설정된 텍스트 상자가 있습니다. 정기적으로 새로운 줄의 텍스트를 추가하고 있습니다. 새 줄이 추가 될 때마다 텍스트 상자가 가장 맨 아래 항목 (가장 최신 항목)으로 자동 스크롤되도록하고 싶습니다. 어떻게하면 되나요?
답변:
정기적으로 새로운 줄의 텍스트를 추가하고 있습니다. 새 줄이 추가 될 때마다 텍스트 상자가 가장 맨 아래 항목 (가장 최신 항목)으로 자동 스크롤되도록하고 싶습니다.
를 사용 TextBox.AppendText(string text)
하면 새로 추가 된 텍스트의 끝으로 자동 스크롤됩니다. 루프에서 호출하면 깜박이는 스크롤 막대를 피할 수 있습니다.
또한 .Text
속성에 연결하는 것보다 훨씬 빠릅니다 . 그것은 당신이 그것을 얼마나 자주 부르는지에 달려 있습니다. 나는 단단한 루프로 테스트하고있었습니다.
텍스트 상자가 표시되기 전에 호출되거나 텍스트 상자가 표시되지 않는 경우 (예 : TabPanel의 다른 탭에서) 스크롤되지 않습니다. 자동 스크롤이 아닌 TextBox.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;
그러나 수동으로 할 이유가 없습니다.
(직접 디 컴파일하면 더 효율적인 내부 메소드를 사용하고 사소한 특수한 경우가 있음을 알 수 있습니다.)
tb.Text += ....
WndProc와
다음 코드 스 니펫을 사용할 수 있습니다.
myTextBox.SelectionStart = myTextBox.Text.Length;
myTextBox.ScrollToCaret();
자동으로 끝까지 스크롤됩니다.
.NET 4.0 에서 인터페이스가 변경된 것 같습니다 . 위의 모든 것을 달성 하는 다음과 같은 방법 이 있습니다. Tommy Engebretsen이 제안했듯이 TextChanged 이벤트 핸들러에 넣으면 자동으로 만들어집니다.
textBox1.ScrollToEnd();
TextBoxBase
클래스에 System.Windows.Controls.Primitives
있습니다 ( PresentationFramework
조립, WPF). 이 메서드는 존재하지 않으며 네임 스페이스 ( 어셈블리, WinForms) 에서 TextBox
클래스를 상속 하는 WinForms에는 작동하지 않습니다 . TextBoxBase
System.Windows.Forms
System.Windows.Forms
ScrollToEnd()
극단적으로 실적이 저조한 될 수 있습니다. 내 앱에서는 프로파일 링 시간의 50 % 이상을 차지했습니다.
textBox1.Focus()
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
나를 위해 작동하지 않았습니다 (이유가 무엇이든 Windows 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
이 스레드에서 해결되지 않은 간단한 차이점을 발견했습니다.
ScrollToCarat()
양식 Load()
이벤트 의 일부로 모든 통화를 수행하면 작동하지 않습니다. 방금 ScrollToCarat()
양식의 Activated()
이벤트에 전화를 추가 했는데 정상적으로 작동합니다.
편집하다
양식의 Activated
이벤트가 처음 실행될 때 (이후 활성화 시가 아님) 에만이 스크롤을 수행 하거나 양식이 활성화 될 때 마다 스크롤하는 것이 중요합니다 .
따라서 Activated()
프로그램이로드 될 때 텍스트를 스크롤하기 위해 이벤트를 잡는 경우 이벤트 핸들러 자체의 이벤트를 구독 취소하면됩니다.
Activated -= new System.EventHandler(this.Form1_Activated);
양식이 활성화 될 때마다 수행해야 할 다른 작업이있는 경우 이벤트가 bool
처음 Activated()
발생할 때 a 를 true로 설정하여 후속 활성화를 스크롤하지는 않지만 필요한 다른 작업을 계속 수행 할 수 있습니다. 하다.
귀하의 경우에도 TextBox
탭에이되지 않는 SelectedTab
, ScrollToCarat()
아무런 영향을주지 않습니다. 따라서 스크롤하는 동안 적어도 선택된 탭으로 만들어야합니다. 이 작업을 수행 할 때 양식이 깜박이면 코드를 a YourTab.SuspendLayout();
및 랩으로 묶을 수 있습니다 YourTab.ResumeLayout(false);
.
편집 종료
도움이 되었기를 바랍니다!
webforms 구현을 볼 것으로 예상되는 다른 사람은 Page Request Manager의 endRequest 이벤트 핸들러 ( https://stackoverflow.com/a/1388170/1830512 ) 를 사용하려고합니다 . 마스터 페이지의 콘텐츠 페이지에서 TextBox에 대해 수행 한 작업은 컨트롤에 변수를 사용하지 않았다는 사실을 무시하십시오.
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);
이것은 단지 나를 위해 일했다 ...
txtSerialLogging-> 텍스트 = "";
txtSerialLogging-> AppendText (s);
위의 모든 경우를 시도했지만 문제는 내 경우 텍스트가 감소하고 증가하며 오랫동안 정적 상태를 유지할 수 있다는 것입니다. 정적은 정적 길이 (라인)를 의미하지만 내용이 다릅니다.
그래서 나는 길이 (선)가 몇 시간 동안 동일하게 유지되는 끝에 한 줄 점프 상황에 직면했습니다 ...