#!/usr/bin/perl -w # # Copyright 2000 by Michael Coyle # Released under GPL. # # Call it with: # [an error occurred while processing this directive] # # Get the file name from the browser... $file_name = $ENV{'QUERY_STRING'}; # Open the file... open (EP, $file_name); # Print to the browser... print "Content-Type: text/html \n\n"; # Load the file and keep spitting it out to the browser... while () { chomp; print "$_ "; } # Close the file and go home... close EP #!/usr/bin/perl -w # # Copyright 2000 by Michael Coyle # Released under GPL. # # Call it with: # [an error occurred while processing this directive] # # Get the file name from the browser... $file_name = $ENV{'QUERY_STRING'}; # Open the file... open (EP, $file_name); # Print to the browser... print "Content-Type: text/html \n\n"; # Load the file and keep spitting it out to the browser... while () { chomp; print "$_ "; } # Close the file and go home... close EP

3D
3D Photo Gallery (Part 1)
3D Photo Gallery (Part 2)

Audio
Poor Man's MIDI
Make A Metronome
iPod Tricks (Part 1)
iPod Tricks (Part 2)
iPod Tricks (Part 3)
Laugh Track Machine
Audio Player with Reverb
Shepard Melody
RB Phone Home
Build a Drum Machine

Custom Controls and Windows
Double Click Listbox
Draggable Metal Window
Double Click Canvas
Custom Buttons
Custom Buttons Part II
iTunes-style Listboxes
Custom Controls


General RB
Scrolling Windows
Using Mesage Dialogs
Case-Sensitive Word Finder
Introduction to Stacks
Wiggle Window
JPEG in PDF
Listbox Checkboxes
Background Applications
Listbox Auto-Find
Virtual Volumes
Time Tracker
Software Distribution (Part 1)
Software Distribution (Part 2)
Software Distribution (Part 3)
Software Distribution (Part 4)
Exceptions
Tips and Tricks
Text Clippings Made Easy

Graphics
Drawing a Simple Gradient
The SpriteSurface: Space Game
Image Spinner
Cropping Graphics (Part 1)
Cropping Graphics (Part 2)
Cropping Graphics (Part 3)
Cropping Graphics (Part 4)
Shimmer Graphics
Lissajous Figures
Simple Screen Capture
Vector Graphics
Kaleidoscope Images
Stegonography
Spirals!
Image Table
RB Magnifying Lens
Screen Capture
Color Picker Tutorial

Hacks
Ghost Grab
Speedy Mouse Extension
iTunes Plugins
iTunes Skinner

Mac OS X
Global Hot Key Event (Carbon Events)
Login Welcomer (Carbon Events)
Add/Remove Buttons
Resizable Sheets
Mac OS X Preferences Window
Using Sheets in REALbasic
Build a Bundle (Part 1)
Build a Bundle (Part 2)
Dock Your Passwords
Mac OS X Debugging
REALbasic Mac OS X Icon Tutorial
Animate Your Dock
RB and the Command Line

Menus
Window Menu
Templates Menu
Listbox Menu

Novelty
Guessing Game
Calendar Trivia
Tile Mixer
Zip Code Finder
Happy Valentine's Day
Merlin Simulator (Part 1)
Merlin Simulator (Part 2)
Merlin Simulator (Part 3)
Buzzword Machine
AppleSoft BASIC

Printing
Print to PDF

Registration
Registration Code Validation
Network Registration Codes

Resources
Picture Extractor (Part 1)
Picture Extractor (Part 2)

Serial
Caller ID (Part 1)
Caller ID (Part 2)
Caller ID (Part 3)

Speech
Speech Recognition

Socket Communication
Easy Peer-to-Peer File Sharing
MacPAD Version Checking
Display Web Image In Canvas
HTML IMG Tags
Version Tracking
Even Smarter Instant Messaging
Web Tiler
JavaScript and REALbasic
Stock Ticker (Part I)
Stock Ticker (Part 2)
AIM Mate

XML Manipulation
Simple XML Introduction

Video
Big Brother Video Capture

Note: All articles without a byline were written by Erick Tejkowski. When cleaning the site I removed them because the code differed from page to page, and I have yet to put them back in.

resexc2.gif (20k)




REALbasic for Dummies
by Erick Tejkowski

$19.99 @ Amazon





Files are in Stuffit 6.5 or earlier, or ZIP format.
Download Stuffit Expander

Tell us about a bad link.

Login Welcomer by Seth Willits
04-24-04




Carbon Events and RB 5.5
There are two event models that exist in Mac OS X. There is the old "classic" model which involved polling for events and giving time to background applications, and there's the new Carbon event model where you install callbacks so that you're told when a specific event occurs. The new Carbon model not only is the preferred method by Apple, it's also a good idea for the developer to use since it opens you up to being notified of events you wouldn't be aware of otherwise.

In the past, if a RB developer wanted to use a Carbon Event REALbasic didn't give to use (like, the toolbar button's event in OS X), we'd have to resort to a plugin and write Carbon code directly. Now, in 5.5 there is a new "AddressOf" feature which allows you to pass the address of a method in REALbasic to any function as a callback parameter/function pointer. In other words, this allows us to use Declare statements to setup a Carbon Event callback in pure REALbasic code. No plugins necessary.

The Login Welcomer Tutorial
To introduce you to using AddressOf and the Carbon Event system, we're going to create a very simple example which, when you switch between users (via fast user switching in Panther), says "Welcome" and "Goodbye." True, it may not be exciting, but it's a simple example to teach you a powerful tool.

Installing an Event Handler
Ok, now to be notified of an event, you first need to install a Carbon Event Handler. This tells the operating system "Hey, notifiy me when this event happens by calling this function." However, there are times when we could register for a certain event, like a mouse click, but only want to be notified when the mouse clicked within this window, or within this control, rather than be notified EVERY time the mouse clicked. The solution to this is the "target" of the event handler. For example, we would install an event handler that notifies of mouse clicks only in the XYZ window, which would be the "target" of the events. In this tutorial, the target of our evens will be the application. (There's the application target, windows, and controls if you were wondering.)

We're going to need a place to put the code to install the handler, so create a new module; I've named mine LoginStatus, but name yours UncleBen for all I care. Next, we'll need to define some constants that will help keep things clear. Add these constants to the module:

  • Carbon as String: Value for Mac Carbon (PEF) is "CarbonLib", and Mach-O is "Carbon"
  • kEventClassSystem as String: "macs"
  • kEventSystemUserSessionActivated as Integer: 10
  • kEventSystemUserSessionDeactivated as Integer: 11
  • noErr as Integer: 0

The first part of the method we'll use to install the handler involves the Declares. The three Declares we need are InstallEventHandler, GetApplicationEventTarget, and NewEventHandlerUPP. They are as follows:


Sub InitLoginNotification()
   Declare Function InstallEventHandler Lib Carbon (eventTarget as integer, handler as Ptr, numTypes as integer, types as ptr, userdata as integer, handlerRef as integer) as Integer
   Declare Function GetApplicationEventTarget Lib Carbon () as Integer
   Declare Function NewEventHandlerUPP Lib Carbon (address as Ptr) as Ptr

InstallEventHandler obvioiusly installs the event handler, GetApplicationEventTarget returns a pointer to the application event target for the application (don't confuse this with the "App" object in REALbasic, this is totally different), and NewEventHandlerUPP takes a pointer to a method/function and returns a a different specialized pointer after turning it into a "event handler procedure." How that really works isn't important at all. What you do need to know however, is the parameters to InstallEventHandler.

The first parameter is a pointer to the target for the handler. This is the value returned by GetApplicationEventTarget. The second parameter is a pointer to the actual event handler which is the value returned by NewEventHandlerUPP. The third is the number of events we're looking to be notified of via the handler, and parameter four is a block of memory which details which events they are. The userdata parameter is anything you want it to be. You can pass any value for this parameter, and when the handler is called, it is supplied back to you. This is typically used to help you identify what you were installing the event handler on, but we won't use it because we don't need to.

Anyway, the very last parameter is a pointer to the handler (you pass in a pointer and when the function returns, the pointer is set to the address of the handler). The only time you really need this is when you want to uninstall the eventhandler which we won't need to do since it's "done for us" by the system as it reclaims memory when the application quits.



   dim err, eventRef as integer
   dim eventType as MemoryBlock
   dim attributes as integer
   
   // Event Types List
   eventType = NewMemoryBlock(8)
   eventType.StringValue(0, 4) = kEventClassSystem
   eventType.Long(4) = kEventSystemUserSessionActivated

An EventTypeSpec is an 8 byte block of memory where the first 4 bytes are a 4 character string representing the class of the event, and the last 4 is an integer/long which specifies which event of that class it is. Here we just identify the event which occurs when a user logs in. Below we do the same for logging out. If there were multiple events we wanted to track simultaneously with the same handler, this block would be 8 times the number of events, and they'd just be strung up next to each other.



   // Install Event Handler
   err = InstallEventhandler(GetApplicationEventTarget(), NewEventHandlerUPP(AddressOf LoggingIn), 1, eventType, 0, 0)
   if err <> noErr then
      MsgBox "InstallEventhandler" + EndOfLine + EndOfLine + str(err)
   end if

Here is where we actually install the event handler. For the last two parameters we simply pass a constant 0 since we don't care about them. The number of events is 1 and we pass the memory block for the event as the parameter immediately following it. Now the important part is that the parameter to NewEventHandlerUPP is "AddressOf LoggingIn". LoggingIn is actually a global REALbasic method (that is, it must NOT be in a class), that also exists in the LoginStatus module. It's quite simple looking and is simply:

Sub LoggingIn()
    Speak "Welcome!"
End Sub

It's sibling, LoggingOut (which is used in the event handler below) looks like:

Sub LoggingOut()
    Speak "Goodbye"
End Sub

(Noticed we used the new "Speak" command in REALbasic 5.5?)

To use the AddressOf feature, you simply place it infront of the name of a method when passing it as a parameter. You can think of it as using ByRef but with methods instead of variables. In fact, that's exactly what it's doing in concept, it just has a different name.

Below, we simply install another event handler for logging out. Nothing special there.



   // Event Types List
   eventType = NewMemoryBlock(8)
   eventType.StringValue(0, 4) = kEventClassSystem
   eventType.Long(4) = kEventSystemUserSessionDeactivated

   
// Install Event Handler
   err = InstallEventhandler(GetApplicationEventTarget(), NewEventHandlerUPP(AddressOf LoggingOut), 1, eventType, 0, 0)
   if err <> noErr then
      MsgBox "InstallEventhandler" + EndOfLine + EndOfLine + str(err)
   end if
End Sub

The very very last step is to call InitLoginNotification() from the Open event of the application class intance "App".

Finished
Alright, now to really use this example you need Panther, but that's only because of the event I've chosen to use. So to see this example in action, turn on Fast User Switching, run the app, and switch back and forth between users. It should welcome you and bid you farewell. w00t.

Like I said, nothing fancy, but these same steps (although different event types are needed) can be used to be notified of scroll-wheel events, toolbar buttons being clicked, uhhh... windows being docked and undocked and more, which is cool and useful. So, go at it, ask some questions on the REALbasic mailing lists, and start using this in your latest Mac OS X app!

As always, you can download the project for this tutorial.






Please support ResExcellence by Visiting our Sponsors. One click makes a difference.


Download REALbasic and create your own software!

#!/usr/bin/perl -w # # Copyright 2000 by Michael Coyle # Released under GPL. # # Call it with: # [an error occurred while processing this directive] # # Get the file name from the browser... $file_name = $ENV{'QUERY_STRING'}; # Open the file... open (EP, $file_name); # Print to the browser... print "Content-Type: text/html \n\n"; # Load the file and keep spitting it out to the browser... while () { chomp; print "$_ "; } # Close the file and go home... close EP #!/usr/bin/perl -w # # Copyright 2000 by Michael Coyle # Released under GPL. # # Call it with: # [an error occurred while processing this directive] # # Get the file name from the browser... $file_name = $ENV{'QUERY_STRING'}; # Open the file... open (EP, $file_name); # Print to the browser... print "Content-Type: text/html \n\n"; # Load the file and keep spitting it out to the browser... while () { chomp; print "$_ "; } # Close the file and go home... close EP