From: NadCixelsyd on
I'm using VB5. If I set

FORM1.FONT = "Courier New"
FORM1.FONTSIZE = 10
TEXT = "A"

real_variable = FORM1.FONTSIZE
PRINT real_variable, SCREEN.TwipsPerPixelX, SCREEN.TwipsPerPixelY,
TextHeight(TEXT), TextWidth(TEXT)

it prints 9.75 15 15 240 120

Why did it change my font size from 10 to 9.75. My hunch is that 10
points is 200 twips which is 13.333 pixels, whereas 9.75 points is 195
twips which is a exactly 13 pixels. In other words, regardless of the
fontsize that I specify, VB will change it to the nearest(?) size such
that it is an integral number of pixels.

Like FONTSIZE, I assume that TextHeight and TextWidth are also always
a intergral number of pixels (i.e. a multiple of 15 twips on my
monitor) (in this case, 16 pixels high and 8 pixels wide).

I tried an assortment of font sizes between 9 and 12.
If I set fontsize between 9.00 and 9.34, VB resets it to 8.25 (which
is 11 pixels high)
If I set Fontsize between 9.35 and 11.62, VB resets it to 9.75 (which
is 13 pixels high)
If I set fontsize between 11.63 and 12,, VB resets it to 12.0 (which
is 16 pixels high)
Why doesn't it allow characters that are 12, 14, or 15 pixels high?

With a font size of 9.75 (points?) and 20 twips per point (doesn't
twip stand for "twentieth of a point"?), why is my TextHeight 240
twips? Shouldn't it be 195 twips (9.75 times 20)? If I use 195
twips for spacing, it looks a bit compressed, whereas if I use 240, it
looks kinda sparse.


From: Mike Williams on
"NadCixelsyd" <nadcixelsyd(a)aol.com> wrote in message
news:df644288-5c3a-47c2-b0e7-144b54c6c2fc(a)x12g2000yqx.googlegroups.com...


> [Re setting various font sizes]
> it prints 9.75 15 15 240 120
> Why did it change my font size from 10 to 9.75. My hunch
> is that 10 points is 200 twips which is 13.333 pixels, whereas
> 9.75 points is 195 twips which is a exactly 13 pixels. In other
> words, regardless of the fontsize that I specify, VB will change
> it to the nearest(?) size such that it is an integral number of pixels

Your hunch is correct, but it's not VB that does it. The GDI32 font
functions (which of course VB uses) require that the point size of all fonts
be an integer pixel value on the device to which you are printing them,
regardless of any changes you might make to the DC. (Even if you mess about
with the mapmode and viewport settings, which is not something you would
normally do anyway, the value returned will be a whole unit of some other
size but it will still represent the nearest it can give you to a whole
device pixel value). Most TrueType fonts can take on most pixel sizes for
their point size (although some of them have certain limitations so the only
way to be totally sure of what you can get is to set a specific font to your
requirement and then check the value you actually get). If your machine is
running at the standard 96 dpi (15 twips per pixel) then 10 points comes to
13.333 pixels and so, as you have correctly assumed, for most trueType fonts
the system will give you 13 pixels, which is the equivalent of 9.75 points.
On another computer (or on the same computer) if it is running at the 120
dpi setting (12 twips per pixel) then 10 points comes to 16.67 pixels, and
so on that machine you will get 17 pixels, which is 10.2 points. On a
printer, if it is running at 600 dpi, 10 points comes to 83.33 pixels and so
the system will give you 83 pixels, which is the equivalent of 9.96 points.

> Like FONTSIZE, I assume that TextHeight and TextWidth are
> also always a intergral number of pixels (i.e. a multiple of 15
> twips on my monitor)

Yes. The same "whole pixel" limitation applies to them as well.

> I tried an assortment of font sizes between 9 and 12.
> If I set fontsize between 9.00 and 9.34, VB resets it to 8.25
> (which is 11 pixels high)
> If I set Fontsize between 9.35 and 11.62, VB resets it to 9.75
> (which is 13 pixels high)
> If I set fontsize between 11.63 and 12,, VB resets it to 12.0
> (which is 16 pixels high)
> Why doesn't it allow characters that are 12, 14, or 15 pixels high?

Actually it does allow more than the above pixel values, at least with most
fonts. The values you are getting above are almost certainly those you will
get from a typical screen bitmap font such as the default MS Sans Serif,
which is not a trueType font. Bitmap fonts have much greater point size
limitations than TrueType fonts, and the above values look okay on the
assumption that you are using a bitmap font (perhaps MS Sans serif).
However, if you change to using a trueType font you will see a definite
difference. Try the following code for example, first setting the font to MS
Sans Serif and then running it again with the font set to Arial or Times new
Roman or Courier New or whatever:

Private Sub Command1_Click()
Font.Name = "MS Sans Serif"
Dim n As Single, p As Single, p2 As Long
For n = 8 To 14 Step 0.1
Font.Size = n
p = Font.Size
p2 = ScaleY(Font.Size, vbPoints, vbPixels)
List1.AddItem Format(n, "0,00") & vbTab & p & vbTab & p2
Next n
End Sub

> With a font size of 9.75 (points?) and 20 twips per point
> (doesn't twip stand for "twentieth of a point"?) . .

Yes it does. There are 20 twips in one point and there are 72 points in one
inch which means there are 1440 twips in one inch.

> . . why is my TextHeight 240 twips? Shouldn't it be 195 twips
> (9.75 times 20)?

No. The point size is the nominal height of the font itself and the
TextHeight is the overall height of the character cell in which it lives. It
is of course a bit more complicated than that. If you would like to see more
details then run the following code, which will give you a graphic
representation of a font and its character cell, together with a little
explanation. Paste the following code into a VB Form:

Mike

Option Explicit
Private Declare Function GetTextMetrics Lib "gdi32" _
Alias "GetTextMetricsA" (ByVal hdc As Long, _
lpMetrics As TEXTMETRIC) As Long
Private Type TEXTMETRIC
tmHeight As Long
tmAscent As Long
tmDescent As Long
tmInternalLeading As Long
tmExternalLeading As Long
tmAveCharWidth As Long
tmMaxCharWidth As Long
tmWeight As Long
tmOverhang As Long
tmDigitizedAspectX As Long
tmDigitizedAspectY As Long
tmFirstChar As Byte
tmLastChar As Byte
tmDefaultChar As Byte
tmBreakChar As Byte
tmItalic As Byte
tmUnderlined As Byte
tmStruckOut As Byte
tmPitchAndFamily As Byte
tmCharSet As Byte
End Type
Private Const DEFAULT_QUALITY As Byte = 0
Private Const DRAFT_QUALITY As Byte = 1
Private Const NONANTIALIASED_QUALITY As Byte = 3
Private Const ANTIALIASED_QUALITY As Byte = 4
Private Const CLEARTYPE_COMPAT_QUALITY As Byte = 5
Private Const CLEARTYPE_QUALITY As Byte = 6

Private Sub Form_Load()
' A graphical representation of the various
' Font details (by Mike Williams).
Dim fName As String, fSize As Single
Dim sampleText As String
fName = "Times New Roman"
fSize = 72
sampleText = "MjtplqdgfH0123"
Dim mymetrics As TEXTMETRIC, savey As Single
Dim InternalLeading As Single
Dim Ascent As Single
Dim Descent As Single
Dim ExternalLeading As Single
Dim txtHeight As Single
Me.AutoRedraw = True
Me.Show
Me.BackColor = vbWhite
Me.Width = Me.ScaleX(7.6, vbInches, vbTwips)
Me.Height = Me.ScaleY(5.7, vbInches, vbTwips)
Me.Line (0, 0)-(Me.ScaleWidth, Me.ScaleHeight), _
RGB(200, 100, 255), BF
Me.ScaleMode = vbPoints
Me.Font.Name = fName
Me.Font.Size = fSize ' 72 points = 1 inch
Me.Font.Italic = False
Me.Font.Bold = False
txtHeight = Me.TextHeight("some text")
GetTextMetrics Me.hdc, mymetrics
InternalLeading = Me.ScaleY(mymetrics.tmInternalLeading, _
vbPixels, Me.ScaleMode)
Ascent = Me.ScaleY(mymetrics.tmAscent, _
vbPixels, Me.ScaleMode)
Descent = Me.ScaleY(mymetrics.tmDescent, _
vbPixels, Me.ScaleMode)
ExternalLeading = Me.ScaleY(mymetrics.tmExternalLeading, _
vbPixels, Me.ScaleMode)
Me.CurrentX = 0: Me.CurrentY = 0
Me.FontTransparent = True
Me.Print sampleText
Me.FontTransparent = False
Me.Print sampleText
savey = Me.CurrentY
Me.Line (0, InternalLeading)- _
(Me.ScaleWidth, InternalLeading), vbYellow
Me.Line (0, Ascent)- _
(Me.ScaleWidth, Ascent), vbGreen
Me.Line (0, Ascent + Descent)- _
(Me.ScaleWidth, Ascent + Descent), vbBlue
If mymetrics.tmExternalLeading > 0 Then
Me.Line (0, Ascent + Descent + ExternalLeading)- _
(Me.ScaleWidth, Ascent + Descent + ExternalLeading), vbRed
End If
' Capital letters (A - Z) and numbers (0 - 9)in most fonts
' start a little after the External Leading and extend down
' to the Ascent line, and the centre of those characters is
' usually about 0.48 of the overall "TextHeight" down from
' the top of the character cell. The following code will
' therefore draw a line approximately through the centre
' of these characters on most (but not all) fonts.
Me.Line (0, txtHeight * 0.48)- _
(Me.ScaleWidth, txtHeight * 0.48), vbWhite
Me.CurrentX = 0
Me.CurrentY = savey
Me.Font.Name = "Arial"
Me.Font.Size = 8
Me.Print " The example text is " & fName & " " _
& Format(fSize, "0.0") & " points"
Me.Print " Internal Leading = " & InternalLeading & " points"
Me.Print " Ascent = " & Ascent & " points"
Me.Print " Descent = " & Descent & " points"
Me.Print " External Leading = " & ExternalLeading & " points"
Me.Print " Total Height (Ascent + Descent) = " _
& Ascent + Descent & " points"
Me.Print " VB TextHeight returns " & txtHeight & " points"
Me.Print " The point size is the Ascent plus the Descent";
Me.Print " minus the Internal Leading = ";
Me.Print Ascent + Descent - InternalLeading
Me.FontTransparent = True
Me.Print
Me.Print " Internal Leading is from the top down to the";
Me.Print " yellow line."
Me.Print " Ascent is from the top down to the green line";
Me.Print " (called the Baseline)";
Me.Print " and it includes the Internal Leading."
Me.Print " Descent is from the green line down to the blue";
Me.Print " line."
Me.Print " The overall height is equal to Ascent plus";
Me.Print " Descent and is equal to the VB TextHeight."
Me.Print " The point size is from the yellow line down to";
Me.Print " the blue line and is equal to Ascent plus Descent";
Me.Print " minus Internal Leading."
If mymetrics.tmExternalLeading > 0 Then
Me.Print " The External Leading is from the blue line to";
Me.Print " the red line and is ignored."
Else
Me.Print " This font has zero external leading."
End If
Me.Print " The white line is typically 0.48 of the TextHeight";
Me.Print " down from the top and runs approximately through the ";
Me.Print " centre of capital letters and numerals."
Me.Print " NOTE: If you use a negative value (normal practice)";
Me.Print " for the desired font size when using the ";
Me.Print " CreateFontIndirect API the system will attempt"
Me.Print " to give you a font where the distance from the yellow";
Me.Print " line to the blue line is equal to the requested value. ";
Me.Print " If you use a positive value the"
Me.Print " system will attempt to give you a font where the overall";
Me.Print " height is equal to the requested value. In both cases";
Me.Print " however all of the above elements "
Me.Print " will be present. (Using a positive value is effectively ";
Me.Print " the same as asking for a slightly smaller font.)"
End Sub