TweetFollow Us on Twitter

Beginning Windows
Volume Number:2
Issue Number:7
Column Tag:ABC's of C

Beginning Windows

By Bob Gordon, Apropos Publication Services, Contributing Editor

Probably the most visible part of the Macintosh user interface is the window. Since we can't build much of an application without showing something on the screen, we will begin to examine how to use the Macintosh Window Manager. At the same time, we'll take a look at the C preprocessor, the if-statement, and review the topics from last month-the Event Manager, structures, and the case statement.

Preprocess Your Code

The C preprocessor provides a variety of useful services. We saw last month how to use the #define to provide a shorthand name by which to refer to a structure. These 'define' statements and other data structures can be stored in a seperate ".h" file and included into our source code at compile time. We can create our own new ".h" file to reduce some of C's more arcane symbols. We will call this file "abc.h".

/* abc.h 
 *
 * Local definitions to improve readability
 *
 */
 
#define True1
#define False  0
#define Nil 0
#define and &&
#define or||
#define not !
#define equals ==
#define notequal !=

extern char *PtoCstr(); /* from stdio.h  */
extern char *CtoPstr();

The first three definitions provide some standard constants. C has no boolean type, but it is a good idea to use labeled constants rather than numbers when doing logic. It makes the code easier to follow. "Nil" is used with pointers. Assign a pointer Nil when you don't want it to point anywhere. C guarantees that a pointer can never point to zero, so this is a safe initialization value.

We then have replacements for the logical operation symbols. Admittedly, these take longer to type, but they are much easier to read (they are especially helpful if you must show your code to someone who doesn't use C), and they are safer. A very popular C bug is to leave one of the equal signs out of the equality operator (see top of next column):

 if (a = b)
    code;

instead of

 if (a == b)
    code;

The first is a perfectly legal C if-statement: it assigns the value of b to a, then if a is non-zero, the code is executed. The second executes the code only if the value of a equals the value of b. The cleverness of this bug is that not only is it legal, but many times it is what you want to do. Using "equals" instead of "==" makes it much less likely to change the meaning of a line by a typo, and it makes it much easier to find.

The last two entries are the Pascal-to-C and C-to-Pascal string conversion utilities. These are normally defined in the stdio.h file, but since we are not including that file, we can put them here. Remember, C and Pascal strings are different, so if we send a string to a Toolbox routine, it must be a Pascal string. These are the functions that Mac C has. Other compilers may have similar functions (Aztec C calls these ctop() and ptoc()) or they will do the conversion automatically. Check your documentation and place the appropriate functions in abc.h so you can use them without repeating the external declarations in every source file.

To use abc.h, just have it as one of the include files at the begining of a source file. All the definitions will then be available. We may add other definitions later.

By the way, the May 1986 Byte has an article called "Easy C" that describes a considerably expanded set of preproccessor definitions. The authors replace many of the standard C terms with new ones in an effort to increase readability and reduce errors.

Fig. 1 Program output, window highlited.

if-then-else

There are several if-statements in the sample program. The if-statement is C's other branching construct. Its general form is:

if (expression)
 statement;

if (expression)
 statement;
else    /* shows optional else clause */
 statement;

If the experession evaluates to a non-zero value, the statement is executed. If the expression evaluates to zero and an else is present, the statement following the else is executed. If no else is present, execution continues after the if.

If-statements may be nested, but the relation of else to if may be ambigous:

 if (expression)
 if (another expression)
 statement;
 else
 statement;

Does the else go with the first if or the second? The layout on the page says it will go with the first, but the compiler will place it with the second as it is closer. Use braces to clear up ambiguities:

 if (expression)
 {
 if (another expression)
 statement;
 }
 else
 statement;

Fig. 2 Mouse click outside the window

Fig. 3. Cmd T changes title name

Structures, Functions, and Pointers

The only other C issue we need to deal with is how to get structures in and out of functions. The original definition of C did not allow functions to receive structures as parameters or return them (the new ANSI standard does allow this, check your compiler). A function could, however, receive or return a pointer to a structure. In C a pointer is simply an address, and you can get the address of a variable with the address operator (the ampersand). In the example, theEvent is an EventRecord structure to get the next event from the Event Manager; the pointer (or address) to the EventRecord is specified as &theEvent:

 GetNextEvent(everyEvent,&theEvent);

This passes the address of theEvent to GetNextEvent, by specifying it as &theEvent. This works well with all C compilers, but it does not work in all cases with Toolbox functions. The problem is that Pascal allows structures (records) to be passed as parameters, as well as by address. On the Mac, only structures of four or fewer bytes are passed as parameters; longer structures are passed by address. There is one structure of four bytes, the Point, which we saw last month. Mac C handles this automatically. They define the Point as one of the argument types that can be passed to Toolbox routines. If you are using Mac C, pass the address of the Point. Aztec C, on the other hand, uses a special function, pass() to pass points, as shown below:

FindWindow(pass(er.where), &whichWindow); /*aztec */

Finally, since structures are often used with pointers, C has a special operator to access a member of a structure given a pointer to the structure. If er is an EventRecord and erp is a pointer to an Event Record, the what field is accessed by:

 er.what/* the what member */
 erp->what/* the what member */
 (*erp).what/* the what member */

The last example shows the indirection operator (the asterisk). It yields the value at the address contained in the variable. The structure pointer operator (->) is much easier to read.

Putting a Window on the Screen

The example program this month puts a window on the screen, changes its title, and responds to certain mouse commands. The program deals with only one window and does not include the change size command as multiple windows and changing the size involves accessing the Memory Manager. We'll add these features after we cover it.

The program consists of five routines:

main()

Does initialization and calls the main event loop routine. InitWindows() must be done if you want to use any of the Window Manager routines. See what happens if you do not InitCursor(). The dragbounds rectangle limits the range of DragWindow(): it ensures the window does not fall off the screen. Note that I used the preprocessor to define Screen. This was done simply to avoid typing QD->screenBits.bounds. If we find we need to use QD->screenBits.bounds a lot, we can add it to abc.h.

dowindow()

The dowindow() routine creates a new window on the desktop. As such, it is primarily a call to the toolbox trap NewWindow(), which returns a window pointer to the newly created window structure.

There are several potential trouble spots in NewWindow(). First, the window record (windowRec) must be static. I made it a global. Notice the use of the string conversion routines. See what happens if you don't convert the string back. The parameter, (WindowPtr)-1, is the behind parameter. We wish to place our new window in front of all other windows. To do this we must set the pointer to -1. The construct (WindowPtr) casts the -1 into the type WindowPtr. I expect there would be a serious problem if you left the (WindowPtr) out. Try it. Parameter conversion in C is called 'casting'. By enclosing a parameter type such as WindowPtr in parenthesis, followed by a variable, that variable, in this case, -1, is converted into the same parameter type, in this case a four byte address. Hence, (WindowPtr)-1 is just a fancy way of defining -1 as a long int. Finally, the last parameter is refCon, a value passed to the Window Manager for the application's own use. I'm just passing a zero because I don't have anything to do with it at this time. refCon, though is a long. Mac C seems to pass this correctly, but other compilers may require the value to be explicitly a long. This is another case where things that look correct will not work correctly. To make a constant explictly a long, place an "L" after it (0L).

eventloop()

This is similar to last month's program. Here the EventRecord is local to eventloop(). I only wanted to check the keyDown and mouseDown events so I could have changed the event mask. You might rewrite it that way. If you are reading along in Using the Macintosh Toolbox in C, you will notice that they have this program as one function. I try to keep things fairly small.

dokey()

Here we respond to all the keyDown events. Most of the toolbox routines are fairly straight forward. Each window function receives a window pointer as a parameter. What we are checking for is our menu of command keys. Assuming we have a window opened, then our dokey() routine defines the command keys we will respond to:

Key Function

cmd m make a window ( call dowindow() )

cmd x kill the window (close it)

cmd s show a hidden window

cmd h hide a shown window

cmd t change the window's title

cmd q quit by returning to the finder

We get the keyboard character by extracting it from the message portion of our event record and masking it with a mask that guarantees we only get command key sequences. Then we extract the ascii value of the key sans command key, and check it against the above table of allowed keystrokes. We check for the m key first so we can make a new window if one does not already exist. After that, our switch construct can list each of our key commands knowing that a valid window is present.

domouse()

domouse handles the mouseDown events. First it must determine where the mouse is. The function FindWindow() does this and returns a window code and a pointer to the relevant window. Note the use of the address operator to pass the Point where member. Most of the window functions here are straight forward. TrackGoAway() retains control as long as the mouse button is down and lights the go-away box if the mouse pointer is in it.

Note that I am always calling DrawGrowIcon() after each Window Manager call. This is not really necessary because we're not doing anything with the grow box. Try taking it out.

Final Notes

We've only touched on part of the Window Manager functions. Some will wait until we've covered memory management, others until we've covered resources. Placing things like window definitions inside resource files helps structure the program and makes the user interface components easier to modify and port to different languages (human, not computer). Since this column is about C, I'm going to avoid using resources so we can use the C functions as much as possible. Also, resources present an extra step in getting a program to run, and while we're learning how to do things, we don't need the extra steps. To learn more about resources, read Joel West's "Resource Roundup" series.

Next month we'll move to menus. Rather than use the program in Using the Macintosh Toolbox with C, I will add menus to this one. Now all we have to do is figure out something interesting to put in our windows. Suggestions are welcome.

/* window manager demonstration 
 * base on program in 
 * Using Macintosh Toolbox with C
 * page 70
 */
 
 /* Here are our include files */
 
 #include "abc.h"/* Our own defines */
 #include "Events.h" /* also includes Macdefs.h */
 #include "Window.h" /* also includes Quickdraw.h, which 
 in turn requires M68KLIB.D  */
 
 /* Here are our defines */
 
 #defineScreen   QD->screenBits.bounds
 #definecharCodeMask 0x000000FF
 
 /* Here are our Global variables */
 
 WindowPtrtheWindow;
 WindowRecord  windowRec;
 Rect   dragbound;
 Rect   limitRect;
 
main()
{
 InitWindows();
 InitCursor();
 FlushEvents(everyEvent);
 
 /* Initialize our global variables */
 
 theWindow = Nil;/*indicates no window */
 SetRect(&dragbound,
 Screen.left + 4,
 Screen.top + 24,
      Screen.right - 4,
 Screen.bottom - 4);
 SetRect(&limitRect,60,40,
 Screen.right - Screen.left - 4,
 Screen.bottom - Screen.top - 24);
 
 dowindow();/* make new window */  
 eventloop();    /* check for events */
}

dowindow()
{
char    *title;  /* first title for window */
Rect    boundsRect;
 
if (not theWindow) /* if no window exists, make one */
 {
 title = "ABC Window";
 SetRect(&boundsRect,50,50,300,150);
 theWindow = NewWindow(windowRec, &boundsRect, CtoPstr(title),True,documentProc, 
(WindowPtr) -1, True, 0);
 DrawGrowIcon(theWindow);
 PtoCstr(title);
 }
}

eventloop()
{
EventRecord theEvent;

while(True)
 if (GetNextEvent(everyEvent,&theEvent))
 switch(theEvent.what)    
 { 
 case keyDown:   
 dokey(&theEvent); /* check key, */
 break;
 case mouseDown:
 domouse(&theEvent); /* mouse down evts */
 break;
 default:
 break;
 }
}

dokey(er)
 EventRecord*er;
{
 char   c;/* character from message */
 char   *title2; /* second title for window */
 
 if (not(er->modifiers & cmdKey))  
 return;/* only pay attention to cmd keys */
 /* extract character, lower 8 bits */
 c = er->message & charCodeMask; 
 if (c equals 'q' or c equals 'Q') /* 'q' quits program */
 ExitToShell();  
 
 if (not theWindow)
 {
 if (c equals 'm' or c equals 'M')
 {
 dowindow();
 return;
 }
 else
 {
 SysBeep(1);
 return;
 }
 }
 /* Have a window, so try commands */
 switch (c)
 {
 case 'x':
 case 'X':
 CloseWindow(theWindow);
 theWindow = Nil;
 break;
 case 's':
 case 'S':
 ShowWindow(theWindow);
 DrawGrowIcon(theWindow);
 break;
 case 'h':
 case 'H':
 HideWindow(theWindow);
 break;
 case 't':
 case 'T':
 title2 = "A Different Title";
 SetWTitle(theWindow, CtoPstr(title2));
 PtoCstr(title2);
 break;
 default:
 SysBeep(1);
 break;
 }
}

domouse(er)
 EventRecord*er;
{
 short  windowcode;
 WindowPtrwhichWindow;
 short  ingo;
 long   size;
 
 windowcode = FindWindow(&er->where, &whichWindow);
 switch (windowcode)
 {
 case inDesk:
 if (theWindow notequal 0)
 {
 HiliteWindow(theWindow, False);
 DrawGrowIcon(theWindow);
 }
 else
 ExitToShell();  /* exit if no window */
 break;
 case inMenuBar:
 SysBeep(1);
 break;
 case inSysWindow:
 SysBeep(1);
 break;
 case inContent:
 HiliteWindow(whichWindow,True);
 DrawGrowIcon(theWindow);
 break;
 case inDrag:
 DragWindow(whichWindow, &er->where, &dragbound);
 DrawGrowIcon(theWindow);
 break;
 case inGrow:
 /* not included this month */
 break;
 case inGoAway:
 ingo = TrackGoAway(whichWindow, &er->where);
 if (ingo)
 {
 CloseWindow(whichWindow);
 theWindow = Nil;
 }
 break;
 }
}

Why Did They Do it Dept.?

Here is another little oops for Apple's new Mac Plus. It seems on the old ROMS, if you held down a menu item with the mouse and then did a cmd-shift-3 to take a paint snapshot, when you released the mouse, the menu remained down while the screen was captured in a paint document. This became a great feature because it allowed you to document your menu bar selections. In the new ROMs, this feature no longer works. When you release the mouse, the menu snaps up and then the screen is captured. The result is that there is no way to document your menu bar selections anymore. Boo! MacTutor will pay $250 for the best article that provides a convenient patch for Apple's blunder.

 
AAPL
$119.00
Apple Inc.
+1.40
MSFT
$47.75
Microsoft Corpora
+0.28
GOOG
$540.37
Google Inc.
-0.71

MacTech Search:
Community Search:

Software Updates via MacUpdate

Skype 7.2.0.412 - Voice-over-internet ph...
Skype allows you to talk to friends, family and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
HoudahSpot 3.9.6 - Advanced file search...
HoudahSpot is a powerful file search tool built upon MacOS X Spotlight. Spotlight unleashed Create detailed queries to locate the exact file you need Narrow down searches. Zero in on files Save... Read more
RapidWeaver 6.0.3 - Create template-base...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
iPhoto Library Manager 4.1.10 - Manage m...
iPhoto Library Manager lets you organize your photos into multiple iPhoto libraries. Separate your high school and college photos from your latest summer vacation pictures. Or keep some photo... Read more
iExplorer 3.5.1.9 - View and transfer al...
iExplorer is an iPhone browser for Mac lets you view the files on your iOS device. By using a drag and drop interface, you can quickly copy files and folders between your Mac and your iPhone or... Read more
MacUpdate Desktop 6.0.3 - Discover and i...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
SteerMouse 4.2.2 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. It also supports Apple Mighty Mouse very well. SteerMouse can assign various functions to buttons that Apple's software does not allow,... Read more
iMazing 1.1 - Complete iOS device manage...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more
PopChar X 7.0 - Floating window shows av...
PopChar X helps you get the most out of your font collection. With its crystal-clear interface, PopChar X provides a frustration-free way to access any font's special characters. Expanded... Read more
OneNote 15.4 - Free digital notebook fro...
OneNote is your very own digital notebook. With OneNote, you can capture that flash of genius, that moment of inspiration, or that list of errands that's too important to forget. Whether you're at... Read more

Latest Forum Discussions

See All

Lucha Amigos (Games)
Lucha Amigos 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Forget Ninja Turtles, and meet Wrestlers Turtles! Crazier, Spicier and…Bouncier! Sling carapaces of 7 Luchadores to knock all... | Read more »
Raby (Games)
Raby 1.0.3 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.3 (iTunes) Description: ***WARNING - Raby runs on: iPhone 5, iPhone 5C, iPhone 5S, iPhone 6, iPhone 6 Plus, iPad Mini Retina, iPad Mini 3, iPad 4, iPad Air,... | Read more »
Oddworld: Stranger's Wrath (Games)
Oddworld: Stranger's Wrath 1.0 Device: iOS Universal Category: Games Price: $5.99, Version: 1.0 (iTunes) Description: ** PLEASE NOTE: Oddworld Stranger's Wrath requires at least an iPhone 4S, iPad 2, iPad Mini or iPod Touch 5th gen... | Read more »
Bounce On Back (Games)
Bounce On Back 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: | Read more »
Dwelp (Games)
Dwelp 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: === 50% off for a limited time, to celebrate release === Dwelp is an elegant little puzzler with a brand new game mechanic. To complete a... | Read more »
Make Way for Fat Chicken, from the Maker...
Make Way for Fat Chicken, from the Makers of Scrap Squad Posted by Jessica Fisher on November 26th, 2014 [ permalink ] Relevant Games has announced they will be releasing their reverse tower defense game, | Read more »
Tripnary Review
Tripnary Review By Jennifer Allen on November 26th, 2014 Our Rating: :: TRAVEL BUCKET LISTiPhone App - Designed for the iPhone, compatible with the iPad Want to create a travel bucket list? Tripnary is a fun way to do exactly that... | Read more »
Ossian Studios’ RPG, The Shadow Sun, is...
Ossian Studios’ RPG, The Shadow Sun, is Now Available for $4.99 Posted by Jessica Fisher on November 26th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Mmmm, Tasty – Having the Angry Birds for...
The very first Angry Birds debuted on iOS back in 2009. When you sit back and tally up the number of Angry Birds games out there and the impact they’ve had on pop culture as a whole, you just need to ask yourself: “How would the birds taste... | Read more »
Rescue Quest Review
Rescue Quest Review By Jennifer Allen on November 26th, 2014 Our Rating: :: PATH BASED MATCH-3Universal App - Designed for iPhone and iPad Guide a wizard to safety by matching gems. Rescue Quest might not be an entirely original... | Read more »

Price Scanner via MacPrices.net

Black Friday: 15% off iTunes Gift Cards
Staples is offering 15% off $50 and $100 iTunes Gift Cards on their online store as part of their Black Friday sale. Click here for more information. Shipping is free. Best Buy is offering $100... Read more
BEVL Releases Dock Tailored for iPhone 6 and...
Seattle based BEVL has released their first product: an iPhone dock that is divergent in build quality, rock-solid function and visual simplicity to complement the iPhone. BEVL is now accepting... Read more
Black Friday: $150 off 13-inch Retina MacBook...
 Best Buy has 13-inch 2.6GHz Retina MacBook Pros on sale for $150 off MSRP on their online store as part of their Black Friday sale. Choose free shipping or free local store pickup (if available).... Read more
Black Friday: $300 off 15-inch Retina MacBook...
 B&H Photo has the new 2014 15″ Retina MacBook Pros on sale for $300 off MSRP as part of their Black Friday sale. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina... Read more
Black Friday: Up to $140 off MacBook Airs, fr...
 B&H Photo has 2014 MacBook Airs on sale for up to $140 off MSRP as part of their Black Friday sale. Shipping is free, and B&H charges NY sales tax only: - 11″ 128GB MacBook Air: $799 $100... Read more
Black Friday: 13-inch 2.5GHz MacBook Pro on s...
 Best Buy has the 13″ 2.5GHz MacBook Pro on sale for $899.99 on their online store as part of their Black Friday sale. Choose free shipping or free instant local store pickup (if available). Their... Read more
Black Friday: 21-inch 1.4GHz iMac on sale for...
 Best Buy has the 21″ 1.4GHz iMac on sale for $899.99 on their online store as part of their Black Friday sale. Their price is $200 off MSRP. Choose free shipping or free local store pick up. Price... Read more
Black Friday iPad Air 2 sale prices, $100 off...
 Best Buy has iPad Air 2s on sale for $100 off MSRP on their online store for Black Friday. Choose free shipping or free local store pickup (if available). Sale prices available for online orders... Read more
2014 1.4GHz Mac mini on sale for $449, save $...
 B&H Photo has the new 1.4GHz Mac mini on sale for $449.99 including free shipping plus NY tax only. Their price is $50 off MSRP, and it’s the lowest price available for this new model. Adorama... Read more
Early Black Friday pricing on 27-inch 5K iMac...
 B&H Photo continues to offer Black Friday sale prices on the 27″ 3.5GHz 5K iMac, in stock today and on sale for $2299 including free shipping plus NY sales tax only. Their price is $200 off MSRP... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.