OVH Cloud OVH Cloud

Calculer la largeur d'un texte

10 réponses
Avatar
Guy Lafrenière
Bonjour Collègues,

J'utilise un contrôle MSFlexGrid. Je voudrais que, en double cliquant sur
une colonne, la largeur de la colonne s'ajuste automatiquement à la largeur
du plus long texte dans la colonne.

Je pense que je saurais comment faire en utilisant la propriété TextWidth
d'un contrôle PictureBox invisible que je placerais dans ma Form. Cette
solution me paraît toutefois pénalisante côté vitesse d'exécution parce que
j'aurai éventuellement à traiter des grids ayant plusieurs centaines, voire
milliers, de lignes et/ou colonnes.

Il doit bien y avoir une autre façon de faire en utilisant l'API.

Le code ressemblerait peu-être à ceci:

' Dans la section générale
Private m_MaxWidth As Long
Private m_FontName As String
Private m_FontSize As Long
Private m_FontBold As Boolean
Private m_FontItalic As Boolean
Private m_ColGrid As Long

' Le code ici attribue les valeurs à m_fontName, m_FontSize, m_FontBold,
m_FontItalic, m_ColGrid

m_MaxWidth = MaxWidth(flexGrid,m_ColGrid)

Private Function MaxWidth( flexGrid as MSFlexGrid, lngCol As Long )
Dim lngRow as Long
Dim lngMaxWidth As Long, lngNewMaxWidth As Long
For lngRow = 0 To flexGrid.Rows
lngNewMaxWidth = GetTextWidth flexGrid, lngRow, lngCol
If lngNewMaxWidth > lngMaxWidth Then
lngMaxWidth = lngNewMaxWidth
End If
End For
MaxWidth = lngMaxWidth
End Function

Quelqu'un peut-il m'aider pour créer la fonction GetTextWidth?
Le code plus haut n'est qu'une suggestion. Si vous connaissez un code plus
efficace, allez-y!

Merci à l'avance pour toute aide.

Guy Lafrenière

10 réponses

Avatar
Jacques93
Bonjour Guy Lafrenière,

Guy Lafrenière a écrit :
Bonjour Collègues,

J'utilise un contrôle MSFlexGrid. Je voudrais que, en double cliquant sur
une colonne, la largeur de la colonne s'ajuste automatiquement à la largeur
du plus long texte dans la colonne.

Je pense que je saurais comment faire en utilisant la propriété TextWidth
d'un contrôle PictureBox invisible que je placerais dans ma Form. Cette
solution me paraît toutefois pénalisante côté vitesse d'exécution parce que
j'aurai éventuellement à traiter des grids ayant plusieurs centaines, voire
milliers, de lignes et/ou colonnes.

Il doit bien y avoir une autre façon de faire en utilisant l'API.

Le code ressemblerait peu-être à ceci:

' Dans la section générale
Private m_MaxWidth As Long
Private m_FontName As String
Private m_FontSize As Long
Private m_FontBold As Boolean
Private m_FontItalic As Boolean
Private m_ColGrid As Long

' Le code ici attribue les valeurs à m_fontName, m_FontSize, m_FontBold,
m_FontItalic, m_ColGrid

m_MaxWidth = MaxWidth(flexGrid,m_ColGrid)

Private Function MaxWidth( flexGrid as MSFlexGrid, lngCol As Long )
Dim lngRow as Long
Dim lngMaxWidth As Long, lngNewMaxWidth As Long
For lngRow = 0 To flexGrid.Rows
lngNewMaxWidth = GetTextWidth flexGrid, lngRow, lngCol
If lngNewMaxWidth > lngMaxWidth Then
lngMaxWidth = lngNewMaxWidth
End If
End For
MaxWidth = lngMaxWidth
End Function

Quelqu'un peut-il m'aider pour créer la fonction GetTextWidth?
Le code plus haut n'est qu'une suggestion. Si vous connaissez un code plus
efficace, allez-y!




Un fois déterminé le texte le plus long de ta colonne, tu peux utiliser
l'API :

GetTextExtentPoint32

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_8smq.asp?frame=true


Contrainte : l'API utilisant le Device Context (paramètre hDC), et le
contrôle MSFlexGrid n'en disposant pas, il faut utiliser
la propriété hDC de la feuille (ou d'un contrôle
PictureBox), et que la police de caractères et ses
caractéristiques soient les mêmes.

Exemple de code utilisant cet API :

Option Explicit

Private Type Size
Cx As Long
Cy As Long
End Type

Private Declare Function GetTextExtentPoint32 Lib "GDI32" Alias
"GetTextExtentPoint32A" (ByVal hDC As Long, _
ByVal lpsz As String, ByVal cbString As Long, _
lpSize As Size) As Long


Private Function GetTextWidth(s As String) As Integer
Dim lResult As Long
Dim sz As Size

lResult = GetTextExtentPoint32(Me.hDC, s, Len(s), sz)
GetTextWidth = sz.Cx * Screen.TwipsPerPixelX + 120
End Function

--
Cordialement,

Jacques.
Avatar
Hervé
Bonsoir Guy,
Voilà ce que j'utilse, regarde si ça te conviens et adapte dans la proc
"AjusterColonne" (la colonne que tu veux définir) :

Declare Function GetDC _
Lib "USER32" ( _
ByVal hWnd As Long) As Long

Declare Function ReleaseDC _
Lib "USER32" ( _
ByVal hWnd As Long, _
ByVal hDC As Long) As Long

Declare Function CreateFontA _
Lib "Gdi32" ( _
ByVal H As Long, _
ByVal W As Long, _
ByVal E As Long, _
ByVal O As Long, _
ByVal W As Long, _
ByVal I As Long, _
ByVal U As Long, _
ByVal S As Long, _
ByVal C As Long, _
ByVal OP As Long, _
ByVal CP As Long, _
ByVal Q As Long, _
ByVal PAF As Long, _
ByVal F As String) As Long

Declare Function SelectObject _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal hObject As Long) As Long

Declare Function DeleteObject _
Lib "Gdi32" ( _
ByVal hObject As Long) As Long

Declare Function GetTextExtentPoint32A _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal lpsz As String, _
ByVal cbString As Long, _
lpSize As SDimTexte) As Long

Declare Function GetDeviceCaps _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal nIndex As Long) As Long

Type SDimTexte
Largeur As Long
Hauteur As Long
End Type

Function DimTexte(Texte As String, _
Police As String, _
Taille As Double, _
Optional Gras As Boolean, _
Optional Italique As Boolean) As SDimTexte

Dim hFont As Long, hDC As Long
Dim PixpInch As Double

hDC = GetDC(0)
PixpInch = GetDeviceCaps(hDC, 90) / 72
hFont = CreateFontA(-Taille * PixpInch, 0, 0, 0, _
400 - 300 * Gras, -Italique, 0, 0, 1, 0, 0, 0, 0, Police)
If hFont = 0 Then
ReleaseDC 0, hDC
DimTexte.Largeur = 0
DimTexte.Hauteur = 0
Else
SelectObject hDC, hFont
GetTextExtentPoint32A hDC, Texte, Len(Texte), DimTexte
DeleteObject hFont
ReleaseDC 0, hDC
End If

End Function

Private Sub AjusterColonne()
Dim TailleTexte As SDimTexte
Dim Largeur As Single
Dim Texte As String
Dim I As Integer
Dim Ligne As Integer

With Grille
'mémorise le N° de ligne
Ligne = .Row
.Col = 1 'à adapter !!!

'cherche le texte le plus long
For I = 1 To .Rows - 1
.Row = I
If Len(.Text) > Len(Texte) Then
Texte = .Text
End If
Next I

'mesure la longueur du texte en pixel (
With .Font
TailleTexte = DimTexte(Texte, .Name, .Size)' , .Bold, .Italic)
End With

'change la mesure en Twips et rajoute 100 Twips (< à adapter !)
Largeur = TailleTexte.Largeur * Screen.TwipsPerPixelX + 100

'ajuste la colonne au texte
.ColWidth(1) = Largeur

'se repositionne sur la ligne
.Row = Ligne
End With

End Sub

Hervé.


"Guy Lafrenière" a écrit dans le message de news:

Bonjour Collègues,

J'utilise un contrôle MSFlexGrid. Je voudrais que, en double cliquant sur
une colonne, la largeur de la colonne s'ajuste automatiquement à la
largeur
du plus long texte dans la colonne.

Je pense que je saurais comment faire en utilisant la propriété TextWidth
d'un contrôle PictureBox invisible que je placerais dans ma Form. Cette
solution me paraît toutefois pénalisante côté vitesse d'exécution parce
que
j'aurai éventuellement à traiter des grids ayant plusieurs centaines,
voire
milliers, de lignes et/ou colonnes.

Il doit bien y avoir une autre façon de faire en utilisant l'API.

Le code ressemblerait peu-être à ceci:

' Dans la section générale
Private m_MaxWidth As Long
Private m_FontName As String
Private m_FontSize As Long
Private m_FontBold As Boolean
Private m_FontItalic As Boolean
Private m_ColGrid As Long

' Le code ici attribue les valeurs à m_fontName, m_FontSize, m_FontBold,
m_FontItalic, m_ColGrid

m_MaxWidth = MaxWidth(flexGrid,m_ColGrid)

Private Function MaxWidth( flexGrid as MSFlexGrid, lngCol As Long )
Dim lngRow as Long
Dim lngMaxWidth As Long, lngNewMaxWidth As Long
For lngRow = 0 To flexGrid.Rows
lngNewMaxWidth = GetTextWidth flexGrid, lngRow, lngCol
If lngNewMaxWidth > lngMaxWidth Then
lngMaxWidth = lngNewMaxWidth
End If
End For
MaxWidth = lngMaxWidth
End Function

Quelqu'un peut-il m'aider pour créer la fonction GetTextWidth?
Le code plus haut n'est qu'une suggestion. Si vous connaissez un code plus
efficace, allez-y!

Merci à l'avance pour toute aide.

Guy Lafrenière






Avatar
Jean-Marc
"Jacques93" a écrit dans le message de
news:
Bonjour Guy Lafrenière,

Guy Lafrenière a écrit :
> Bonjour Collègues,
>
> J'utilise un contrôle MSFlexGrid. Je voudrais que, en double


cliquant sur
> une colonne, la largeur de la colonne s'ajuste automatiquement à la


largeur
> du plus long texte dans la colonne.
>
> Je pense que je saurais comment faire en utilisant la propriété


TextWidth
> d'un contrôle PictureBox invisible que je placerais dans ma Form.


Cette
> solution me paraît toutefois pénalisante côté vitesse d'exécution


parce que
> j'aurai éventuellement à traiter des grids ayant plusieurs


centaines, voire
> milliers, de lignes et/ou colonnes.
>




Un fois déterminé le texte le plus long de ta colonne, tu peux


utiliser
l'API :



Hello Jacques,

Es tu sur que cela va fonctionner?
J'ai un doute car je me demande si le critère "Texte le plus long"
est suffisant.

En effet, si on utilise une Font à empattement non fixe (autre
que Courier ou équivalent), le texte avec le plus de lettres
n'est pas nécessairement le plus large.

Exemple:

iiiiiiii (8 lettres)
wwwwww (6 lettres)

J'ai fait un exemple ici:
http://myjmnhome.dyndns.org/download/flexgrid.jpg


Qu'en penses tu? Ou peut être ais je mal compris ce que
tu entendais par "le plus long" ?


Amicalement,

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Jacques93
Bonjour Jean-Marc,
Jean-Marc a écrit :
"Jacques93" a écrit dans le message de
news:
Bonjour Guy Lafrenière,

Guy Lafrenière a écrit :
Bonjour Collègues,

J'utilise un contrôle MSFlexGrid. Je voudrais que, en double




cliquant sur
une colonne, la largeur de la colonne s'ajuste automatiquement à la




largeur
du plus long texte dans la colonne.

Je pense que je saurais comment faire en utilisant la propriété




TextWidth
d'un contrôle PictureBox invisible que je placerais dans ma Form.




Cette
solution me paraît toutefois pénalisante côté vitesse d'exécution




parce que
j'aurai éventuellement à traiter des grids ayant plusieurs




centaines, voire
milliers, de lignes et/ou colonnes.







Un fois déterminé le texte le plus long de ta colonne, tu peux


utiliser
l'API :



Hello Jacques,

Es tu sur que cela va fonctionner?
J'ai un doute car je me demande si le critère "Texte le plus long"
est suffisant.

En effet, si on utilise une Font à empattement non fixe (autre
que Courier ou équivalent), le texte avec le plus de lettres
n'est pas nécessairement le plus large.

Exemple:

iiiiiiii (8 lettres)
wwwwww (6 lettres)

J'ai fait un exemple ici:
http://myjmnhome.dyndns.org/download/flexgrid.jpg


Qu'en penses tu? Ou peut être ais je mal compris ce que
tu entendais par "le plus long" ?


Amicalement,




J'en penses que je me suis très mal expliqué. La fonction "fonctionne",
vu qu'elle prend en compte la police, sa taille, ses attributs, etc...
et renvoie la taille en pixel occupée par la chaîne, et c'est donc cette
fonction qui permet de déterminer le texte le plus long en taille, et
non pas en terme de nombre de caractères.

Par contre, en commençant par

"Un fois déterminé le texte le plus long de ta colonne"

effectivement, je fausse tout le raisonnement, vu que c'est cette
fonction qui permet de connaître le texte le plus long en taille.

En appelant cette fonction (après adaptation) dans la boucle qui balaie
la colonne indiquée par Guy, ça doit marcher.

Suis pas sûr d'être plus clair...

En tout cas, merci si tu m'as aidé à l'être :-)
Sinon, merci quand même ;-)


--
Cordialement,

Jacques.
Avatar
Jacques93
Bonsoir Guy, Jean-Mar, Collègues, etc ...

Code sans commentaire, sauf qu'il ne fonctionne que sur la colonne 1 :-D

Option Explicit
Private Type Size
Cx As Long
Cy As Long
End Type

Private Declare Function GetTextExtentPoint32 Lib "GDI32" Alias
"GetTextExtentPoint32A" (ByVal hDC As Long, _
ByVal lpsz As String, ByVal cbString As Long, _
lpSize As Size) As Long

Private Sub Command1_Click()
Me.MSFlexGrid1.ColWidth(1) = MaxWidth(Me.MSFlexGrid1, 1)
End Sub

Private Function MaxWidth(flexGrid As MSFlexGrid, lngCol As Long)
Dim lngRow As Long
Dim lngMaxWidth As Long, lngNewMaxWidth As Long

For lngRow = 0 To flexGrid.Rows - 1
lngNewMaxWidth = GetTextWidth(flexGrid.TextMatrix(lngRow, lngCol))
If lngNewMaxWidth > lngMaxWidth Then
lngMaxWidth = lngNewMaxWidth
End If
Next lngRow
MaxWidth = lngMaxWidth
End Function

Private Function GetTextWidth(s As String) As Integer
Dim lResult As Long
Dim sz As Size

lResult = GetTextExtentPoint32(Me.hDC, s, Len(s), sz)
GetTextWidth = sz.Cx * Screen.TwipsPerPixelX + 120
End Function


--
Cordialement,

Jacques.
Avatar
Jean-Marc
"Jacques93" a écrit dans le message de
news:eGG$
Bonjour Jean-Marc,
Jean-Marc a écrit :
> "Jacques93" a écrit dans le message de
> news:



Hello Jacques et les autres,

J'en penses que je me suis très mal expliqué. La fonction


"fonctionne",
vu qu'elle prend en compte la police, sa taille, ses attributs, etc...
et renvoie la taille en pixel occupée par la chaîne, et c'est donc


cette
fonction qui permet de déterminer le texte le plus long en taille, et
non pas en terme de nombre de caractères.



Oui c'est bien ce qui me semblait.

Par contre, en commençant par

"Un fois déterminé le texte le plus long de ta colonne"

effectivement, je fausse tout le raisonnement, vu que c'est cette
fonction qui permet de connaître le texte le plus long en taille.



Voila, c'est ici que ça me posait un problème :-)


En appelant cette fonction (après adaptation) dans la boucle qui


balaie
la colonne indiquée par Guy, ça doit marcher.

Suis pas sûr d'être plus clair...



Si si, maintenant tout est ok :-)

En tout cas, merci si tu m'as aidé à l'être :-)
Sinon, merci quand même ;-)



plaisir :-)

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Jacques93
Bonsoir à tous,
Des gens ont écrit des mots
[...]

Si si, maintenant tout est ok :-)



Si c'est clair pour mon collègue Belge, j'espère qu'il en est de même
pour mon collègue Québécois ;-)


En tout cas, merci si tu m'as aidé à l'être :-)
Sinon, merci quand même ;-)



plaisir :-)




Idem :-D

--
Cordialement,

Jacques.
Avatar
Jean-Marc
"Jacques93" a écrit dans le message de
news:%
Bonsoir à tous,
Des gens ont écrit des mots
[...]
>
> Si si, maintenant tout est ok :-)

Si c'est clair pour mon collègue Belge, j'espère qu'il en est de même
pour mon collègue Québécois ;-)



Je suis belge de coeur, mais français d'origine, breton pour être
précis,
expatrié outre quiévrain depuis 4 ans :-)

Les mauvaises langues disent que j'ai pris l'accent mais moi je dis
que ça est juste seulement des carabistouilles et que ça tu dois une
fois pas rire avec, hein !

--
Jean-marc
Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
"There are only 10 kind of people
those who understand binary and those who don't."
mailto: remove '_no_spam_' ;
Avatar
Guy Lafrenière
Bonjour Jacques 93,

J'ai essayé le code que tu m'as proposé et ça fonctionne à merveille.

Merci beaucoup!

Guy Lafrenière

----------------------------------------------------------------------------
--------

"Jacques93" a écrit

GetTextExtentPoint32

Contrainte : l'API utilisant le Device Context (paramètre hDC), et le
contrôle MSFlexGrid n'en disposant pas, il faut utiliser
la propriété hDC de la feuille (ou d'un contrôle
PictureBox), et que la police de caractères et ses
caractéristiques soient les mêmes.

Exemple de code utilisant cet API :

Option Explicit

Private Type Size
Cx As Long
Cy As Long
End Type

Private Declare Function GetTextExtentPoint32 Lib "GDI32" Alias
"GetTextExtentPoint32A" (ByVal hDC As Long, _
ByVal lpsz As String, ByVal cbString As Long, _
lpSize As Size) As Long


Private Function GetTextWidth(s As String) As Integer
Dim lResult As Long
Dim sz As Size

lResult = GetTextExtentPoint32(Me.hDC, s, Len(s), sz)
GetTextWidth = sz.Cx * Screen.TwipsPerPixelX + 120
End Function


Avatar
Guy Lafrenière
Bonsoir Hervé,

Je te remercie d'avoir pris la peine de me répondre.

Ton code est plus complexe que celui proposé par Jacques93. Le code de ce
dernier fonctionne à merveille.

J'aimerais savoir si ton code est ainsi parce que tu ne connaissais pas la
méthode proposée par Jacques 93, ou si ta méthode offre des avantages que
n'a pas la méthode de Jacques 93.

Au plaisir de te lire!

Guy Lafrenière

----------------------------------------------------------------------------
----

Hervé a écrit

Voilà ce que j'utilse, regarde si ça te conviens et adapte dans la proc
"AjusterColonne" (la colonne que tu veux définir) :

Declare Function GetDC _
Lib "USER32" ( _
ByVal hWnd As Long) As Long

Declare Function ReleaseDC _
Lib "USER32" ( _
ByVal hWnd As Long, _
ByVal hDC As Long) As Long

Declare Function CreateFontA _
Lib "Gdi32" ( _
ByVal H As Long, _
ByVal W As Long, _
ByVal E As Long, _
ByVal O As Long, _
ByVal W As Long, _
ByVal I As Long, _
ByVal U As Long, _
ByVal S As Long, _
ByVal C As Long, _
ByVal OP As Long, _
ByVal CP As Long, _
ByVal Q As Long, _
ByVal PAF As Long, _
ByVal F As String) As Long

Declare Function SelectObject _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal hObject As Long) As Long

Declare Function DeleteObject _
Lib "Gdi32" ( _
ByVal hObject As Long) As Long

Declare Function GetTextExtentPoint32A _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal lpsz As String, _
ByVal cbString As Long, _
lpSize As SDimTexte) As Long

Declare Function GetDeviceCaps _
Lib "Gdi32" ( _
ByVal hDC As Long, _
ByVal nIndex As Long) As Long

Type SDimTexte
Largeur As Long
Hauteur As Long
End Type

Function DimTexte(Texte As String, _
Police As String, _
Taille As Double, _
Optional Gras As Boolean, _
Optional Italique As Boolean) As SDimTexte

Dim hFont As Long, hDC As Long
Dim PixpInch As Double

hDC = GetDC(0)
PixpInch = GetDeviceCaps(hDC, 90) / 72
hFont = CreateFontA(-Taille * PixpInch, 0, 0, 0, _
400 - 300 * Gras, -Italique, 0, 0, 1, 0, 0, 0, 0, Police)
If hFont = 0 Then
ReleaseDC 0, hDC
DimTexte.Largeur = 0
DimTexte.Hauteur = 0
Else
SelectObject hDC, hFont
GetTextExtentPoint32A hDC, Texte, Len(Texte), DimTexte
DeleteObject hFont
ReleaseDC 0, hDC
End If

End Function

Private Sub AjusterColonne()
Dim TailleTexte As SDimTexte
Dim Largeur As Single
Dim Texte As String
Dim I As Integer
Dim Ligne As Integer

With Grille
'mémorise le N° de ligne
Ligne = .Row
.Col = 1 'à adapter !!!

'cherche le texte le plus long
For I = 1 To .Rows - 1
.Row = I
If Len(.Text) > Len(Texte) Then
Texte = .Text
End If
Next I

'mesure la longueur du texte en pixel (
With .Font
TailleTexte = DimTexte(Texte, .Name, .Size)' , .Bold, .Italic)
End With

'change la mesure en Twips et rajoute 100 Twips (< à adapter !)
Largeur = TailleTexte.Largeur * Screen.TwipsPerPixelX + 100

'ajuste la colonne au texte
.ColWidth(1) = Largeur

'se repositionne sur la ligne
.Row = Ligne
End With

End Sub

Hervé.