Liberty BASIC Default Variables
Internet - Downloading a File to Disk
API Corner - Easy Font Manipulations
Mapping Real World Coordinates
API Zone... Beware!
It is best to understand the use of API calls in Liberty BASIC before using this technique. Earlier issues of the newsletter include tutorials for calling the Windows API from Liberty BASIC, and for creating an manipulating controls with API calls. This method is meant for the more experienced Liberty BASIC programmer.
FontDialog
For a complete discussion of the FontDialog command, see issue #68. This command allows the user to select a font facename and size, along with attributes like bold and italic. When the FontDialog returns, the options chosen by the user are contained in the receiver variable. The FontDialog requires a font specification provided by the programmer and returns the choice made by the user. Remember that Liberty BASIC replaces blank spaces in font names with the underscore character.
fontdialog "arial", font$ fontdialog "courier_new bold 12", font$
Fonts in Liberty BASIC Windows and Controls
Windows and controls have default fonts. No font commands need to be issued if the default font face and size is acceptable.
The font on a window or control can be changed with the font command. If a font command is sent to a window, all controls on the window will display text using the specified font. Both statictext controls in the window below display the same font:
statictext #win.1, "First",10,10,100,24 statictext #win.2, "Second",10,50,100,24 open "Test" for window as #win #win "font verdana italic 12" wait
The window font command can be overridden by sending an individual font command to a control. Controls that can display text must have a font command preceded by a "!" character. The second statictext below has its own font:
statictext #win.1, "First",10,10,100,24 statictext #win.2, "Second",10,50,100,24 open "Test" for window as #win #win "font verdana italic 12" #win.2 "!font arial bold 16" wait
A groupbox has no font command available. Groupboxes display the default font, or the font from the window font command.
groupbox #1.group, "Groupbox",10,10,200,200 open "Test" for window as #1 #1 "font arial italic 14" wait
API Font Command
Right about now, you are probably wondering why this article is in the API Corner! Fonts are easy enough to handle with native LB commands! Unfortunately, there are some places where native LB font commands won't work. One of these places is in the groupbox. Because a groupbox doesn't have its own font command, it must display either the default font or the font in the command given to the window. A unique groupbox font can be accomplished in one of several ways.
Font Handles
Since setting a control font by API requires a handle to a font, a font handle must first be obtained. The most complex, but most flexible way is to CreateFontA with an API call. It is a long function with many arguments.
It is easier to get the stock GUI font, which is done with GetStockObject and a flag of _DEFAULT_GUI_FONT as below. This only allows the program to get a handle to the default font, so although it is easier, it is far less flexible than CreateFontA.
calldll #gdi32, "GetStockObject",_ _DEFAULT_GUI_FONT as long, hFont as long
There is a method that makes use of Liberty BASIC easy access to fonts and combines it with some very simple API calls. It requires that a font command be issued to a Liberty BASIC control. This control can be visible and in use, or it can be a dummy control that is located off the window at negative coordinates. Once this font command has been issued, a handle to the font can be obtained with the SendMessageA API call, using the control handle as the first argument and _WM_GETFONT as the second argument. The next two arguments are passed as "0", and the function returns the handle to the font on the control.
CallDLL #user32, "SendMessageA",_ hWnd As Long,_ 'window or control handle _WM_GETFONT As Long,_ 'message 0 As Long,_ 'wordParam 0 As Long,_ 'longParam hFont As Long 'returns handle of font
Once this handle has been obtained, it can be used to set the font on a groupbox or other LB control with the SendMessageA API call. It requires a handle to the control that is to receive the font. The second argument is the message flag _WM_SETFONT. The next argument is the handle of the font and the last argument is passed as "1" which causes the control to repaint and show its new font.
CallDLL #user32, "SendMessageA",_ hWnd As Long,_ 'window or control handle _WM_SETFONT As Long,_ 'message hFont As Long,_ 'handle of font 1 As Long,_ 'repaint flag result As Long
Demo
In the little demo below, the user selects a font from a fontdialog. A Liberty BASIC font command is used to display this font on a visible button - the "Exit" button in this case. When the user clicks the "Change Groupbox Font" button, the handle for the font is obtained and used to set the font on the groupbox. To simplify the code, the SendMessagA API call is wrapped in a Liberty BASIC function.
nomainwin groupbox #1.group, "Groupbox",10,10,200,200 button #1.change, "Change Groupbox Font",[change],UL,20,50,170,40 button #1.quit, "Exit",[quit],UL,20,100,170,40 open "Change Groupbox Font" for window_nf as #1 #1 "trapclose [quit]" 'set font for all controls on window: #1 "font arial 10" 'allow user to select a font on his system fontdialog "times_new_roman italic 12",font$ 'now override window font command and set font 'for exit button as chosen by user: #1.quit "!font " ; font$ wait [quit] close #1:end [change] 'get handle for exit button font hFont=SendMessage(hwnd(#1.quit),_WM_GETFONT,0,0) 'set groupbox font to match exit button ret = SendMessage(hwnd(#1.group),_WM_SETFONT,hFont,1) wait Function SendMessage(hWnd,msg,wParam,lParam) CallDLL #user32, "SendMessageA",_ hWnd As Long,_ 'window or control handle msg As Long,_ 'message wParam As Long,_ 'wordParam lParam As Long,_ 'longParam SendMessage As Long 'return from function End Function