Problem beim korrekten positionieren eines Chatlog's und eines Textcursors hinter dem eingegebenen Text

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ClonkAndre.

    Problem beim korrekten positionieren eines Chatlog's und eines Textcursors hinter dem eingegebenen Text

    Hallo, ich habe gleich 3 Fragen. Aber alle bezüglich einer selbst gezeichneten Textbox.

    Ich erstelle sehr gerne Mods für GTA und diesesmal wollte ich einen eigenen Chat bauen.
    Da man in GTA nicht einfach TextBoxen oder Labels hinzufügen kann, muss ich diese selber zeichnen.

    Frage 1: Wie kann ich den Textcursor richtig hinter dem eingegebenen Text platzieren? - ✔ Nicht perfekt aber funktionsfähig


    Wie man anhand der Bilder sehen kann, ist der Textcursor nicht richtig hinter dem Text platziert (oder sogar machmal vor dem Text).

    Dies ist mein momentaner Code zum zeichnes des Cursors
    Spoiler anzeigen

    C#-Quellcode

    1. e.Graphics.DrawText("_", new RectangleF((Game.Resolution.Width - 660f) + (chatInput.Length * 14f), Game.Resolution.Height - 52.5f, 15f, 39f), TextAlignment.Left, Color.White, chatFont); // Caret
    2. // chatInput = Der eingegebene Text vom User
    3. // chatFont = Die Schriftart von dem Text
    4. // chatFont Family = Microsoft Sans Serif
    5. // chatFont Height = 24f
    6. // chatFont FontScaling = Pixel



    Frage 2: Wie kann ich Nachrichten im Chatlog nach einer entsprechenden Anzahl von Nachrichten nach oben verschieben? - ✔ Funktionsfähig
    Diese Frage ist jetzt nicht gerade aussagekräftig also hier nochmal anders erklärt:

    Momentan sieht mein Chatlog so aus:


    Ich habe jetzt 5 Nachrichten hineingeschreiben.
    Ab der 6ten Nachricht sollen sich die bereits vorhandenen Nachrichten eins nach oben schieben, so dass die neue Nachricht ganz unten ist und die anderen Nachrichten sich eines nach oben schieben, aber so das trotzdem nur 5 Nachrichten sichbar sind.

    Spoiler anzeigen

    Mit 5 Nachrichten:

    Quellcode

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5


    Mit 6 Nachrichten:

    Quellcode

    1. 2
    2. 3
    3. 4
    4. 5
    5. 6



    Mein momentaner Code
    Spoiler anzeigen

    C#-Quellcode

    1. if (chatMessages.Count > 5)
    2. {
    3. // Ab 6 Nachrichten...
    4. }
    5. else
    6. {
    7. for (int i = 0; i <= chatMessages.Count - 1; i++)
    8. {
    9. e.Graphics.DrawText(chatMessages[i].ToString(), new RectangleF(Game.Resolution.Width - 645, (Game.Resolution.Height / 2) - 120 + i * 30, 600f, 27f), TextAlignment.Right, Color.FromArgb(255, 255, 255, 255), chatFont);
    10. }
    11. }



    Frage 3 (Optional): Wie funktioniert es wenn der Text vom Rand abgeschnitten wird, dass wenn man weiterschreibt der Text trotzdem lesbar ist? - ❌ Noch nicht abgeschlossen


    Code zum anzeigen des textes
    Spoiler anzeigen

    C#-Quellcode

    1. e.Graphics.DrawText(chatInput, new RectangleF((Game.Resolution.Width - 735f) + chatModeTextSize.Width, Game.Resolution.Height - 52.5f, 623f, chatInputTextSize.Height), TextAlignment.Left, Color.White, chatFont); // Input
    2. // + chatModeTextSize.Width = Dynamischer Abstand zum "[ALL]"


    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ClonkAndre“ ()

    Hallo @ClonkAndre

    Generell arbeite mit MeasureString (Graphics), da hast du die genauen Masse des Textes.

    Sofern der Cursor gezeichnet ist, sollte es möglich sein den an den richtigen Ort zu zeichnen, da die Abmasse des Textes nun bekannt sind.

    Auch das Verschieben des gezeichneten Textes lässt sich so problemlos ausrechnen und somit hat sich auch die letzte Frage selber beantwortet.

    docs.microsoft.com/de-de/dotne…ics?view=netframework-4.5


    docs.microsoft.com/de-de/dotne…tem_Drawing_StringFormat_


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „exc-jdbi“ ()

    Zu dem 2. Problem und Deinem Code: Mit der For-Schleife einfach nicht bei 0 beginnen.
    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
    Dieses Problem ist gelöst, danke!

    @exc-jdbi
    Da ich die Graphics Klasse von GTA verwende, habe ich leider dort kein MeasureString.
    Aber ich habe mich erkundingt und herausgefunden das es auch ein MeasureText Methode gibt die sich in System.Windows.Forms.TextRenderer befindet. Und diese scheint zu funktionieren.

    Nun habe ich aber leider so einen großen Abstand zwischen Text und Cursor und ich weiß auf den ersten Blick nicht wo dieser herkommt.


    Code:

    C#-Quellcode

    1. Size chatInputTextSize = TextRenderer.MeasureText(chatInput, chatFont.WindowsFont);
    2. e.Graphics.DrawText(caretChar, new RectangleF((Game.Resolution.Width - 660f) + chatInputTextSize.Width, Game.Resolution.Height - 52.5f, caretCharSize.Width, caretCharSize.Height), TextAlignment.Left, Color.White, chatFont); // Caret


    Eventuell übersehe ich auch mal wieder etwas total offensichtliches.

    Dem 3. Problem habe ich mich noch nicht gewidmet.
    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ClonkAndre“ ()

    Dann miss doch einfach mal alles quasi per Hand aus. Du hast ja einen Screenshot. Da kannst Du jetzt doch alle Komponenten Deiner Berechnung überprüfen. Wenn für chatInputTextSize.Width z.B. 126 angegeben wird, kannst Du doch in Paint oder so ausmessen, ob das der Wahrheit entspricht.
    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
    Ich habe jetzt mal ein bisschen debugging betrieben und habe mir die Breite von chatInputTextSize ausgeben lassen.

    test hat eine Breite von 51
    Ein kleines w hat eine Breite von 31
    Ein großes W hat eine Breite von 35

    Schriftart die ich benutze: Microsoft Sans Serif mit der größe von 24 und der FontScaling Eigenschaft auf Pixel.

    Nun muss ich aber nochmal fragen was Du genau meinst mit dem ausmessen mit Paint?

    Ich habe das nun so versucht, indem ich die Breite von test genommen habe, die war ja 51. Dann habe ich in gimp eine neue Ebene erstellt mit der Breite 51.
    Eine Ebene mit Text erstellt und in diesem test hineingeschrieben, die Font auf meine Font im Projekt gesetzt.

    Das Ergebnis:

    Wie man sieht habe ich kleinen Abstand.

    Ich weiß nicht genau ob es so von dir gemeint war.
    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!
    Ein Beispiel: Du hast Deinen Screenshot in Post#4. Du weißt, wo genau das Bild auf dem Bildschirm erscheint. Wenn Du jetzt z.B. die Position von test in Paint nachmisst und das mit dem vergleichst, was Du als X-Koordinate für test festgelegt hast, kannst Du rausfinden, wo sich eventuelle Differenzen ergeben. Vielleicht ist auch eine Art fixer Skalierungsfaktor miteinzubeziehen. Das ergäbe sich aber erst aus den Messungen verschiedener Größen, z.B. test-X-Wert, test-Breite und verschiedenen Ausprobierpositionen für den Cursor. Wär vielleicht eh eine Variante, dass Du den Cursor auf z.B. einen X-Wert von 100, 120, 140 stellst und dann mit Paint ausmisst, wieviel es dann tatsächlich ist.

    Im Anhang ein Beispiel. Die Längenmessungen (Pixelanzahl) in Paint ergaben
    • A = 65 px (Anfang von test)
    • B = 30 px (Breite von test)
    • C = 123 px (Anfang des Cursors)
    • D = 13 px (Breite des Cursors)
    bzgl. Skalierungsfaktor: Wenn Du nun eben mehrere Punkte festlegst, diese ausmisst und es keine konstante Differenz zwischen Soll- und Ist-Werten gibt, aber bei allen rauskommt: Istwert : Sollwert = X, dann ist X eben Dein Skalierungsfaktor, den Du in Deinem Positionierungscode mit einbeziehen musst.
    Bilder
    • Abmessungen.png

      43,18 kB, 710×140, 64 mal angesehen
    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.
    Achso okay, ich denke/hoffe mal das ist es nun verstanden habe.
    Ich messe die Werte mit Gimp aus, da ich dort Hilfslinien einfügen kann und direkt an der Position schieben kann wo ich messen möchte.

    Dazu muss ich aber noch sagen, dass der Screenshot den ich in Post#4 gezeigt habe, nur ein Teil von dem eigentlichen Screenshot ist.
    Dies ist der ganze Screenshot


    Ich habe mal verschiedene X-Werte für den Cursor gemessen. (Die die Du mir vorgeschlagen hast)
    Und die Messung aller Werte ergaben ein perfektes Ergebnis. Bedeutet: Ich habe 100 eingestellt ich habe auch 100 in Gimp messen können.

    So sah es dann während des testens aus


    Was ich allerdings feststellen konnte, ist das die Cursor Width und ChatInput Width unterschiedlich Breit sind.
    Werte die mir angezeigt werden:
    ChatInput Width (test Text): 51
    Cursor Width: 26

    Werte die ich mit Gimp messen konnte:
    ChatInput Width (test Text): 30
    Cursor Width: 13

    Genau die Werte die sich in deinem Test ergaben.

    Die kleine Textbox die ich unten rechts zeichne soll sich auch immer der Bildschirmauflösung anpassen bzw. tut es auch.
    Meine Auflösung beträgt: 1920x1080
    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ClonkAndre“ ()

    Ich habe es einigermaßen geschafft den Cursor hinter dem Text zu bekommen. Es ist nicht perfekt, aber besser als zuvor..
    Spoiler anzeigen

    C#-Quellcode

    1. e.Graphics.DrawText(caretChar, new RectangleF((Game.Resolution.Width - 735f) + chatModeTextSize.Width + (chatInputTextSize.Width - (chatInput.Length * 2)) - (chatInput.Length == 0 ? 0 : 10f), Game.Resolution.Height - 52.5f, caretCharSize.Width, caretCharSize.Height), TextAlignment.Left, Color.White, chatFont); // Caret



    Nun wollte ich mich mal an Frage 3 rantasten, weiß aber wirklich nicht wie ich da vorgehen soll..
    Über irgendwelche Ideen/Beispiele etc. würde ich mich freuen.
    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!