Zawijanie wyrazów dla etykiety w formularzach Windows Forms

184

Jak możemy uzyskać funkcję zawijania słów dla etykiety w formularzach Windows Forms ?

Umieściłem etykietę w panelu i dynamicznie dodałem tekst do etykiety. Ale przekracza długość panelu. Jak mogę to rozwiązać?

Nagu
źródło

Odpowiedzi:

166

Szybka odpowiedź: wyłącz AutoSize .

Dużym problemem jest to, że etykieta nie zmieni automatycznie wysokości (tylko szerokość). Aby uzyskać to prawo, należy podklasować etykietę i uwzględnić logikę zmiany rozmiaru w pionie.

Zasadniczo w OnPaint musisz zrobić:

  1. Zmierz wysokość tekstu (Graphics.MeasureString).
  2. Jeśli wysokość etykiety nie jest równa wysokości tekstu, ustaw wysokość i zwróć.
  3. Narysuj tekst.

Będziesz także musiał ustawić flagę stylu ResizeRedraw w konstruktorze.

Jonathan C. Dickinson
źródło
12
Wybierz etykietę, do której dynamicznie dodajesz tekst. Spójrz na właściwości etykiety i wyłącz AutoSize. Teraz będziesz mógł przeciągnąć / ustawić obszar etykiety i automatycznie zawinie się, aby pozostać w tych parametrach. Nie ma potrzeby dodatkowego kodowania.
madeFromCode
Właśnie tego szukałem, ponieważ dotyczy to formatowania mojego formularza tekstem wyjaśniającym w formie akapitu.
Philip Brack
1
@madeFromCode Musisz ustawić wysokość programowo, jeśli chcesz, aby etykieta rozwijała się w pionie, inaczej tekst zostanie przycięty.
Edwin,
348

W rzeczywistości zaakceptowana odpowiedź jest niepotrzebnie skomplikowana.

Jeśli ustawisz etykietę na AutoSize, będzie ona automatycznie powiększać się z każdym umieszczonym w niej tekstem. (Obejmuje to wzrost pionowy).

Jeśli chcesz, aby zawijał słowa o określonej szerokości, możesz ustawić właściwość MaximumSize.

myLabel.MaximumSize = new Size(100, 0);
myLabel.AutoSize = true;

Testowane i działa.

John Gietzen
źródło
10
Jeśli masz etykietę przyciąganą do kontenera, możesz wyłączyć AutoSize, pozostawić właściwość maksymalnego rozmiaru bez zmian i zawija słowa dokładnie tak, jak chcemy. KISS w pracy!
TheBlastOne
Dzięki temu rozwiązaniu nie można uzyskać szerokości płynu.
Robin
1
@Sam: Tak, po prostu ustaw odpowiednie właściwości „anchor”. Próbowałeś nawet?
John Gietzen,
1
Sam: powinieneś być w stanie ustawić Dockwłaściwość zarówno etykiety, jak i panelu na Top, zamiast mojego rozwiązania.
John Gietzen
2
Przyłączyłem się do OnResizerodzica i zadzwoniłemmyLabel.MaximumSize = new Size(Bounds.Width, 0);
Chris Morgan
23

W moim przypadku (etykieta na panelu) ustawiam label.AutoSize = falsei label.Dock = Fill. Tekst etykiety jest automatycznie zawijany.

alex555
źródło
To powoduje, że etykieta wypełnia cały formularz i powoduje, że zasłania wszystkie inne elementy sterujące w formularzu ... To znaczy, że nie działa. Czy istnieją inne wymagania, które nie wypełnią całego formularza?
Peter Mortensen
5
etykieta znajduje się na panelu , a nie bezpośrednio w formularzu. Dlatego tekst nie wykracza poza granice panelu
alex555
OK, ale czy nie zasłoniłoby to wszystkich innych elementów sterujących w panelu?
Peter Mortensen
1
Co uniemożliwia Ci utworzenie dodatkowego panelu zawierającego tylko etykietę?
alex555
To wygląda na dodatkowy układ, który powinien być niepotrzebny. Z pewnością etykieta powinna mieć własne pudełko, a nie musi być umieszczana w innym pudełku.
Edwin,
17

Zła wiadomość: nie ma właściwości automatycznego zawijania.

Dobra wiadomość: na końcu tunelu jest światło!

Możesz to zrobić programowo, aby dynamicznie dopasować rozmiar, ale oto najprostsze rozwiązanie:

  • Wybierz właściwości etykiety
  • AutoSize = True
  • MaximumSize = ( szerokość , wysokość ) gdzie Width = maksymalny rozmiar, jaki ma być etykieta, a Height = liczba pikseli, które mają być zawijane

    Przykładowe właściwości

Sebastian Castaldi
źródło
4
Jeszcze jedna uwaga, jeśli pozostawisz maksymalną wysokość na 0, nadal będzie się rozszerzać w pionie.
palehorse
Moja etykieta nie ma właściwości AutoSize i MaximumSize, jak mogę je dodać?
mrbengi
11

Z MSDN , automatycznie zawijaj tekst w etykiecie :

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

public class GrowLabel : Label {
    private bool mGrowing;
    public GrowLabel() {
        this.AutoSize = false;
    }
    private void resizeLabel() {
        if (mGrowing) 
            return;
        try {
            mGrowing = true;
            Size sz = new Size(this.Width, Int32.MaxValue);
            sz = TextRenderer.MeasureText(this.Text, this.Font, sz, TextFormatFlags.WordBreak);
            this.Height = sz.Height;
        }
        finally {
            mGrowing = false;
        }
    }
    protected override void OnTextChanged(EventArgs e) {
        base.OnTextChanged(e);
        resizeLabel();
    }
    protected override void OnFontChanged(EventArgs e) {
        base.OnFontChanged(e);
        resizeLabel();
    }
    protected override void OnSizeChanged(EventArgs e) {
        base.OnSizeChanged(e);
        resizeLabel();
    }
}
hipo
źródło
Aby rozdzielić znaki zamiast słów (przydatne, gdy masz długie ciągi bez spacji, takie jak ścieżki plików), zamiast tego użyj (TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl). Zobacz ostatni post w tym samym wątku MSDN.
Ohad Schneider
1
Nie zapomnij również uwzględnić górnej i dolnej części etykiety w obliczeniach ( Height = sz.Height + Padding.Vertical;)
Igor Brejc,
6

Musiałem znaleźć szybkie rozwiązanie, więc po prostu użyłem TextBox o tych właściwościach:

var myLabel = new TextBox
                    {
                        Text = "xxx xxx xxx",
                        WordWrap = true,
                        AutoSize = false,
                        Enabled = false,
                        Size = new Size(60, 30),
                        BorderStyle = BorderStyle.None,
                        Multiline =  true,
                        BackColor =  container.BackColor
                    };
użytkownik3356581
źródło
To dobre rozwiązanie, ale wolę używać ReadOnly niż ustawienie Enabled na false.
PahJoker
1
To pomysłowe rozwiązanie, które działa również dobrze w Compact Framework (gdzie Label nie ma właściwości AutoSize i MaximumSize).
Tim Coulter
3

Miej lepszy na podstawie odpowiedzi @hypo

public class GrowLabel : Label {
    private bool mGrowing;
    public GrowLabel() {
        this.AutoSize = false;
    }
    private void resizeLabel() {
        if (mGrowing)
            return;
        try {
            mGrowing = true;
            int width = this.Parent == null ? this.Width : this.Parent.Width;

            Size sz = new Size(this.Width, Int32.MaxValue);
            sz = TextRenderer.MeasureText(this.Text, this.Font, sz, TextFormatFlags.WordBreak);
            this.Height = sz.Height + Padding.Bottom + Padding.Top;
        } finally {
            mGrowing = false;
        }
    }
    protected override void OnTextChanged(EventArgs e) {
        base.OnTextChanged(e);
        resizeLabel();
    }
    protected override void OnFontChanged(EventArgs e) {
        base.OnFontChanged(e);
        resizeLabel();
    }
    protected override void OnSizeChanged(EventArgs e) {
        base.OnSizeChanged(e);
        resizeLabel();
    }
}

int width = this.Parent == null ? this.Width : this.Parent.Width; pozwala to na użycie etykiety automatycznego wzrostu po zadokowaniu do elementu nadrzędnego, np. panelu.

this.Height = sz.Height + Padding.Bottom + Padding.Top; tutaj dbamy o wypełnienie u góry iu dołu.

marzec1993
źródło
1
  1. Umieść etykietę w panelu
  2. Chwyć ClientSizeChanged eventpanel, sprawiając, że etykieta wypełni przestrzeń:

    private void Panel2_ClientSizeChanged(object sender, EventArgs e)
    {
        label1.MaximumSize = new Size((sender as Control).ClientSize.Width - label1.Left, 10000);
    }
  3. Zestaw Auto-Sizeetykietę natrue

  4. Ustaw Docketykietę naFill
noelicus
źródło
Czy kroki 3 i 4 zostały wykonane przez projektanta? Z jakichś powodów są to kroki 3 i 4?
Stealth Rabbi,
Są one wykonywane w projektancie (ale mogą być wykonane w kodzie, jeśli jest to potrzebne) i nie ma powodu do zamówienia.
noelicus
1

Nie jestem pewien, czy będzie pasować do wszystkich przypadków użycia, ale często używam prostej sztuczki, aby uzyskać zachowanie owijania: włóż Labeldo AutoSize=falseśrodka 1x1, TableLayoutPanelktóry zadba o Labelrozmiar.

Pragmateek
źródło
1

Ustaw właściwość AutoEllipsis na „PRAWDA”, a właściwość AutoSize na „FALSE”.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Ravi Kumar GN
źródło
0

Jeśli panel ogranicza szerokość etykiety, możesz ustawić właściwość Anchor etykiety na Left, Right i ustawić AutoSize na true. Jest to koncepcyjnie podobne do nasłuchiwania SizeChangedzdarzenia panelu i zaktualizowania MaximumSize etykiety do wartości new Size(((Control)sender).Size.Width, 0)sugerowanej w poprzedniej odpowiedzi . Każda strona wymieniona we właściwości Anchor jest, no cóż, zakotwiczona do odpowiedniej wewnętrznej strony zawierającej Kontroli. Zatem umieszczenie dwóch przeciwnych stron w zakotwiczeniu skutecznie określa wymiar formantu. Zakotwiczenie w lewo i prawo ustawia właściwość Szerokość elementu sterującego, a zakotwiczenie w górę i w dół ustawiłoby właściwość Wysokość.

To rozwiązanie, jako C #:

label.Anchor = AnchorStyles.Left | AnchorStyles.Right;
label.AutoSize = true;
Binki
źródło
Nie działa Etykieta zwiększa szerokość mojego panelu po prostu, że nie musi się zawijać. Niestety okno nie jest tak szerokie.
ygoe
0

Jeśli naprawdę chcesz ustawić szerokość etykiety niezależnie od treści, uważam, że najłatwiejszym sposobem jest:

  • Ustaw autosize true
  • Ustaw maksymalną szerokość, jak chcesz
  • Identycznie ustaw minimalną szerokość

Teraz etykieta ma stałą szerokość, ale automatycznie dostosowuje swoją wysokość.

Następnie w przypadku tekstu dynamicznego zmniejsz rozmiar czcionki. W razie potrzeby użyj tego fragmentu kodu w obszarze podrzędnym, w którym ustawiony jest tekst etykiety:

If Me.Size.Height - (Label12.Location.Y + Label12.Height) < 20 Then
    Dim naam As String = Label12.Font.Name
    Dim size As Single = Label12.Font.SizeInPoints - 1
    Label12.Font = New Font(naam, size)
End If
Kjell Verbeke
źródło
0

Pomogło mi to w moim formularzu o nazwie InpitWindow: In Designer for Label:

AutoSize = true;
Achors = Top, Left, Right.

private void InputWindow_Shown(object sender, EventArgs e) {
    lbCaption.MaximumSize = new Size(this.ClientSize.Width - btOK.Width - btOK.Margin.Left - btOK.Margin.Right -
        lbCaption.Margin.Right - lbCaption.Margin.Left, 
        Screen.GetWorkingArea(this).Height / 2);
    this.Height = this.Height + (lbCaption.Height - btOK.Height - btCancel.Height);
    //Uncomment this line to prevent form height chage to values lower than initial height
    //this.MinimumSize = new Size(this.MinimumSize.Width, this.Height);
}
//Use this handler if you want your label change it size according to form clientsize.
private void InputWindow_ClientSizeChanged(object sender, EventArgs e) {
    lbCaption.MaximumSize = new Size(this.ClientSize.Width - btOK.Width - btOK.Margin.Left * 2 - btOK.Margin.Right * 2 -
        lbCaption.Margin.Right * 2 - lbCaption.Margin.Left * 2,
        Screen.GetWorkingArea(this).Height / 2);
}

Cały kod mojej formy

Mikrofon
źródło
0

Jeśli wymiary przycisku muszą pozostać niezmienione:

myButton.Text = "word\r\nwrapped"
Rjain
źródło
0

Prostą odpowiedzią na ten problem jest zmiana właściwości DOCK etykiety. Domyślnie jest to „BRAK”.

Sunil Neeradi
źródło
0

Jeśli wcześniej wpisujesz tekst do etykiety, możesz to zrobić.

  1. W projektancie kliknij prawym przyciskiem myszy etykietę i wybierz Właściwości.
  2. W oknie Właściwości wyszukaj kartę tekstową.
  3. Kliknij kartę i kliknij przycisk strzałki obok niej.
  4. Na górze pojawi się okno.
  5. Możesz nacisnąć Enter w wyskakującym oknie, aby dodać linie i wpisać jak w notatniku! (NACISNĄĆ WPROWADŹ, GDZIE CHCESZ OWIJĄĆ TEKST ETYKIETY)
DJ
źródło
-12

Użyj style="overflow:Scroll"w etykiecie jak w poniższym HTML. Spowoduje to dodanie paska przewijania do etykiety w panelu.

<asp:Label
    ID="txtAOI"
    runat="server"
    style="overflow:Scroll"
    CssClass="areatext"
    BackColor="White"
    BorderColor="Gray"
    BorderWidth="1"
    Width = "900" ></asp:Label>
Sweety Jain
źródło
3
Głosowanie w tej sprawie jest w porządku, ale przynajmniej powiedz, dlaczego to zrobiłeś. Powodem tego było odrzucenie, ponieważ <asp: Label> nie jest używane w WinForms. Ta odpowiedź dotyczy niewłaściwej platformy.
theJerm
4
ponieważ jest to asp.net, a nie winform
Trikaldarshi,