나는 어떻게 표시 스크롤 막대에서 시스템입니다.Windows.Forms.TextBox 경우에만 텍스트가 적합하지 않은?

StackOverflow https://stackoverflow.com/questions/73110

  •  09-06-2019
  •  | 
  •  

문제

에 대한 시스템입니다.Windows.Forms.TextBox 으로 여러=True,나는 같은 보여주기 위해 스크롤면 텍스트가 적합하지 않.

이것은 읽기 전용 텍스트 상자에만 사용하시겠습니까?그것은 텍스트할 수 있도록 사용자 텍스트를 복사합니다.거기에 아무것도장에서 지원하는 자동차의 표시 스크롤?지 않은 경우 해야 나를 사용하여 다른 컨트롤?또는 필요하 후크 TextChanged 및 수동으로 확인에 대한 오버플로우(그렇다면,방법을 말하는 경우 텍스트에 맞는?)


어떤 행운을 가지고 있지 않으로 다양한 조합의 WordWrap 와 스크롤 막대를 설정합니다.고 싶 없는 스크롤 처음에는 각 동적으로 나타나는 경우에만의 텍스트에 적합하지 않은 주어진 방향입니다.


@nobugz,감사,작동하는 경우 WordWrap 사용할 수 없습니다.아보지 않은 사용하지 않 wordwrap 지만,그것은 두 가지 악.


@André Neves,좋은 지점,그리고 나는 그 길을 가는 경우 그것은 사용자 편집할 수 있습니다.는 것에 동의 일관성 기본 원칙에 대한 UI 직관적이다.

도움이 되었습니까?

해결책

추가로 새로운 클래스 프로젝트 코드를 붙여 아래와 같습니다.컴파일.새제에서 상단의 도구에의 형태입니다.그것은 확실하지 않는 완벽한 하지만 일해야 한다.

using System;
using System.Drawing;
using System.Windows.Forms;

public class MyTextBox : TextBox {
  private bool mScrollbars;
  public MyTextBox() {
    this.Multiline = true;
    this.ReadOnly = true;
  }
  private void checkForScrollbars() {
    bool scroll = false;
    int cnt = this.Lines.Length;
    if (cnt > 1) {
      int pos0 = this.GetPositionFromCharIndex(this.GetFirstCharIndexFromLine(0)).Y;
      if (pos0 >= 32768) pos0 -= 65536;
      int pos1 = this.GetPositionFromCharIndex(this.GetFirstCharIndexFromLine(1)).Y;
      if (pos1 >= 32768) pos1 -= 65536;
      int h = pos1 - pos0;
      scroll = cnt * h > (this.ClientSize.Height - 6);  // 6 = padding
    }
    if (scroll != mScrollbars) {
      mScrollbars = scroll;
      this.ScrollBars = scroll ? ScrollBars.Vertical : ScrollBars.None;
    }
  }

  protected override void OnTextChanged(EventArgs e) {
    checkForScrollbars();
    base.OnTextChanged(e);
  }

  protected override void OnClientSizeChanged(EventArgs e) {
    checkForScrollbars();
    base.OnClientSizeChanged(e);
  }
}

다른 팁

이 질문했을 경우 해결하고 동일한 문제입니다.

가장 쉬운 방법은 그것을 변경하는 시스템입니다.Windows.Forms.됩니다.스크롤 막대성 이 경우에 남아 있을 수 있습의 기본값 RichTextBoxScrollBars.모두 나타내는"표시한 수평 및 수직 스크롤 막대를 할 때 필요합니다." 그것은 좋은 것으면 이 기능에서 제공했 TextBox.

나는 또한 몇 가지의 실험,그리고 발견하는 수직 바이 항상 표시를 당신이 그것을 사용하는 경우,그리고 가로 막대를 보여주는 만큼 그것의 사용과 WordWrap == false.

나는 당신을 생각하지 않을 얻을 정확히 무엇을 원하는 여기에.그러나 믿는 사용자가는 것 같은 더 나은 윈도우 기본 행동을 하려는 힘입니다.면 응용 프로그램을 사용하여,내가 가능하게 방해되는 경우 나란 부동산 갑자기 수축 때문에 그것을 요구를 수용 예기치 않은 스크롤 막대기 때문에 나는 그것을 너무 많이다.

아마도 그것은 좋은 아이디어만을 사용하면 응용 프로그램에 따라 창고 있습니다.

이 극히 미묘한 버그에서 nobugz 의 솔루션에 있는 결과 힙 손상이지만,사용하는 경우에만 AppendText()를 업데이트 TextBox.

설정의 스크롤바 속에서 OnTextChanged 의 원인이됩니다 Win32 창(처리)을 파괴되고 다시 만들어집니다.하지만 OnTextChanged 라의 창자에서 Win32 편집하 제어(EditML_InsertText),는 즉시 그 후 기대한의 내부 상태는 Win32 편집을 변경되지 않습니다.불행하게도,이후 창을 재현하며,그 내부 상태에 사용된 OS,결과에 액세스 위반이 발생합니다.

똥 묻은 개가 겨 묻은 개를 나무래서 이야기:를 사용하지 않 AppendText()경우에 당신이 이용하기 위하여 려고 하고 있 nobugz 의 솔루션입니다.

나는 몇 가지 성공됩니다.

  public partial class MyTextBox : TextBox
  {
    private bool mShowScrollBar = false;

    public MyTextBox()
    {
      InitializeComponent();

      checkForScrollbars();
    }

    private void checkForScrollbars()
    {
      bool showScrollBar = false;
      int padding = (this.BorderStyle == BorderStyle.Fixed3D) ? 14 : 10;

      using (Graphics g = this.CreateGraphics())
      {
        // Calcualte the size of the text area.
        SizeF textArea = g.MeasureString(this.Text,
                                         this.Font,
                                         this.Bounds.Width - padding);

        if (this.Text.EndsWith(Environment.NewLine))
        {
          // Include the height of a trailing new line in the height calculation        
          textArea.Height += g.MeasureString("A", this.Font).Height;
        }

        // Show the vertical ScrollBar if the text area
        // is taller than the control.
        showScrollBar = (Math.Ceiling(textArea.Height) >= (this.Bounds.Height - padding));

        if (showScrollBar != mShowScrollBar)
        {
          mShowScrollBar = showScrollBar;
          this.ScrollBars = showScrollBar ? ScrollBars.Vertical : ScrollBars.None;
        }
      }
    }

    protected override void OnTextChanged(EventArgs e)
    {
      checkForScrollbars();
      base.OnTextChanged(e);
    }

    protected override void OnResize(EventArgs e)
    {
      checkForScrollbars();
      base.OnResize(e);
    }
  }

무엇을 단을 설명하는 것은 거의 정확한 UI 시나리오 내가 직면하고있다.텍스트 상자를 읽는만,나는 그것을 필요로하지 않에 대응하 TextChanged.고 나아보세요 자동 스크롤 다시 계산이 지연 될 그래서 그것의 발사하지 않을 수십의 초당 시간 동안 창은 크기가 조정됩니다.

대부분의 UIs,텍스트 상자를 가진 수직 및 수평 스크롤 막대,음 악,이렇게 나에만 관심이 있는 수직 스크롤 막대가 여기에.

또한 것을 발견했 MeasureString 생산 높이었던 것보다 더 무엇이 필요합니다.를 사용하여 텍스트 상자의 PreferredHeight 없는 테두리 선으로 높이는 더 나은 결과를 제공합니다.

다음과 같은 작동하는 것 같다 꽤 잘,또는 국경 없는,그리고 작동 WordWrap 니다.

단순히 부르 AutoScrollVertically()필요할 때,그리고 필요에 따라 지정 recalculateOnResize.

public class TextBoxAutoScroll : TextBox
{
    public void AutoScrollVertically(bool recalculateOnResize = false)
    {
        SuspendLayout();

        if (recalculateOnResize)
        {
            Resize -= OnResize;
            Resize += OnResize;
        }

        float linesHeight = 0;
        var   borderStyle = BorderStyle;

        BorderStyle       = BorderStyle.None;

        int textHeight    = PreferredHeight;

        try
        {
            using (var graphics = CreateGraphics())
            {
                foreach (var text in Lines)
                {
                    var textArea = graphics.MeasureString(text, Font);

                    if (textArea.Width < Width)
                        linesHeight += textHeight;
                    else
                    {
                        var numLines = (float)Math.Ceiling(textArea.Width / Width);

                        linesHeight += textHeight * numLines;
                    }
                }
            }

            if (linesHeight > Height)
                ScrollBars = ScrollBars.Vertical;
            else
                ScrollBars = ScrollBars.None;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex);
        }
        finally
        {
            BorderStyle = borderStyle;

            ResumeLayout();
        }
    }

    private void OnResize(object sender, EventArgs e)
    {
        m_timerResize.Stop();

        m_timerResize.Tick    -= OnDelayedResize;
        m_timerResize.Tick    += OnDelayedResize;
        m_timerResize.Interval = 475;

        m_timerResize.Start();
    }

    Timer m_timerResize = new Timer();

    private void OnDelayedResize(object sender, EventArgs e)
    {
        m_timerResize.Stop();

        Resize -= OnResize;

        AutoScrollVertically();

        Resize += OnResize;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top