top of page

Showing the 'Font' dialog box using the ChooseFont Windows API Function

  • Writer: John
    John
  • 1 day ago
  • 3 min read
This post is one of a series providing implementation examples of Windows API Functions, Types, Enums and Consts using VBA. The code in this post can be used as-is, however, if you regularly (or even just occasionally) work with Windows API declarations in VBA, you may want to see the posts Automatically add Windows API declaration(s) and Using 'F1' to view Windows API web pages which explain some of the functionality that can be added to the VBE by VBE_Extras.

First things first ... I didn't develop all of this code by myself. I came across this in an article dated January 2019 named ChooseFont-Dialog-API for 64-Bit-VBA on Philipp Stiefel's Codekabinett website. He, in turn, had found the original (32-bit only) code on Stephan Lebans' website and adapted it to work with 64-bits. And it appears that Stephan Lebans modified code that was originally written by Terry Kreft.


The code shows the 'Font' dialog box ...


The 'Font' dialog box

... and allows all of the values in the controls within it to be set before it is shown, and to be read after it is shown. This means that your code can allow the user to select a font, including:


  • The font name

  • The font style (eg italic, bold)

  • The font size

  • Whether the font is 'strikeout'

  • Whether the font is 'underlined'

  • The font colour

  • The specific script (ie the charset)


So what does my version of the code do that is different to Philipp Stiefel's version? A few things:


  • It uses Unicode (not ANSI) Functions and Types meaning that, for example, it can handle font names and font styles that might include Unicode characters in their names

  • It allows for setting / getting the Strikeout and CharSet (aka Script) values ... though note that a TextBox doesn't support different CharSets (even though it does have a ... hidden ... Font.CharSet property)

  • It avoids memory leaks by: releasing the Device Context that is created when converting the font height from points to 'logical units'; releasing the memory that is locked while showing the Font dialog


So, first, here is the core code to show the 'Font' dialog. This should be put in a standard Module in your VBA Project ... if you want to try this out with the subsequent code in this post, then call the Module "ModuleChooseFont" ...



So ... how to use this code?! Here's two options ... this first option is to just run it from within the VBE using F5 (or Run > Run Sub/UserForm) using this code (which you should put in a standard Module) ...



This uses a static variable 'tFormFontInfo' to remember the values chosen from one 'run' of the Sub to the next. And it sets some sensible defaults for some of the members of tFormFontInfo as it will be initialised with zero's and empty Strings which don't make much sense. After the Font dialog is closed, it sends details of the selections made to the Immediate window.


This is a second example for which you will need a UserForm named 'UserForm1' with a TextBox named 'TextBox1' and a CommandButton named 'CommandButton1'. The only code you need in the code-behind for the UserForm is this ...



... and then you can show the UserForm like so ...



Note that the TestWithTextBox Function has a parameter named txtBox that has an Object value type but you pass a TextBox (actually an MSForms.TextBox) into it (from the CommandButton1_Click event handler Sub in the UserForm). The reason for using Object is because, assuming you added this code to a new VBA Project, until you add a UserForm, your project will not have a reference to the 'Microsoft Forms 2.0 Object Library' and, obviously, MSForms.TextBox lives in that library. This would result in a compilation error. Once you have added a UserForm (when you add a UserForm, the VBE automatically adds the reference to the 'Microsoft Forms 2.0 Object Library' for you), or add the reference to the library manually, you can (if you want) change the value type of the txtBox parameter to MSForms.TextBox. This just makes the code clearer as to what type of object must be passed in to the Function.


To make life simpler, below is an Excel Workbook containing all of the code ... once downloaded, unzipped and unblocked (if you don't know how to unblock the file, see my Unblock a file containing VBA code post), just click the 'Click me' button on Sheet1 to run the code (and the close button ... the "red X" in the UserForm's title bar ... when you are done).



Comments


bottom of page