REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 063

FontPrinter: Part Two

In our previous lesson, we got started creating FontPrinter, a simple program that prints out a chart of available characters of a font. This project will teach us about printing in REALbasic, as well as creating our own print preview system we can use in other programs.

Create an About Box

To get us started, let's create an About Box for our program. We'll need a few items for this, so start by downloading this file.

The items within that archive are: fingerCursor, a cursor resource, and rbulogo.pct, a graphic of the RBU logo. There's also a class called hotCanvasClass, which we used in a previous project: it's a canvas subclass that includes a URL property in which we can install a URL to go to when the user clicks on it.

Put the graphic and the cursor within the "Linked Resources" folder (inside your project folder) and then drag them into your project. It doesn't matter where you put hotCanvasClass -- once you drag it to the project window, it's embedded into your project file. You can put the original someplace where you'll find it in case you want to use it in other projects.

Now let's add the About Box window (File, "New Window"). Give it these settings:

Within the window, you'll need several items: drag on three staticText controls, one canvas, and two hotCanvasClass items (you can drag these from the project window onto aboutWindow).

Give the canvas control these settings:

Select staticText1 and give it these settings (note that the large text reads "FontPrinter"):

StaticText2 should look like this:

The text for staticText2 should be this (yes, the URL lines are left blank):

Copyright ©2002 by REALbasic University. All Rights Reserved.
Free, non-commercial distribution is permitted.
REALbasic University Website:
REALbasic Developer Magazine:

Finally, take staticText3 and give it these settings:

The finished About Box window should look like this:

Note that we've placed the two hotCanvasClass objects on the window (the rectangles to the right of the about text). The top one should be named rbuCanvas and the bottom one rbdCanvas.

Now that the graphical interface is done, let's add some code.

First, let's do some initialization stuff. Go to the Open even of aboutWindow and add this:

  
rbdCanvas.url = "http://www.rbdeveloper.com/"
rbuCanvas.url = "http://www.applelinks.com/rbu/"

Next, in both keyDown and mouseDown events, put this:

  
self.close

Now, I could have created a "logo" for the FontPrinter using a graphics program like Adobe Photoshop and brought that into the program the same way we did the RBU logo. But in this case I was in a hurry and didn't feel like firing up Photoshop just for a bit of text, but at the same time, a program's name written in Charcoal or whatever is incredibly boring.

So why not just use a large staticText and set the font to something fancy, like FrenchScript?

The problem with that approach is that a user may not have FrenchScript installed. There's a simple workaround for that, however: we just need to check to see if the font we want to use is installed.

Let's add a method to aboutWindow (Edit menu, "New Method"). Give it these settings:

Good. Now just put in this code:

  
dim i,n as integer

n = FontCount-1
for i = 0 to n
if Font(i) = fontName then
return true
end if
next

Again, this is simple code. All we are doing is stepping through all the installed fonts and seeing if the one we passed is installed. If it is, we return true.

You can actually grab this right from REALbasic's online help (though the formatting is slightly different). Note that in the RB example code, they add a "return false" at the end of the method. That isn't really needed since methods return false by default (unless you explicity return true earlier, the method returns false at the end).

Once we've got this method written, we can use it. Go to the Open event of staticText1 and put in this:

  
if fontAvailable("FrenchScript") then
me.textFont = "FrenchScript"
me.textSize = 60
elseif fontAvailable("Sand") then
me.textFont = "Sand"
elseif fontAvailable("Gadget") then
me.textFont = "Gadget"
else
me.textFont = "System"
end if

You see how this works? We check to see if a font is installed; if it is, we use it, otherwise we try a different font. Feel free to expand this to cover more fonts or change the font names to match fonts you prefer.

There's only one more step to fully active the About Box: open Window1 and go to the AppleAbout menu handler and put in this line of code:

  
aboutWindow.showModal

Perfect! Try running the program and choosing "About FontPrinter" from the Apple Menu (app menu under Mac OS X). Notice how the About Box works: when you put the mouse cursor over a hot-linked URL, it changes to a finger cursor (clicking will launch your web browser and take you to that location). Simple, but easy to do and effective.

Adding Global Variables

You might have noticed that one of the items in our About Box was a staticText item which included the text "#kversion" -- and when you ran the program, it displayed as "kversion" -- what's up with that?

When you use a number sign in front of a menu item's text or the contents of a staticText, that tells REALbasic you're using a constant. In the case of FontPrinter, we haven't yet defined a constant called kversion, so just the text is displayed. Let's fix that.

Add a new module (File menu, "New Module") and name it globalsModule. Within it (double-click on it to open it) add a new constant (Edit menu, "New Constant") called kversion and give it a value of "1.0" (no quotes, of course). That's going to represent the version number of our application.

Next, add the following global properties (variables) to globalsModule:

Finally, we're going to add an initialization routine to the program. When I first wrote FontPrinter, I simply "hard-coded" the special characters used for each key stroke. However, in preparing FontPrinter for publication in REALbasic University, I quickly realized that it wouldn't work to display special characters as text in a web browser.

So instead I've prepared a special resource file which contains the special character text strings. It looks like this in ResEdit:

Download the file here. Put it in your "Linked Resources" folder and drag it into your project window.

Then create a new method within globalsModule (Edit menu, "New Method"). Call it "init" (there are no parameters) and give it this code:

  
dim i as integer
dim res as resourceFork

res = app.resourceFork

if res <> nil then
for i = 1 to 4
gTheString(i) = res.GetResource("TEXT", 999 + i)
next
end if

All this does is read the resource fork of the FontPrinter application and load those each of those four strings into the gTheString array. Later, our print routine will use that string to print the characters in the appropriate font.

For now, we've got one more step: go to the Open event of Window1 and insert:

  
init

That will execute (call) init when FontPrinter first runs. We only need to run it once, because gTheString is a global property, so once it's filled with the appropriate text characters, it will stay filled.

Well, that's it for this lesson. In our next lesson we'll learn about printing in REALbasic.

If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.

Next Week

We learn to print!

Letters

Now we've got a letter from Todd, who's got a question regarding control arrays.

(If you don't remember from previous lessons, a control array is an array of a control. In other words, it's an array -- a(1), a(2), a(3), etc. -- but each index doesn't contain a string or integer, but an instance of a control [an editField, staticText, checkBox, pushButton, etc.]. It's useful for manipulating a lot of controls programmatically. For instance, in RBU Pyramid, we used a control array to programmatically create and manipulate the playing cards which were subclasses of the canvas control.)

Hi Marc,

Before discovering REALbasic and your great site, the most complicated thing that I have ever programmed was a VCR. Now I feel like I am finally on the road to actually making software that I've always wanted, but was too specifically suited to my needs to ever be commercially available from other sources.

I have an idea for a project I would like to work on, where interface element controls would be placed on or removed from a window dynamically. I have discovered the use of control arrays might be a step in the right direction but I have some questions about their use. For instance, I tried to use "ubound" to determine how many copies of a control I may have open on an active window, but REALbasic complained that, for example, "editField()" was not an array, even though I have editField(0), editField(1), editField(2), etc... in use. Is their any way to use "ubound" on a control array to determine how many instances of that control exist?

I also would would like to know about the following. How does one go about adding a new control into a control array and placing it on to a spot on a window programatically, without having to place each one with the Interface Editor? Specifically, I am look at dynamically creating and placing editFields into a window.

I hope you can answer my questions. It would certainly streamline my code if I could do these things.

Todd Janiak
Cadillac, MI

Excellent questions, Todd!

The short answer is "no" -- you cannot use uBound on a control. However, that's not such a big deal. There are two ways to create a control array: within the IDE by dragging controls to a window and giving them an index, like this (which has an index of 0):

Or you can do it programmatically, by duplicating an existing instance of a control via code.

When you do it within the IDE, you already know how many items you've created, so uBound isn't needed. When you do it programmatically, you can simply keep track of how many you've created. The simplest way is to put them in an array (either global or window-specific).

For example, here's a little program I wrote to demonstrate this. Our window contains pushButton1, which has this code in the Action event, and a single staticText item which we will duplicate (its index is set to zero, so it's a control array and it is named staticTextArray). Within window1 we've defined s(10) as staticText as a property.

  
dim i, x as integer

x = me.top + me.height + 8
for i = 1 to 10
s(i) = new staticTextArray
s(i).top = x
s(i).left = me.left
s(i).text = "This is static # " + str(i)
x = x + s(i).height + 8
next // i

As you can see, when you push the pushButton, we generate 10 copies of the staticText control. Each time we call new staticTextArray a new instance of the control is created and a reference stored inside the s() array. That allows us to manipulate it later: we can move and position it where we want, and change the text it displays.

Since we've got the controls in our own array, we can easily use uBound to discover the size. Here's code I put within the mouseDown event of the staticTextArray object:

  
msgBox "Control # " + str(index) + " out of " + str(uBound(s))

When you click on any of the staticText controls, it will display a dialog with the number of the control and the total number of controls.

(Instead of doing it this way, an alternative would be to create a special counter variable which you could increment every time you create a new control: gNumControls = gNumControls + 1.)

Of course I used staticText controls in this example, but this would work for any control: editFields, canvases, etc. All you have to do is modify the source object (the one you copy from) and the control array property.

If you'd like the complete project file for this example, you can grab it here.


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband