Position eines Buchstaben in einem Label bestimmen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Position eines Buchstaben in einem Label bestimmen

    Hallo Zusammen,
    kann mir jemand sagen, wie man die Position eines Buchstaben in einem Label bestimmen kann?

    Situation:
    Ich benutze das ".MouseDown"-Ereignis eines Labels und lese die Position des Mousezeigers über das "MouseEventArgs e.X" aus.
    Die zurückgegebene X-Koordinate innerhalb des Labels müsste jetzt auf die Buchstaben-Position im Textstring umgerechnet werden.

    Ich habe soetwas früher schon einmal mittels API-Funktionen gemacht und weiß, dass die Umrechnung fontabhängig ist;
    aber:
    1. habe ich vergessen wie ich es gemacht habe und
    2. würde ich es gern umgehen, API-Funktionen zu benutzen.

    Für eine Lösung bzw. Tipps dazu wäre ich dankbar.
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    Das kommt drauf an. Wenn das Label auf AutoSize eingestellt ist, sollte man es mit MeasureString hinbekommen. Es wäre zwar möglich, dann den zu messenden Text Buchstaben für Buchstaben zu erweitern (Labeltext = "Beispiel" => Measurestring durchlaufen lassen mit B, dann mit Be, Bei, Beis, Beisp, Beispi, Beispie, Beispiel) und dann immer schauen, ob das gemessene MausX zu einer berechneten Textllänge der genannten Textbausteine passt, aber es geht bestimmt auch effizienter.
    Besonders einfach würde es allerdings mit Fixed Fonts werden. Da geht die Rechnerei sehr leicht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed, danke für Deine schnelle Antwort!

    Mit (dem Link zu) "Fixed Font" kann ich gar nichts anfangen.

    Mit den Vorschlägen unter dem Link zu "MeasureString" habe ich einiges versucht, aber es scheint so, dass der Weg hierbei umgekehrt ist; es werden bei "Stringmessungen" immer in Pixelangaben geliefert.
    Ich brauche jedoch einen Wert innerhalb des Strings, der mir die stringbezogene Position des (im Label) angeklickten Buchstaben ermittelt. Dies soll in Etwa so sein, als wenn ich die Position in einer RichTextBox durch Abfrage der Cursorposition erhalte, was ja eben in einem Label nicht möglich ist, da es nicht das aktive Steuerelement sein kann!
    Der Hintergrund meines Anliegens ist, dass in einem Label, einzelne angeclickte Worte ermittelt und erläutert werden können.

    Da ich aber noch keine andere Idee habe, werde ich erstmal in Richtung Deines Vorschlags von "MeasureString" weiter suchen.

    Sollte noch Jemand andere Ideen haben, dann her damit!
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    Fixed Fonts haben eine feste Breite pro Zeichen. Also kann man sagen: »Kennt man die eine, kennt man sie alle.«. Will heißen: Wenn man die Breite erstmal kennt, kann man sich schnell ausrechnen, über welchem Zeichen die Maus sein wird.
    Bzgl. MeasureString: Ist zwar noch etwas ausbaufähig, aber kannst es ja mal damit probieren:

    VB.NET-Quellcode

    1. Private Sub Label1_MouseClick(sender As Object, e As MouseEventArgs) Handles Label1.MouseClick
    2. Dim g As Graphics = Graphics.FromHwnd(Me.Handle), PartialText As New System.Text.StringBuilder()
    3. For i = 0 To Label1.Text.Length - 1
    4. PartialText.Append(Label1.Text(i))
    5. If e.X <= g.MeasureString(PartialText.ToString, Label1.Font).Width Then MessageBox.Show(Label1.Text(i)) : Exit For
    6. Next
    7. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Es gibt auch Graphics.MeasureCharacterRange() - damit kann man die Bereiche einzelner Zeichen oder Worte vermessen.
    Allerdings gelten die Messwerte nur, wenn auch mit Graphics.DrawText gezeichnet wurde.
    Labels zeichnen aber ihren Text mit der TextRenderer-Klasse.
    Also um MeasureCharacterRange() zu verwenden müsste man ein ownerDrawn Label benutzen.

    Die Idee mit der Richtextbox findich garnet so schlecht - kann man ja readonly machen.
    An Labeln stört mich eh oft, dass man deren Text nicht auskopieren kann.
    @VaporiZed,
    dein geposteter Code klappt sehr gut, allerdings scheint die Cusorposition auf Leerzeichen nicht erkannt zu werden, aber das krieg ich schon hin.

    @ErfinderDesRades,
    so einfach wie Deine Idee ist, so gut ist sie! Auch ich habe es schon oft als störend empunden, dass Labeltexte nicht auskopiert werden können und mein jetziges Problem wäre damit auch einfach zu lösen.
    Meine Frage dazu ist aber,
    knallt es nicht unheimlich auf die Ressourcen, wenn man "alle" Label, die eben nicht nur der Anzeige dienen sollen, gegen RichTextBoxen oder TextBoxen austauschen würde? Deshalb habe ich diese Möglichkeit bisher immer gescheut.

    Problem gelöst - Danke Beiden für Eure Hilfe!
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.
    Es ist schwer einzuschätzen, wieviel Resource ein Objekt frisst. Also Control ist schon von vornherein ein fettes Objekt - ob nun Label oder Rtb. Sicher hat Rtb mehr, aber wieviel das ausmacht - wie gesagt: schwer zu sagen.
    Vielleicht ist das ganz wenig: den Richtext, paar Variablen zur CursorPositionierung, paar Backingfields für einige mehr Properties und gut.
    Solltest halt sowieso zusehen, nicht tausende Controls aufs Form zu packen.
    Ich denke auch, diese komischen "Wortweise-Labels", wie du sie brauchst - soo viele werden das doch garnet werden, odr?
    @ErfinderDesRades,
    Solltest halt sowieso zusehen, nicht tausende Controls aufs Form zu packen.

    Nun, das ist ja genau der Grund - wie ich bereits schrieb - dass ich diese Möglichkeit bisher immer gescheut habe und mal irgendwo las, dass ein Label eines der Ctrls ist, welches die wenigsten Ressoursen "frisst" und ich halt gerne meine Programme so "schlank" wie möglich halten möchte.

    @VaporiZed,
    ich habe den von Dir geposteter Code an mein Programm angepasst und es funktioniert alles bestens!

    Nochmals herzlichen Dank Euch Beiden für die schnelle und kompetente Hilfe!
    mfG DHB

    Ich meine:
    :P Es sollten nur ernstzunehmende Beiträge eingestellt werden!
    :( Beiträge, die nur deren Anzahl in die Höhe treiben sollen, stehlen Lesern deren Zeit und schenken nur Frust.
    ;) Wenn ein Autor sein Thema für erledigt hält, sollte er dies kurz als letzten Eintrag vermerken.
    8) Leser wüssten dann, dass hier weitere Beiträge nicht mehr sinnvoll sind.

    DHB schrieb:

    Auch ich habe es schon oft als störend empunden, dass Labeltexte nicht auskopiert werden können
    Dann nimm doch einfach eine ReadOnly TextBox.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    BackColor
    von nem Label?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Doch. Die BackColor-Property einer TextBox ändert sich standardmäßig von Window auf Control, wenn man ReadOnly auf True setzt. Kann man aber wie gewohnt ändern. Bei Enabled = False wird's schon tricky. Korrigiere: auch da geht's. Man muss sich nur für eine Farbe entscheiden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.