[Library] Fnt v4.0 - Do Stuff With Fonts

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

[Library] Fnt v4.0 - Do Stuff With Fonts

25 Aug 2014, 21:18

Post History
This library was first released on the original AutoHotkey forum. You can find the original post here.

Introduction
Most font requirements can be handled with the AutoHotkey gui Font and GUIControl Font commands but there are limitations. The Fnt library was created to expand on what can be done with fonts.

Fnt Library
Key features:
  • Create fonts. Create and delete logical fonts as needed. Yes, this is one way to get around the AutoHotkey upper limit of 200 fonts. Starting with v0.6, creating any of the standard non-client fonts (Ex: Menu font) is a snap.
  • Calculate the size of GUI controls before creating them. Or after changing the font of a GUI control. New functions introduced in v3.0 make it even easier to accurately calculate the size for some GUI controls.
  • Calculate the tab stops on Edit, Rich Edit, or ListBox controls. New functions released in v0.6 make it much easier to set the tab stops based on actual data.
  • Calculate the largest font size to fit. A new function released in v4.0 makes it easy to calculate the font size needed to fit text within a fixed space.
What's New in Version 4
Version 4 is not a reboot but there are a large number of changes and a large number of possible script breakers. Please read the Release Notes carefully before using. Some key updates:

New functions:
  • Fnt_CalculateFontSizeToFit. Calculate the font size needed to fit a string of one or lines of text to fit within a fixed space. Version 3.0 of the library included a experimental version of a function that did something similar. This function is significantly more efficient.
  • Fnt_DrawText and Fnt_DrawTextToBitmap. These functions include a large number of formatting options to draw text to a static control or to a bitmap.
  • Fnt_IsValidFaceName and Fnt_IsValidFontName. Quickly determine if a font is installed on the current computer.
  • Character set. New functions and changes to existing functions to support the character set of a font.
Updates:
  • Flag/Option string names. All functions with parameters that contain bit flag values have been modified to also support string names that represent each bit flag value. For example, instead of setting a parameter to the following bit flag values: 0x800|0x40000|0x2000000, a string with the following values can be used instead: "NoOEMFonts|TTOnly|InactiveFonts". This update makes it significantly easier to set the flag values, make changes, and to debug.
  • Fnt_ChooseFontDlg. This function has been modified so that it no longer requires non-Fnt functions to operate. Interpretation: All external functions have been integrated into the Fnt library.
  • Documentation. The general library documentation has been moved to the _Fnt.Doc.ahk file. Natural Docs v2.0 is used to generate HTML documentation from this file and from the function documentation. This HTML document is in a new format that is different from the previous version of this library. See the Release Notes for more information.
The Code
The pertinent files are as follows:
  • Project: Fnt.zip
    This archive file includes Fnt library, add-on libraries, example scripts, and project documentation.
  • Documentation: Starting with v4.0, the project documentation is included in the project archive file (above).
Compatibility
Starting with v2.0, this library is designed to work on all versions of AutoHotkey v1.1+. It is not compatible with AutoHotkey v2.0+.

Issues/Considerations
A few considerations:
  • Windows compatibility. The library is designed to run on all versions of Windows >= Windows Vista. The reality is that I only have one machine to test this software on. If you experience any problems with your version of Windows, please let me know. I will try to correct the problem.
  • DPIScale. The DPIScale feature (AutoHotkey v1.1.11+) can be incompatible with the Fnt library. See the library documentation for more information.
  • Tooltips. Out of the blue, Microsoft changed how the tooltip control responds to certain messages. The tooltip may no longer automatically redraw when the WM_SETFONT message is sent. Worse yet, if the Redraw option of the WM_SETFONT message is set to TRUE, the tooltip may be deactivated (hidden but not destroyed). Starting with v0.9, the Fnt_UpdateTooltip function was added to work in conjunction with the Fnt_SetFont function when used on a tooltip control. See the documentation in the Fnt_SetFont function for more information.
  • Windows 10+. There are a very small number of features that work as expected on Windows XP through Windows 7, but do not work as expected on Windows 10+. They are certainly not show stoppers but the "inconvenience factor" may be consideration. These "works differently on Windows 10" issues are identified in the release notes or in the project documentation.
  • Examples. If any of the examples don't work as expected, please let me know. I will try to correct the problem. Also, the examples have been written for the most common screen resolutions - 1920x1080 or higher. Screens with resolutions at least 1280x768 should work fine but there might be a few exceptions. For screens with a resolution less than 1280x768, there may be more than than a few examples that don't display well. If you experience a problem with an example because of screen resolution, let me know. I will try to correct the problem.
Last AutoHotkey v1.1+ Version
With the exception of bug fixes, v4.0 will be last version of the Fnt library for AutoHotkey v1.1+. Future versions (if any) will require AutoHotkey v2.0+.

References Release Notes
Last edited by jballi on 28 Jun 2023, 03:54, edited 11 times in total.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

25 Aug 2014, 21:21

v0.6 (Preview)
Bug fixes, enhancements, and a bunch of new functions. See the bottom of the first post for the details.
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

26 Aug 2014, 19:39

Great! Im happy to see this library "alive" again :D
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

02 Sep 2014, 11:49

Dialog Template Units

Introduction
The latest release of the Fnt library introduces functions that convert to and from Dialog Template Units. This topic can be confusing and sometimes frustrating and so I created this document in an attempt to generate a better understanding of the subject.

Stuff To Know
This document discusses "dialog base units" and "dialog template units". Be careful. These terms look very similar but they describe different types of measurement. To help differentiate the terms, I've given them different colors so that dialog base units won't be easily confused with dialog template units. This document may look a bit like a coloring book but I hope that it helps.

These terms are often prepended with "horizontal" or "vertical". For example: horizontal dialog template units. "Horizontal" refers to the width or x-Axis of the measurement. "Vertical" refers to the height or y-Axis of the measurement.

Background and Executive Summary
Someone a long time ago figured out that the font used in a window can be used to determine the size of the window and/or the size of objects in the window. The original idea was a means of controlling the size of system dialogs. If the system font was small, then the dialog window was created to be one size. If the system font was large, then the same dialog was created to be a larger size to accommodate for the larger font.

Dialog Template Units are font-based units of measurement. They are used to specify the size (width and/or height) of a window or GUI control without knowing the font or font size that will be used to populate the text within the window and/or GUI control. The unfortunate name is a result of defining a unit of measurement within dialog box templates which are structures used by the DialogBox and CreateDialog functions.

Dialog Base Units
Everything is "based" on Dialog Base Units.

A horizontal dialog base unit is the average width, in pixels, of all of the uppercase and lowercase Roman characters of a font, i.e. the average width of this string: "AaBbCc...Zz". A vertical dialog base unit is equal to the height, in pixels, of the font.

Dialog Template Units
Dialog Template Units are just smaller units of Dialog Base Units.

There are 4 horizontal dialog template units for each horizontal dialog base units. There are 8 vertical dialog template units for each vertical dialog base units.

Improving Understanding
There are a few facts and mnemonics that should make it a bit easier to understand how to convert to or from dialog template units.

Horizontal
Horizontal dialog template units are based on horizontal dialog base units which are based on the width of a average character of a font. So, instead of horizontal dialog template units, think of the number of "average characters" of a font.

There are 4 horizontal dialog template units for every "average character" of a font. So, to convert "average characters" to dialog template units, multiply the number of "average characters" by 4. For example, to create a GUI control that is 60 "average characters" in width, specify 240 (60 times 4) horizontal dialog template units.

To convert horizontal dialog template units back into "average characters", divide by 4. For example, 500 horizontal dialog template units is equal to 125 (500 divided by 4) "average characters".

Vertical
Don't worry too much about vertical dialog template units. They are equal to factor (8:1) of the height of the font. When measuring a single line of text, the value will always be 8. For two lines of text, the value will always be 16. And so on. This measurement is not as valuable because 1) the height of the font is always available and 2) calculating the height of a control is a little more complicated than knowing the height of the font.

When converting from vertical dialog template units, just divide by 8. For example, 80 vertical dialog template units is equal to 10 vertical dialog base units which is equal to the height of 10 characters of a font.

Uses
Dialog template units are rarely used outside of the dialog template structure but the methodology used to convert to/from them does provide value. In general, the library functions can be used to calculate the size of a GUI control before it is created or after the font is changed on the control. Also, the functions can be used to set the tab stops on an Edit or Rich Edit control which are set in dialog template units. I originally created these functions to support this feature.

The Fnt library includes a few examples that use the dialog template units functions. They include:

Code: Select all

Example - Dialog Template Units.ahk
Example - Set Tab Stops on Edit Control.ahk
I've modified several other library examples to use the dialog template units functions to help format the data that is displayed as a part of the output of the example.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

28 Sep 2014, 23:08

I ask, why do I use Fnt_GetStringWidth () Gets the width is not uniform it?
such as unified menu width:

Image

Code: Select all

f:=StrSplit(".;8a-@sdf1|9ESDFKOOI")
Loop 10
{
    b:=""
    Loop 500
    {
        Random, d, 1, f.MaxIndex()
        b.=f[d]
	a:=Fnt_GetStringWidth(0,b)
	if (a>=400)
	Break
    }

    Menu, Test, Add, % b, Test
}
Menu, Test, Show
Test:
Thanks.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

28 Sep 2014, 23:36

Does not seem to get the default font, more unified:
Image

Code: Select all

f:=StrSplit(".;8a-@sdf1|sdfSdf无可奈何花落去士大夫9ESDFKOOI")
Loop 10
{
    b:=""
    Loop 
    {
        Random, d, 1, f.MaxIndex()
        b.=f[d]
	a:=Fnt_GetStringSize(1,b)
	if (a>=400)
	  {
		b:=a "  " b
		Break
	  }
    }


    Menu, Test, Add, % b "...", Test
}
Menu, Test, Show
Test:
Return

Fnt_GetStringSize(hFont,p_String)
    {
    Static Dummy6596
          ,DEFAULT_GUI_FONT:=17
          ,HWND_DESKTOP    :=0
          ,SIZE
    PtrType:=(A_PtrSize=8) ? "Ptr":"UInt"

    ;-- If needed, get the handle to the default GUI font
    if not hFont
        hFont:=DllCall("GetStockObject","Int",DEFAULT_GUI_FONT)

    ;-- Select the font into the device context for the desktop
    hDC      :=DllCall("GetDC",PtrType,HWND_DESKTOP)
    hFont_Old:=DllCall("SelectObject",PtrType,hDC,PtrType,hFont)

    ;-- Get string size
    VarSetCapacity(SIZE,8,0)
    RC:=DllCall("GetTextExtentPoint32"
        ,PtrType,hDC                                    ;-- hDC
        ,"Str",p_String                                 ;-- lpString
        ,"Int",StrLen(p_String)                         ;-- c (string length)
        ,PtrType,&SIZE)                                 ;-- lpSize

    ;-- Housekeeping
    DllCall("SelectObject",PtrType,hDC,PtrType,hFont_Old)
        ;-- Necessary to avoid memory leak

    DllCall("ReleaseDC",PtrType,HWND_DESKTOP,PtrType,hDC)

    ;-- Return to sender
    if RC
        Return NumGet(SIZE,0,"Int")

    }
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 00:14

arcticir wrote:I ask, why do I use Fnt_GetStringWidth () Gets the width is not uniform it?
such as unified menu width:
Hey arcticir,

With a double-byte character set, you are definitely getting into an area that is out of my league but I'm hoping that it's just an apples vs. oranges problem. You are testing the width of a string using the default GUI font but using the system Menu font to display the string. Try this.

Code: Select all

hMenuFont:=Fnt_CreateMenuFont()
f:=StrSplit(".;8a-@sdf1|9ESDFKOOI")
Loop 10
{
    b:=""
    Loop 500
    {
        Random, d, 1, f.MaxIndex()
        b.=f[d]
    a:=Fnt_GetStringWidth(hMenuFont,b)
    if (a>=400)
    Break
    }

    Menu, Test, Add, % b, Test
}
Fnt_DeleteFont(hMenuFont)
Menu, Test, Show
Test:
return
I hope this helps.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 01:09

Thank you, it solved my problems. :D

In addition, I ask, in addition to calculating the width of each word, there is any way to get the character within the width of it?
For example:

Code: Select all

a:=Fnt_XXX(hMenuFont,"ASFDSFDSGSDFASDF",40)
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 08:00

arcticir wrote:In addition to calculating the width of each word, there is any way to get the character within the width of it?
For example:

Code: Select all

a:=Fnt_XXX(hMenuFont,"ASFDSFDSGSDFASDF",40)
I'm sorry, I'm going to need a little more help with this one. When you say, "calculate the width of each word", what does a "word" represent? In your example, 1) what does the "40" represent and 2) what is returned?, i.e. what is stored in the "a" variable? It would be very helpful if you could give me a more detailed example and/or more information on what you you are trying to accomplish. Thanks.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 08:38

Sorry, my negligence.

Now need to calculate each character

Code: Select all

f:="ASFDSFDSGSDFASDF"
Loop, parse, f
{
b.=A_LoopField
    a:=Fnt_GetStringWidth(hMenuFont,b)
    if (a>=40)
    Break
}

I think the character width can get within a specified
Do not use the "Loop"

Code: Select all

a:=Fnt_GetStringWidth(hMenuFont,"ASFDSFDSGSDFASDF")
if     if (a>40)
b:=Fnt_XXX(hMenuFont,"ASFDSFDSGSDFASDF",40)  ;Such as Return "ASFD"
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 16:12

If I read this requirement correctly, it reads something like, "Give me the portion of a string that is less than or equal to a specified number of pixels of a specified font."

I do see something like a Fnt_TruncateStringToFit function in the future (thanks for the idea) but I don't have anything for now. It's not very efficient, but a brute-force method (checking one character at a time) like your example is the fastest thing to program and will probably return the value in a very reasonable amount of time. I'm sorry I couldn't be more helpful.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

29 Sep 2014, 22:42

Thank you, you have helped me a lot.

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

I extracted Fnt.ahk some code, write a small function to accelerate. I hope you do not mind.

Code: Select all

sw:=StringWidth()
f:=StrSplit(".;8a-@sdf1|9ESDFKOOI")
Loop 10
{
    b:=""
    Loop 500
    {
        Random, d, 1, f.MaxIndex()
        b.=f[d]
    }
	b:=sw.Width(b,400)
    Menu, Test, Add, % b, Test
}

Menu, Test, Show
Test:
return
 

Code: Select all

StringWidth(h:=""){
	Return New StringWidth(h)
}

Class StringWidth {
	__New(hFont){
		PtrType:=(A_PtrSize=8) ? "Ptr":"UInt"
		if !This.hFont:=hFont
			This.Font:=hFont:=Fnt_CreateMenuFont()
		This.DC		:=DllCall("GetDC",PtrType,0)
		This.Old	:=DllCall("SelectObject",PtrType,This.DC,PtrType,hFont)
	}

	Width(String,StrLen,fs:="..."){
		Static PtrType:=(A_PtrSize=8) ? "Ptr":"UInt",SIZE,ss:=VarSetCapacity(SIZE,8,0)
		RC:=DllCall("GetTextExtentPoint32",PtrType,This.DC ,"Str",String ,"Int",StrLen(String),PtrType,&SIZE)
		if (NumGet(SIZE,0,"Int") >= StrLen)
			{
				Loop, parse, String
				{
					b.=A_LoopField,RC:=DllCall("GetTextExtentPoint32",PtrType,This.DC ,"Str",b,"Int",A_Index,PtrType,&SIZE)
					if (NumGet(SIZE,0,"Int") >= StrLen)
					{			
						b.=fs
						Break 
					}			
				}
			}
			else	b:=String
		Return b
	}
	__Delete(){
		PtrType:=(A_PtrSize=8) ? "Ptr":"UInt"
		if This.Font
			Fnt_DeleteFont(This.Font)
		DllCall("SelectObject",PtrType,This.DC,PtrType,This.Old),DllCall("ReleaseDC",PtrType,0,PtrType,This.DC)
	}

}
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.6 (Preview) - Do Stuff With Fonts

30 Sep 2014, 14:35

arcticir, I've written a general purpose function to do the job. I've named it Fnt_TruncateStringToFit for now. It was designed to try to make the smallest number of calls to external functions, specifically Fnt_GetStringSize, as possible. After the methodology has been vetted (and if merited), I will update it for additional efficiency.

Since you have a real-life use for this function, I will PM you a copy of the function for your review. Please give it try at your convenience. Be aware that the version I'm posting is in full debug mode. If you have a debug viewer, you can see what's going on in the background. If you have any additional questions, problems, or comments on this topic, please PM me.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.7 (Preview) - Do Stuff With Fonts

08 Oct 2014, 22:54

v0.7 (Preview)
A bug fix, several enhancements, and some new functions. See the bottom of the first post for the details.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: [Library] Fnt v0.7 (Preview) - Do Stuff With Fonts

01 Nov 2014, 05:36

I added a parameter.

Code: Select all

Fnt_TruncateStringToFit(hFont,p_String,p_MaxStringW,Ellipsis:=""){
………
Return l_String Ellipsis  ;"…"
}

Thank you for giving us such a good library.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.8 (Preview) - Do Stuff With Fonts

06 Jan 2015, 03:50

v0.8 (Preview)
A few new functions. See the bottom of the first post for the details.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v0.9 (Preview) - Do Stuff With Fonts

19 Aug 2015, 01:57

v0.9 (Preview)
New font options "helper" functions and a few new miscellaneous functions. See the Release Notes section of the first post for the details.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v1.0 - Do Stuff With Fonts

04 Nov 2015, 21:20

v1.0
A bug fix, a new function, and a few new/updated examples. See the Release Notes section of the first post for the details.

Please note that this version will be last version of the library to support all versions of AutoHotkey. Future versions (if any) will only support AutoHotkey v1.1+.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Status Bar Font

04 May 2016, 00:42

Status Bar Font

I've noticed this several times over the years but because the status bar is an easily-forgotten component of a window, I did not put two and two together until recently.

AutoHotkey sets the font for the text displayed in the status bar. If the developer does not specify a font or the gui Font command is used without parameters before the status bar is added, the default GUI font is used. Otherwise, the last font set before the status bar is added is used.

The thing is, the font used to draw the text in the status bar is supposed to be a component of Non-client Metrics. These are system-wide parameters used by all windows. "Non-client" refers to all components of the window that are not part of the client. They include the border, caption, menu, status bar, etc. From a font perspective, this includes the caption font, menu font, status font (status bar and tooltips) and message font (MsgBox dialog).

Non-client attributes like the status bar font are set by default when the user selects a theme and text size (DPI). If desired, the user can customize one or more of these items by going to the Control Panel (Window Color and Appearance dialog) and change the font, size, color, etc. Non-client attributes can also be set programmatically (one example here) although I haven't been able to come up with an real-life reason to do so.

So, what's wrong with using the default GUI font for the status bar? Absolutely nothing. It's a very readable font and because the font size is smaller on many themes, you can fit a lot of text in small amount of space. The problem is that it's not the font selected by the user when they selected the theme, DPI, or when they customized it in the Control Panel. For many themes, the non-client font used for the status bar is a bit larger and easier to read than the default GUI font.

Instructing AutoHotkey to use the system non-client font for the status bar is easy with the Fnt library. The best time to do it is when the status bar is added to the GUI. For example:

Code: Select all

gui Font,% "s" . Fnt_GetStatusFontSize(),% Fnt_GetStatusFontName()
gui Add,StatusBar
This method uses the standard Autohotkey gui Font command to establish the correct font before the status bar is added.

If needed, the font can be set after the status bar has been added. For example:

Code: Select all

hSBFont:=Fnt_CreateStatusFont()
Fnt_SetFont(hSB,hSBFont,True)
  ;-- This assumes that hSB is the handle to the status bar
I recently started making these changes to some of my scripts that have a GUI with a status bar. For my theme and DPI, the font size is a bit larger and easier to read than the default GUI font. In addition, it matches the menu font.
User avatar
jballi
Posts: 723
Joined: 29 Sep 2013, 17:34

Re: [Library] Fnt v2.0 - Do Stuff With Fonts

05 May 2016, 05:53

v2.0
Minor bug fix, several enhancements, several new functions, and new and updated examples. See the Release Notes section of the first post for the details.

This and future versions of the library will only run on AutoHotkey v1.1+.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 120 guests