PowerPC assembly language beginners guide.
This chapter will examine the creation of Menus, Dialog Boxes and Event Loops. It will also give a brief guide of how to use ResEdit (a utility for creating and manipulating Resources).
Overview of Chapter 6
If you can recall the last chapter, we started to create our first real Mac Application. Did you have any problems with that? Was there any mistakes in it? We stated that there would be errors in it, so did you spot them?
Did you notice that the macros start_up and tidy_up were missing?
Let us remind ourselves of these macros:
This macro saves the general purpose registers (GPRs) and sets up the stack and BSS pointer to r30.
This macro restores the GPRs and the stack.
So now lets modify the main.s file to encompass the above macros.
Now that we are up to speed, how will we go about initialising the Mac App. We need to set up a few resources; we will go through each one, step by step. We will start by a setting up a window, then we will create a menu bar (using ResEdit) and tie them in to our program. Once that it complete we will set up an events loop and finally we will set up a Dialog and Alert box to demonstrate the difference.
So to summarise
Setting up a Window
We first saw this in Chapter 5. Now we will set up the window in the init.s file. We will use the GetNewCWindow call. Remember that we need to store the pointer to the window which is returned by GetNewCWindow. So in the Chapter6_BSS.def file we will reserve space for this variable
win_ptr_1: rs.w 1
Then in init.s we create the window with the following code:
Notice the SetPort call. This tells the program that the window you have just defined is going to be made active - i.e. any drawing commands are to be carried out in this port.
So far, so good ("so what!!" I hear you cry), now that we have set up the window, let's set up the menu bar.
Setting up a Menu Bar
Setting up the menu is separated into a few different sections. Firstly we have to define the MENU resource using ResEdit (Thank you Lord for small mercies). If you have never used ResEdit or heard of it, you have led a very sheltered life, but anyway ResEdit is a Visual tool for creating Resources. Lets make a menu and see how easy it is.
If you haven't got ResEdit then you will have to Add the Chapter6_menu resources to your project. Try and get a copy of ResEdit and use it, it is a VERY important tool.
Load ResEdit. Create a New File by selecting File, New... Select a file name and place to save the file. An empty window will then open, the title bar will be the name of the file you have just created. I know this is "sucking eggs", but I have to be sure we have covered every step.
Then select the Resource menu option. From there select the Create New Resource option. This will open a window which has a list of resource names. Notice that the name of the resources are like mnemonics. We will select a MENU resource.
This will open a window where it will show the user one 'tab' of a menu. The user will be given the option of entering a Title for the menu or Selecting the Apple Menu.
This is the first selection, so select the Apple Menu Symbol. The press <CR>. You will notice that it goes to the next line. So what we will do is create an option to show a Dialog Box (which will eventually be our about box) and another option to create an Alert Box, so that we can see the difference.
So in the Text field enter My Demo Alert Box and then press <CR>. It will go to the next line of the menu. Select the separator option to put a line underneath. Then close the window and that menu is set up.
So that is the Apple Menu done, we need to make a File menu next. We need to make another MENU resource (like we did before). Notice how there is now a window with a picture of the first menu with an identifying id value underneath which starts at 128 (well that's no surprise!!). The next MENU resource will have an id of 129, and so on if you made more MENU resources.
Instead of selecting the Apple Menu, the Title of this menu is File. Press <CR> to go to the next line. The option is NEW. So enter into the Text field New. This time though we also want a keyboard simulation of this option (AppleKey + N), so in the Cmd-Key: field enter N.
Enter some more options (what ever you want!!), but make sure you have an OPEN, a SAVE and a QUIT option in your menu.
Once you have done that close the window and save it.
It is now time to set up the menu.
How this is done is by using the GetMenu, InsertMenu and DrawMenuBar calls. The GetMenu command searches the open resource list and read the predefined menu from the resource and returns a handle. This handle is used to add the menu to the Menu Bar using the Insert Menu command. Finally, once all the menus have been inserted into the Menu Bar, it is drawn by the DrawMenuBar call.
Here are the definitions of each of the calls:
So if we look at the code we will see how we get each menu (Apple Menu first), then Insert each menu (the left most menu first, so we have The Apple Menu first). Once we Insert each menu, the Menu bar is then drawn so that it appears on screen.
Note: The Apple Menu is a special beast, using the above method will only give you the Dialog box and Alert box in the Menu. To add all the other applications to the menu you must use AppendResMenu. This call is detailed below:
The following code loads and displays our menu bar:
Right, that sets up the menu but it doesn't do a fat lot. Why?
The answer is fairly simple! Mac OS responds to EVENTS. Anything from pressing a key to clicking the mouse button. This was covered in Chapter 6. These events are in a queue and the OS acts upon the next one along using Event Handlers (please note this is a major simplification, this guide is showing you how to use EVENTS, not the internal workings of the MacOS). As an interesting note, Windows (I've just brought up my lunch) 95 works in a similar way, so crack events here and you can code Windows 95 apps (is that a bonus or a curse?) .
At the moment our application does not process any events so how can we open a menu, if we are not looking for a mouse click, or a menu selection etc.
Now Try imagining a Event routine, what should it do?
Note: If you go off and process an event you must return to the top of the Event Loop afterwards.
That's fairly straight forward. The call that we use was introduced the the last chapter.
So lets go to the code. We will firstly set up the parameters then call WaitNextEvent. If there is a null event returned we will return to the top of the Event Loop. If it returns an event we will process it, if it is a mouse event or an update event (these are the only events we will be covering in this lesson) else we will return to the top of the Event Loop.
As you can see the Events Loop is a fairly simple routine. But this still doesn't open our menu and let us select options from it, so now we have to process our mouse events.
There are a few different mouse events, like:
We are only concerned (in this example) with the mouse clicking on the menu bar and then selecting an option from the menu. So here is the plan of action. When we get a mousedown event, find out where the mouse was pressed, was it on the menubar? This is done using the FindWindow call. If we clicked in the menu bar area we will jump to the menu routines.
Lets examine the FindWindow call:
The code looks like this:
Again a simple compare of the returned value to branch to the next section. Right, this is where it gets a bit more involved. Once you have clicked on the menu the program must do a few things first before it can process your selection of menu.
Firstly we have to discover what menu was selected, we will use the MenuSelect call to find this out. This call reads in the global mouse co-ordinates and so opens the menu that you have selected (if you clicked the menu bar) or selects the option from a menu that you clicked (if you clicked an option in a menu). Lets examine the MenuSelect call:
Once we find out what selection has been made, we process the code for that option. If you look at the code below (the heading is MENU STUFF), you can see how we call the ExitToShell if the menu selection is Quit. Notice how we use the StandardGetFile call to open a standard 'Open File' dialog box. And yes, StandardPutFile opens a standard 'Save File' dialog.
Right, I will let you mess about with the other standard calls, what we will look at now is how we call the Dialog Box and the Alert Box.
Calling an Alert Box
Calling an Alert Box is a single call. The Alert Box you display will have to be created in ResEdit. Examine the resource file for this project to look at an example Alert box.
To select the Alert Box we simply check to see what menu item has been selected from the Apple Menu and if it is not any of the other options then we process the Alert box routine. the call is called Alert. This is called then the code returns to the event loop.
Calling a Dialog Box
This is a more involved process, the program must firstly call GetNewDialog which creates a dialog from the specified DLOG resource. That only makes the dialog, the program must make the dialog appear using the ModalDialog call which begins user interaction with the dialog. Then we finally call DisposeDialog to close the dialog and release the related memory. Lets look at the commands:
Below is the code concerning the Dialog Boxes, Alert Boxes and Menu Selections. Read this carefully!!!
If you look above you can see how we call to any external program through the Apple Menu. We firstly use the GetMenuItemText call to find the name of the program we wish to run, then we use OpenDeskAcc to run the program.
Lets examine the commands:
This in itself will not make the program run, it will only run once our program becomes suspended (this is also an event) and this will only happen after we have processed an UPDATE event (I bet you thought I was never going to get to that didn't you). So lets look at the steps you need to go through to process an update event. Firstly we save the current GrafPort using GetPort, then we make our GrafPort the current one with SetPort. We then call for an Update of our window using BeginUpdate. We then redraw the bottom right corner of the window if it has been resized using DrawGrowIcon, next we update any visible controls using DrawControls. Then we end the update using EndUpdate and finally restore the current GrafPort.
There are a few calls there, but I will document only BeginUpdate and EndUpdate.
This will then update the window and so run any call to execute external programs. Lets look at the code:
Take your time with this lesson, there is a lot of information here that needs to be learnt thoroughly. This has given us a base from which to make a Mac Application.
In the next Chapter we will look at other events, and get onto mouse cursors in different areas of our window (as we never got round to it in this chapter). We will look at stretching (resizing) windows and other events. We will decide exactly what sort of Application it will be eventually. We will add to the menus and modify the Help Menu.
Reproduction in whole or part prohibited without permission.
Download the project for this chapter