| |||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||
Print This Article REALbasic University: Column 057
SimplePaint: Part IVOur children's painting program is progressing nicely, but there's one very important feature we need to implement to make it worth using: the ability to save pictures.
Saving PicturesSince the design philosophy behind SimplePaint is that there should be no confusing "file save" dialogs, we've got to come up with a simple way to save pictures. The method I chose is for each picture to be saved with a default name to a default folder. The tradeoff is the user doesn't get to choose the name of the picture or where it is saved, but the benefit is simplicity and no "file save" dialog. Saving pictures isn't difficult, but it will require several pieces of code. First, open your SimplePaint project and open the Code Editor of paintWindow (double-click on the open paintWindow). In the KeyDown event, add this code (it doesn't especially matter where as long as it's not within another if-then segment):
All this does is call the method savePict if the user presses the "S" key. (Note that though we're using an uppercase "S" for key detection, because REALbasic isn't case sensitive by default, this will work for either "s" or "S.") Now we need to create that method. On the Edit menu, choose "New Method" and call it savePict (leave the parameters and return fields blank). The way our save routine will work is this: we'll store saved pictures in same folder as the SimplePaint application. We'll just number the pictures so each will have a unique name. But sharp readers will notice a problem with that system. It works fine during a single session. However, once a few pictures have been saved and the program is relaunched, the counting begins at one, and there's already a "Picture 1" on the disk! Our new picture would overwrite the old one, which would be incredibly rude. So somehow we must make sure we don't save the new picture on top of an old one. The trick is to find the highest numbered picture on the disk. Adding one to that number will give us our new picture number. Here's how that routine works. Create a new method called getNumber and have it return an integer. Here's what the code looks like:
As you can see, this is remarkably simple. All we do is increment a value, i, by one, and keep checking to see if a file named "Picture " + i exists or not. If it does, we keep adding one to i. If "Picture i" doesn't exist, we know it's okay to save a new picture with that name, so we return the value of i! Now go back to savePict and put in this code:
This creates a new folderItem within our default folder (getFolderItem("") returns the folder of your application). The folderItem's name is "Picture " plus a number -- the one calculated by our getNumber method. To save the picture, we use our folderItem's saveAsPicture method, passing it p, our drawing. That's it!
Getting Rid of a Dialog BoxYou may notice that our save routine displays a dialog box. It's just a message box, confirming the save, but for young users, that can be confusing. They won't notice the modal dialog and won't be able to figure out why they can't draw any more. So how do we tell the user the picture's saved without a dialog? A mere beep could indicate an error, not success. There's a simple solution right within REALbasic's own online Help! Bring up REALbasic's online help and type "speech" as the search term. Here's what comes up (you'll probably have to scroll a bit to see this code as it's not at the top of the help window): ![]() Now create a new method like this: ![]() To do speech, I just dragged in the code from RB's help window (code with a dotted border can be dragged into the Code Editor to add it) and modified it. This code uses a declare statement to access the Mac OS's built-in speech routines (which are not accessible via a standard REALbasic command). Once we've declared a routine, we can call it like any other REALbasic routine. REALbasic just passes our command on to the operating system. Because system commands are not available for all platforms, we therefore must check the platform before making the OS call. We do that with the conditional compilation commands, #if-#endif, and REALbasic's special "target boolean" values, targetMacOS and targetCarbon, which return true if we're running Mac OS or Carbon (Mac OS X). (Note that because Carbon apps can run under Mac OS, there's no way to tell if your app is really running Mac OS X -- all you can tell is if you're running under Carbon.) Unfortunately, the online help code doesn't work under Mac OS X (it causes the application to quit). At first I wondered if speech was supported under Carbon, but a quick check on Apple's developer's website showed that the SpeakString command is supported under Carbon. To make it work, I therefore set up a targetCarbon version of the function replacing "SpeechLib" with "CarbonLib" -- and it worked! (Note that not all Carbon commands are as easily translated. Sometimes the Carbon commands have new names or different parameters from their Mac OS equivalents, which can get complicated to translate. If you don't know what you're doing with declares, it's best not to mess with them unless you enjoy watching your computer crash.) Here's the finished routine:
If the speech is successful (available), we return true, otherwise false (which would be the case if the user didn't have an operating system capable of speech).
Now we just need to make some minor changes to our savePict method so instead of displaying a dialog we speak a message to the user:
Note that if speech isn't installed, the routine will display the confirmation dialog as before.
Erasing the ScreenWe've now given SimplePaint the ability to save pictures, but what happens after that? Usually the child will want to start a new picture -- we need a way to let the child erase the screen. Go to the KeyDown event of paintWindow and insert in this:
This just checks to see if the user pressed the Delete key (ASCII 8) and if so, clears the picture with the clearRect method and refreshes the screen. Easy!
Adding an EraserIt's usually easier to tell children to simply use white to erase, but we'll go ahead and add an erase keyboard command. All it does it change the current color to white. In paintWindow's KeyDown event add this:
Now pressing "E" switches the color to white so you can erase. That's it for today. Next time we'll add some more features like changing the mouse cursor and some sounds. If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
Next WeekMore SimplePaint polishing. LettersOur letter this week is from David in Arizona. He writes: Hello Marc, Hi David! The simplest solution for your situation is to just to refer to the properties of the other windows as properties of other windows. That sounds way more complicated than it is. Just put the window name in front of the property name, separated by a period. For example, to delete all the rows of a listBox on window2, put: window2.listBox.deleteAllRows You can refer to any object or property of another window simply by putting the window's name in front of it (followed by a period). These are all valid:
The other approach is to use global variables -- add properties to a module and they're accessible by all windows and methods. But that could be more complicated since you'd have to store the stuff from the one window into global properties, then access the globals from the other window. Just accessing another window's data directly is simpler.
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 See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
| |||||||||||||||||||||||||||||