Ecriture d'un mot avec path.addstring

Soyez le premier à donner votre avis sur cette source.

Vue 4 280 fois - Téléchargée 228 fois

Description

Cette source permet d'étudier le décalage existant entre l'endroit où on demande l'écriture du mot et l'endroit où le mot est obtenu à l'écran !
Il existe en effet un décalage inattendu entre l'instruction qui dessine le mot et celle qui dessine un rectangle de la même taille au même endroit...

C'est important de maitriser ce décalage si on veut un affichage précis du mot pour des raisons graphiques (et esthétiques)

Ce décalage dépend :
- des caractères du mot (e,p,t,i,E,5,...)
- de la taille (hauteur) de la fonte utilisée (il y a proportionnalité)

L'étude est faite avec deux types de paramètres :
- une translation absolue (X transl et Y transl) qui donne l'écart en pixels
- une translation proportionnelle à la taille de la fonte utilisée (Xcoeff et Ycoeff), plus utilisable dans un programme

Et en résumé :
X transl = Xcoeff * taille_fonte et Y transl = Ycoeff * taille_fonte

Je n'ai pas étudié en comparant les fontes, mais cet outil peut être complété pour le faire...

Source / Exemple :


Imports System.Windows.Forms.Application
Imports System.Drawing.Drawing2D

Public Class Form1
    Dim mot As String 'mot
    Dim hauteur_mot As Integer
    Dim x, y As Double 'position demandée du mot
    Dim xcoeff, ycoeff As Double 'pour placer le mot ds le rectangle !
    Dim xt, yt As Double 'translation pour placer le mot

    'Events
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        mot = "Essai"
        hauteur_mot = 250
        TextBoxHauteur.Text = CStr(hauteur_mot)
        x = 150
        y = 20
        xcoeff = 0.085
        TextBoxXCoeff.Text = CStr(xcoeff)
        ycoeff = 0.2
        TextBoxYCoeff.Text = CStr(ycoeff)
        xt = 0
        TextBoxXTransl.Text = CStr(xt)
        yt = 0
        TextBoxYTransl.Text = CStr(yt)
    End Sub
    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

    End Sub
    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dessin(e.Graphics)
    End Sub

    Private Sub ButtonMot_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonMot.Click
        Dim s As String

        s = InputBox("Chaine à dessiner :", , mot)
        mot = IIf(s <> "", s, mot)

        Me.Refresh()
        DoEvents()

    End Sub

    Private Sub ButtonHauteurPlus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonHauteurPlus.Click
        hauteur_mot += 1
        TextBoxHauteur.Text = CStr(hauteur_mot)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub ButtonHauteurMoins_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonHauteurMoins.Click
        hauteur_mot -= 1
        TextBoxHauteur.Text = CStr(hauteur_mot)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub TextBoxHauteur_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBoxHauteur.TextChanged
        hauteur_mot = Val(TextBoxHauteur.Text)
        Me.Refresh()
        DoEvents()
    End Sub

    Private Sub ButtonXCoeffPlus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonXCoeffPlus.Click
        xcoeff = CType(TextBoxXCoeff.Text, Single)
        xcoeff *= 1.01
        TextBoxXCoeff.Text = CStr(xcoeff)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub ButtonXCoeffMoins_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonXCoeffMoins.Click
        xcoeff = CType(TextBoxXCoeff.Text, Single)
        xcoeff *= 0.99
        TextBoxXCoeff.Text = CStr(xcoeff)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub TextBoxXCoeff_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBoxXCoeff.TextChanged
        xcoeff = CType(TextBoxXCoeff.Text, Single)
        Me.Refresh()
        DoEvents()
    End Sub

    Private Sub ButtonYCoeffPlus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonYCoeffPlus.Click
        ycoeff = CType(TextBoxYCoeff.Text, Single)
        ycoeff *= 1.01
        TextBoxYCoeff.Text = CStr(ycoeff)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub ButtonYCoeffMoins_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonYCoeffMoins.Click
        ycoeff = CType(TextBoxYCoeff.Text, Single)
        ycoeff *= 0.99
        TextBoxYCoeff.Text = CStr(ycoeff)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub TextBoxYCoeff_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBoxYCoeff.TextChanged
        ycoeff = CType(TextBoxYCoeff.Text, Single)
        Me.Refresh()
        DoEvents()
    End Sub

    Private Sub ButtonXTranslPlus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonXTranslPlus.Click
        xt = CType(TextBoxXTransl.Text, Single)
        xt += 1
        TextBoxXTransl.Text = CStr(xt)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub ButtonXTranslMoins_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonXTranslMoins.Click
        xt = CType(TextBoxXTransl.Text, Single)
        xt -= 1
        TextBoxXTransl.Text = CStr(xt)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub TextBoxXTransl_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBoxXTransl.TextChanged
        xt = CType(TextBoxXTransl.Text, Single)
        Me.Refresh()
        DoEvents()
    End Sub

    Private Sub ButtonYTranslPlus_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonYTranslPlus.Click
        yt = CType(TextBoxYTransl.Text, Single)
        yt += 1
        TextBoxYTransl.Text = CStr(yt)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub ButtonYTranslMoins_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonYTranslMoins.Click
        yt = CType(TextBoxYTransl.Text, Single)
        yt -= 1
        TextBoxYTransl.Text = CStr(yt)
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub TextBoxYTransl_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBoxYTransl.TextChanged
        yt = CType(TextBoxYTransl.Text, Single)
        Me.Refresh()
        DoEvents()
    End Sub

    Private Sub CheckBoxCoeff_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBoxCoeff.CheckedChanged
        Me.Refresh()
        DoEvents()
    End Sub
    Private Sub CheckBoxTranslation_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBoxTranslation.CheckedChanged
        Me.Refresh()
        DoEvents()
    End Sub

    'Routines
    Public Sub DrawString(ByVal g As Graphics, ByVal s As String, ByVal hauteur As Integer, _
                         ByVal x1 As Double, ByVal y1 As Double)

        Dim Origine As PointF = New PointF(x1, y1) ' position demandée : (x1,y1)
        Dim SF As StringFormat = New StringFormat(0)
        Dim path As New System.Drawing.Drawing2D.GraphicsPath ' Create a GraphicsPath.

        ' Set the SmoothingMode to high quality for best readability.
        g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality

        ' Add the string to the path; declare the font, font style, size :
        path.AddString(s, Me.Font.FontFamily, FontStyle.Bold, hauteur, Origine, SF)

        g.FillPath(Brushes.Black, path) 'tracé lettres pleines

        path.Dispose()
        SF.Dispose()

    End Sub
    Public Function GetStringWidth(ByVal s As String, ByVal hauteur As Integer) As RectangleF
        'détermine la longueur d'un texte écrit avec Path.AddString()
        Dim BoundRect As RectangleF
        Dim SF As StringFormat = New StringFormat(0)
        Dim path As New GraphicsPath ' Create a GraphicsPath.
        Dim Origine As PointF = New PointF(50, 50) 'peu importe, il n'est pas dessiné

        ' Add the string to the path; declare the font, font style, size :
        path.AddString(s, Me.Font.FontFamily, FontStyle.Bold, hauteur, Origine, SF)
        BoundRect = path.GetBounds() 'dimensions du path avant la matrice de rotation

        path.Dispose()
        SF.Dispose()

        Return BoundRect
    End Function 'détermine la longueur d'un texte écrit avec Path.AddString()
    Private Sub Dessin(ByVal g As Graphics)
        Dim BoundRect As RectangleF 'limites du texte écrit ds chaque part
        Dim larg, haut As Single

        DrawString(g, mot, hauteur_mot, x, y)

        BoundRect = GetStringWidth(mot, hauteur_mot)
        larg = BoundRect.Width
        ButtonLargeurMot.Text = "Largeur mot " & CStr(larg)
        haut = BoundRect.Height
        ButtonHauteurMot.Text = "Hauteur mot " & CStr(haut)
        If CheckBoxCoeff.Checked Then
            g.DrawRectangle(Pens.Green, _
                            CType(x + xcoeff * hauteur_mot, Single), CType(y + ycoeff * hauteur_mot, Single), _
                            larg, haut)
        End If
        If CheckBoxTranslation.Checked Then
            g.DrawRectangle(Pens.Red, CType(x + xt, Single), CType(y + yt, Single), larg, haut)
        End If

    End Sub

End Class

Conclusion :


Si la documentation existe sur cette fonction (et ce décalage !) merci d'indiquer le lien...

Codes Sources

A voir également

Ajouter un commentaire Commentaires
cs_bigboss9
Messages postés
162
Date d'inscription
jeudi 22 janvier 2004
Statut
Membre
Dernière intervention
20 juillet 2013

12 mai 2010 à 23:44
@oxsygen : La fonction MeasureString du framework possède de nombreux bugs dont le plus gênant d'entre eux est de ne pas mesurer correctement les polices qui n'ont pas le même espacement entre les caractères, notamment les polices OpenType. La fonction écrite par l'auteur permet de contourner ce bug.
oxsygen
Messages postés
1
Date d'inscription
mercredi 15 octobre 2008
Statut
Membre
Dernière intervention
12 mai 2010

12 mai 2010 à 12:41
C'est peu de dire que tu réécris la roue là.

En c# tu as :
using System.Windows.Forms; // for TextRenderer
Size size=TextRenderer.MeasureText(g, str, f, new Size(), TextFormatFlags.NoPadding);

(Doit avoir l'équivalent VB.NET j'imagine)

En Win32 pour les vb non .net
GetTextExtentPoint32
cs_bigboss9
Messages postés
162
Date d'inscription
jeudi 22 janvier 2004
Statut
Membre
Dernière intervention
20 juillet 2013

9 mai 2010 à 09:58
Pour les variables non détruites, toutes celles déclarées en DIM dans tes procédures/fonctions et qui ne sont pas détruites.

un varExemple = nothing suffit lorsque l'objet ne dispose pas de l'interface IDisposable. Sinon, varExemple.Dispose()
cs_bigboss9
Messages postés
162
Date d'inscription
jeudi 22 janvier 2004
Statut
Membre
Dernière intervention
20 juillet 2013

9 mai 2010 à 09:55
kbalist
Messages postés
36
Date d'inscription
jeudi 28 janvier 2010
Statut
Membre
Dernière intervention
6 février 2011

8 mai 2010 à 09:22
Merci de ces remarques globalement positives...

"A chaque Refresh() on augmente la consommation du programme" :
Les variables locales sont bien détruites après le Refresh(), et j'ai même utilisé path.dispose(), ce qui devrait libérer la mémoire utilisée en sortie de la routine de dessin, non ?
Je ne vois donc pas l'intérêt de déclarer Path en Global, si ce n'est pour ne pas avoir à le créer et détruire à chaque dessin de l'écran...

Peux-tu me dire quelles sont les variables ou déclarations qui causeraient un dépassement de capacité en C ?

"première lettre du 1er mot en minuscule, 1ère lettre du 2ème mot en Majuscule" :
Je n'ai jamais vu cette règle... tu as un lien ?

"La variable "mot" n'est définie qu'une seule fois et ne change pas" :
Si ! Elle représente la chaine de caractères écrite à l'écran et elle est modifiable avec un controle

Merci de me donner ces quelques précisions pour mon édification personnelle et celle de ceux qui liront ce sujet...
Afficher les 9 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.