SmallSystem font size

Anyone know how the get the real size of the SmallSystem font size?
There should be a Windows API call to get this…

Hello Massimo,

The system text size is usually set to a default value of 0, which allows the OS to select the appropriate default size. To get the size of the default text then use the Graphics.TextSize command. Here is some example code.

[code] //Make a new label and format it
Dim MyLabel as new Label
MyLabel.TextFont = “SmallSystem”
MyLabel.Text = “SmallSystem Text”

//Check the size
Dim MyTextSize as Integer
MyTextSize = MyLabel.TextSize
If MyTextSize = 0 then //Is size system default?
MyTextSize = Graphics.TextSize //Get Size
Else
MyTextSize = MyLabel.TextSize //Get other size
End If

msgbox "Small System Text Size is: " + CStr(MyTextSize)[/code]

Is this what you are looking for?

Edit: Changed Label1 to MyLabel

For the edit control (ie/ text area) see EM_GETCHARFORMAT
https://msdn.microsoft.com/en-us/library/windows/desktop/ff485923(v=vs.85).aspx

[quote=180855:@Eugene Dakin]Hello Massimo,

The system text size is usually set to a default value of 0, which allows the OS to select the appropriate default size. To get the size of the default text then use the Graphics.TextSize command. Here is some example code.
[/quote]

Thanks Eugene, this seems working, however I get a possibly wrong result. Since this method is cross platform, I tried it on Mac and it reports the SmallSystem font size is 12, while truly it’s 11 (as reported from Cocoa API).

What I was looking for is a Windows API working more or less like the NSFont.smallSystemFontSize Cocoa API.

Hi Massimo,

I’ve been trying to develop a Declare solution for you but I seem to be missing something. Does anyone have any helpful suggestions?

Here is some code for Norman’s suggested EM_GETCHARFORMAT:

[code] //EM_GETCHARFORMAT
Declare Function SendMessage Lib “user32” Alias “SendMessageA” ( hwnd As integer, wMsg As Integer, ByVal wParam As integer, ByVal lParam As Ptr) As Integer
Const EM_GETCHARFORMAT = 1082 //&h43A
Const SCF_SELECTION = &h1
Dim MyString as CString = Label1.Text
Dim MyAnswer as Integer
Dim m as New MemoryBlock(200)

Label1.SelectAll
MyAnswer = SendMessage(Label1.handle, EM_GETCHARFORMAT, SCF_SELECTION, m)

MsgBox "MyAnswer = " + CStr(MyAnswer) + EndOfLine +_
"Label1.Handle = " + CStr(Label1.Handle) + EndOfLine +_
"m.Size = " + CStr(m.Size) + EndOfLine +_
"m.Int32Value(0) cbSize = " + CStr(m.Int32Value(0)) + EndOfLine +_
"m.Int32Value(4) dwMask = " + CStr(m.Int32Value(1)) + EndOfLine +_
"m.Int32Value(8) dwEffects = " + CStr(m.Int32Value(8)) + EndOfLine +_
"m.Int32Value(12) yHeight = " + CStr(m.Int32Value(12)) + EndOfLine +_
"m.Int32Value(16) yOffset = " + CStr(m.Int32Value(16)) + EndOfLine +_
"m.Int32Value(20) crTextColor = " + CStr(m.Int32Value(20)) + EndOfLine +_
"m.Byte(24) bCharSet = " + CStr(m.Byte(24)) + EndOfLine +_
"m.Byte(25) bPitchAndFamily = " + CStr(m.Byte(25)) + EndOfLine +_
"m.CString(26) szFaceName = " + CStr(m.CString(26)) + EndOfLine [/code]

The returned value is zero, which should mean that the Declare call is successful and the returned memory block values are:
MyAnswer = 0
Label1.handle = 265702 //this will change
m.size = 200
m.Int32Value(0) cbSize = 0
m.Int32Value(4) dwMask = 0
m.Int32Value(8) dwEffects = 0
m.Int32Value(12) yHeight = 0
m.Int32Value(16) yOffset = 0
m.Int32Value(20) crTextColor = 0
m.Byte(24) bCharSet = 0
m.Byte(25) bPitchAndFamily = 0
m.Cstring(26) szFaceName =

Any thoughts?

Edit: Changed Window1.handle to Label1.handle - typo for making a compact version for the forums

[quote=180883:@Massimo Valle]Thanks Eugene, this seems working, however I get a possibly wrong result. Since this method is cross platform, I tried it on Mac and it reports the SmallSystem font size is 12, while truly it’s 11 (as reported from Cocoa API).

What I was looking for is a Windows API working more or less like the NSFont.smallSystemFontSize Cocoa API.[/quote]

On Windows if you place two labels containing “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA” or whatever text long enough to get a good reference, both using SmallSystem, one with TextSize zero, the other 12, it is exactly the same height and length. If you set the second one at 11, it is too small.

This method does it automatically.

[code] app.UseGDIPlus = True
dim pic as new picture(1,1)
dim pic2 as new picture(1,1)
pic.graphics.TextFont = “SmallSystem”
pic2.graphics.TextFont = “SmallSystem”

for i as integer = 5 to 20
pic2.graphics.textsize = i
if pic.graphics.StringWidth(“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”) = pic2.graphics.StringWidth(“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”) then
msgbox "Text Size is "+str(i)
exit
end if
next
[/code]

Edit : Damn. On a Mac, two labels with one zero, the other 11 shows the same length. Yet, stringwidth is equal for TextSize12. Fortunately, there is a declare.

Interesting also to know that on Windows SmallSystem will be one point bigger, which can be an issue for tight layout.

Do you need to set cbSize to the size of your MessageBlock?

Thanks for your help Jim.

I set the memory block size to 200 (should be enough) and added GetLastError and had the value 5 (Access is denied). I have full administrator rights on the computer. Here is the modified code. I also tried to use the SCF_DEFAULT flag instead of SCF_SELECTION and I get the same GetLastError of 5. Any other helpful thoughts that I am missing?

[code] //EM_GETCHARFORMAT
Declare Function SendMessage Lib “user32” Alias “SendMessageA” (hwnd As integer, wMsg As Integer, ByVal wParam As integer, ByVal lParam As Ptr) As Integer
Const EM_GETCHARFORMAT = 1082 //&h43A
Const SCF_SELECTION = &h1
Const SCF_DEFAULT = &h0
Dim MyString as CString = Label1.Text
Dim MyAnswer as Integer
Dim m as New MemoryBlock(200)

Label1.SelectAll
m.Size = 200
MyAnswer = SendMessage(Label1.handle, EM_GETCHARFORMAT, SCF_SELECTION, m)

Label2.Text = "MyAnswer = " + CStr(MyAnswer) + EndOfLine +_
"Label1.Handle = " + CStr(Label1.Handle) + EndOfLine +_
"m.Size = " + CStr(m.Size) + EndOfLine +_
"m.Int32Value(0) cbSize = " + CStr(m.Int32Value(0)) + EndOfLine +_
"m.Int32Value(4) dwMask = " + CStr(m.Int32Value(1)) + EndOfLine +_
"m.Int32Value(8) dwEffects = " + CStr(m.Int32Value(8)) + EndOfLine +_
"m.Int32Value(12) yHeight = " + CStr(m.Int32Value(12)) + EndOfLine +_
"m.Int32Value(16) yOffset = " + CStr(m.Int32Value(16)) + EndOfLine +_
"m.Int32Value(20) crTextColor = " + CStr(m.Int32Value(20)) + EndOfLine +_
"m.Byte(24) bCharSet = " + CStr(m.Byte(24)) + EndOfLine +_
"m.Byte(25) bPitchAndFamily = " + CStr(m.Byte(25)) + EndOfLine +_
"m.CString(26) szFaceName = " + CStr(m.CString(26)) + EndOfLine

MyGetLastError[/code]

Hi Eugene,

Unfortunately I’m not on my development PC to check this but a couple of things:

  • I thought EM_GETCHARFORMAT was only recognized by a RichEdit control (like TextArea) but your example indicates you are sending the message to a label control?

  • Also, according to MSDN docs for the EM_GETCHARFORMAT message:

[quote]cbSize
Type: UINT
Size in bytes of the specified structure. This member must be set before passing the structure to the rich edit control.[/quote]

So, this value must be set to the size of your MemoryBlock before you call SendMessage (at least that’s my understanding).

Anyway, hope that helps.

Thanks for looking into this a little bit more Jim.

I didn’t know about the difference between a Label and TextArea, and I am always learning more about the subtleties of Xojo, there is much to learn!

The label was converted to a TextArea, and cbSize of the memoryblock was loaded with the value 200. After running the program the GetLastError is 5. I’ll keep working on this and feel free to suggest any other helpful hints.

All the best!

[code] Declare Function SendMessage Lib “user32” Alias “SendMessageA” (hwnd As integer, wMsg As Integer, ByVal wParam As integer, ByVal lParam As Ptr) As Integer
Const EM_GETCHARFORMAT = 1082 //&h43A

Const SCF_SELECTION = &h1
Const SCF_DEFAULT = &h0
Dim MyString as CString = TextArea1.Text
Dim MyAnswer as Integer
Dim m as New MemoryBlock(200)

TextArea1.SelectAll
m.Size = 200
m.UInt32Value(0) = 200 //Set cbSize to size of MemoryBlock
MyAnswer = SendMessage(TextArea1.Handle, EM_GETCHARFORMAT, SCF_DEFAULT, m)

Label2.Text = "MyAnswer = " + CStr(MyAnswer) + EndOfLine +_
"Label1.Handle = " + CStr(TextArea1.Handle) + EndOfLine +_
"m.Size = " + CStr(m.Size) + EndOfLine +_
"m.Int32Value(0) cbSize = " + CStr(m.Int32Value(0)) + EndOfLine +_
"m.Int32Value(4) dwMask = " + CStr(m.Int32Value(1)) + EndOfLine +_
"m.Int32Value(8) dwEffects = " + CStr(m.Int32Value(8)) + EndOfLine +_
"m.Int32Value(12) yHeight = " + CStr(m.Int32Value(12)) + EndOfLine +_
"m.Int32Value(16) yOffset = " + CStr(m.Int32Value(16)) + EndOfLine +_
"m.Int32Value(20) crTextColor = " + CStr(m.Int32Value(20)) + EndOfLine +_
"m.Byte(24) bCharSet = " + CStr(m.Byte(24)) + EndOfLine +_
"m.Byte(25) bPitchAndFamily = " + CStr(m.Byte(25)) + EndOfLine +_
"m.CString(26) szFaceName = " + CStr(m.CString(26)) + EndOfLine [/code]

The returned value is zero, which should mean that the Declare call is successful and the returned memory block values are: MyAnswer = 0 Label1.handle = 265702 //this will change m.size = 200 m.Int32Value(0) cbSize = 200 m.Int32Value(4) dwMask = 0 m.Int32Value(8) dwEffects = 0 m.Int32Value(12) yHeight = 0 m.Int32Value(16) yOffset = 0 m.Int32Value(20) crTextColor = 0 m.Byte(24) bCharSet = 0 m.Byte(25) bPitchAndFamily = 0 m.Cstring(26) szFaceName =

Thanks Eugene and everyone to looking at this.
Unfortunately I can’t provide any suggestions due to my poor knowledge of Windows API.

Personally, unless the pure Xojo code approach does not bring the adequate result, or is too slow, I do not necessarily dig into declares. In this instance on the Mac the pure Xojo does not bring the adequate result, most probably because StringWidth is warped with System and SmallSystem zero, but on Windows it works perfectly.

Perhaps you forgot my point: which size is the SmallSystem font?
Xojo reports 0 and you can set 0 to have the default from Windows. Just need to know the default size for the SmallSystem font.

And the Metrics Info from the C-Class mentioned in this Dev Lib does not work?

[quote=186242:@Massimo Valle]Perhaps you forgot my point: which size is the SmallSystem font?
Xojo reports 0 and you can set 0 to have the default from Windows. Just need to know the default size for the SmallSystem font.[/quote]

[code] dim pic as new picture(1,1)

Pic.graphics.TextFont = “SmallSystem”
Pic.Graphics.TextSize = 0

dim lengthoftext as integer = round(pic.graphics.stringwidth(Label1.Text))

for i as integer = 8 to 16
Pic.Graphics.TextSize = i
if lengthoftext = round(pic.graphics.stringwidth(Label1.Text)) then Msgbox str(i)
next[/code]

Fonts have very precise dimensions that are reported by StringWidth. A simple comparison gives you the actual size used by zero. Is it it not what you wanted to obtain ? I tested the method above on Mac and Windows, the result is absolutely correct.

Well, I posted on Windows channel because I have this problem on Windows :wink:
On Mac I know how to do it, thanks anyway.

Damn Forum Software :wink:
Sorry :slight_smile:

[quote=186246:@Michel Bujardet][code] dim pic as new picture(1,1)

Pic.graphics.TextFont = “SmallSystem”
Pic.Graphics.TextSize = 0

dim lengthoftext as integer = round(pic.graphics.stringwidth(Label1.Text))

for i as integer = 8 to 16
Pic.Graphics.TextSize = i
if lengthoftext = round(pic.graphics.stringwidth(Label1.Text)) then Msgbox str(i)
next[/code]

Fonts have very precise dimensions that are reported by StringWidth. A simple comparison gives you the actual size used by zero. Is it it not what you wanted to obtain ? I tested the method above on Mac and Windows, the result is absolutely correct.[/quote]

This would probably works, but… it’s crazy 8)
I mean, why measuring things with a try catch approach when the OS can probably tell this?
What if the SmallSystem was set to 7? or 18?..

Thanks for your answer but it’s a lame approach. :wink:

[quote=186249:@Massimo Valle]This would probably works, but… it’s crazy 8)
I mean, why measuring things with a try catch approach when the OS can probably tell this?
What if the SmallSystem was set to 7? or 18?..

Thanks for your answer but it’s a lame approach. ;)[/quote]

Massimo, I have been designing fonts for a very long time. Before declare snobism decided that a series of characters should be seen only in terms of system calls, there are foremost graphics. My approach is not lame, it is a typographical one. Your criticising attitude is not constructive. Don’t go calling names what you simply do not like.

Michel, sorry I didn’t want to be rude. I’m really grateful for your help. :slight_smile:
The solution is lame, not from a typographical point of view, but from a programming point of view.
I’m sure of this as you are sure about your typographic measurements.

Thanks anyway, and again, sorry if my answer appeared to be rude. Was not my intention.