TweetFollow Us on Twitter

Menus in TML
Volume Number:4
Issue Number:6
Column Tag:Advanced Mac'ing

Menus as Objects in TML Pascal

By David B. Curtis, Wyoming, MN

[One of the limitations of LightSpeed Pascal and Turbo Pascal, despite their popularity, is that they don’t support objects. TML Pascal does support the object type, which is similar to a procedure. In this article, David Curtis shows us how to use the TML Pascal Object type on menus to create an elegant way to manage menus, especially a custom menu definition like an icon menu, shown in figure 1. Unfortunately, Tom Leonard of TML has not bothered to keep MacTutor supplied with updates to TML Pascal in over a year, so I have been unable to check the compilation and linking of this article. However, the code looks clean and should not have any problems. It is our hope that TML will keep MacTutor and the rest of the development community better informed and supplied with timely updates to their Pascal. -Ed]

In some applications, a graphic menu provides a friendlier user interface than the standard text list. MacDraw’s “Fill”, “Lines”, and “Pen” menus are good examples. They show you the patterns you can choose from, rather than describe them in words. Can you imagine trying to describe the SysPat list verbally? Pictures are much more friendly. I have a similar problem in an application I am working on. It is a simple circuit analysis program, and I wish to have a menu of circuit models for the user to choose from. A circuit element is much more easily drawn than described. The brute force approach to this problem is to make a procedure that draws each circuit model in the menu area. That works, but I dislike it. First of all, it is hard to maintain. Second, it is just plain hard work to build the first time. Finally, it is code that has little hope of ever being useful in another program.

Fig. 1 Icon Menus as Objects in Object Pascal

In case you didn’t notice, my objections to the brute force approach are motivated largely by sloth. How could I avoid excess work, both now and in the future? I went out in search of the lazy man’s way to a widely applicable, easily maintainable graphic menu, and came up with the icon menu. The icon menu procedure uses icons from a resource file to present a palette of selections. The code is generic across any application, and the icons can be maintained easily with ResEdit. Icons turn out to be a very nice size for my circuit model pictures. I suspect that icons would be good for a lot of graphic menu applications. (How about an icon based Transfer menu?) Figure 1 shows a prototype circuit model menu, implemented as an Icon menu.

Implementation Overview

I implemented the icon menu as a TML Pascal UNIT. (Any code that might get used in another program in the future I automatically put into a UNIT.) The OBJECT feature of Pascal is another powerful feature for reducing redundant work. I have used both features to create my icon menu, and usages of both are several layers deep. Each layer is quite simple, but some sort of road map to the structure is in order.

The lowest level unit is the trivial StdPoll (“standard poll”) unit. I mention it only so that you don’t wonder why I didn’t. Eventually, I plan to put generic polling loop code in here, but in its present form, StdPoll’s main purpose is to provide the global variable “Done”, which gets set in response to a “Quit” menu choice. Now on to the interesting stuff.

StdMenu (“standard menu”) is the key unit that everything is built upon. It defines a low level object called MenuHdlr (“menu handler”). A MenuHdlr object collects menu code into one place and “handles” all the associated behaviors. The two methods that a generic MenuHdlr has are Create, which should do whatever it takes to make a menu and insert it at the end of the menu bar; and Choose, which will be called to handle a menu choice. In the default case, Create just slurps up a normal menu resource from the resource fork. Choose, on the other hand, does nothing; it should be overridden in the application with appropriate code to handle the menu choices.

The StdMenu unit also provides pre-defined descendant objects of MenuHdlr, called AppleMenuHdlr, StdFileMenuHdlr, and StdEditMenuHdlr. These menu handlers provide minimal functionality for the Apple, File and Edit menus, respectively. The AppleMenuHdlr should be all most applications need to support a standard Apple menu. The Create method is overidden with code that pulls in desk accessory names, and the Choose method is overidden with code that displays an “About ” alert, or opens a desk accessory.

Notice that the AppleMenuHdlr has an additional method called “Setup”, which does the additional pre-Create work of setting up an alert id for the About selection. I have chosen the convention of putting additional pre-create initialization for MenuHdlrs (if needed) in a Setup method, but Setup is not a method in the generic MenuHdlr. Why? Because every descendant object that overrides a method must have the same parameter list, and that is exactly what we don’t want for a Setup method; we want the Setup method to be specific to the needs of a sub-species of MenuHdlr.

StdFileMenuHdlr and StdEditMenuHdlr exist in StdMenu only to provide bare minimum “Choose” functionallity. Most applications will want to override this code, but the minimal version is handy while prototyping other chunks of the application.

The program TestMenus uses AppleMenuHdlr, StdEditMenuHdlr and StdFileMenuHdlr. Look at the menu objects declared in the “var” section, and then look at the the procedures “InitApplication” and “MenuChoice” to see how the StdMenu unit is used. Notice how clean MenuChoice is because of the overridden Choose methods.

The IconMenu Unit

The meaty unit, as far as we are concerned, is IconMenu. This unit provides icon menu functionallity as a natural extension of the StdMenu facilities. The object type IconMenuHdlr, a descendant of MenuHdlr, adds a Setup method which is used to define the parameters of the icon menu. That includes what the first icon’s resource id is (the rest must follow in sequence), how many icons you have to display, how many icons wide you want the menu, how many extra pixels of blank space you want around each icon, and what the name of the menu is. Setup calculates how many icons tall the menu needs to be. These parameters are then stored in the IconMenuHdlr data record.

The Create method is in charge of a couple of tricks. Since the IconMenu is a non-standard menu, we have to set up our own menu definition procedure. My Icon menu definition procedure is IconMenuDef, a global procedure in the implementation part of the unit. IconMenuDef is installed as the menu’s definition procedure by the Create method. When the Create method first calls NewMenu, it gets a standard MenuInfo record. Since we want to store the larger IconMenuInfo record, Create calls SetHandleSize to “stretch” the storage block to the required size. The call to NewMenu also fills in the menuProc field with a handle to the standard menu definition procedure; we want to write over that with a handle to our own menu definition procedure. Be careful! The default menuProc handle that you get points to the one and only master pointer to the standard menu definition procedure. Assign a new handle to menuProc (which gets a new master pointer) before going through menuProc to set up a new menu definition. If you don’t, you clobber all menus. I am embarrassed to say I learned that the hard way, although it is obvious when you stop and think about it.

The Create method also sets up a reference in the menu record to the IconMenuHdlr object. That way IconMenuDef can find its way back to the data telling it what icons to draw where. (In a normal menu, the item information itself is stored following the MenuInfo record.) To set up the object reference, the menuHandle is type converted to an IconMenuHandle, and SELF is tucked away in the IconMenuInfo record. SELF is a reference to the object calling the method. Each instance of an IconMenuHdlr must call Create, and thus each icon menu gets its own list of icons and its own height and width. The IconMenuInfo record defined in the unit interface provides the necessary type information for the Create method to place the object reference in the menu data.

The MDEF Procedure

MDEF procedures have been described before in MacTutor, also reprinted in The Complete MacTutor, Vol. 2, p. 248, 251); I will just touch on the basics here. If you need more information, dig out those back issues, or see IM Vol. I, p. 362.

A menu definition procedure must respond to three kinds of “messages”, called mSizeMsg, mDrawMsg, and mChooseMsg. When the menu manager sends you the mSizeMsg, he wants to know how much space your menu takes on the screen. The menu manager sends you the mDrawMsg when he wants you to draw your menu on the screen; he has already saved the stuff underneath and given you a nice, white drawing space. When you get the mChoseMsg you should check the mouse location that you are given and do any hiliting and unhiliting necessary to behave like a menu. In a nutshell, that’s all there is to it; but I will admit it took me a while to get all that to work.

My menu definition procedure has four local procedures. One for each menu manager message type, and one that returns a rectangle in global coordinates when given the number of a menu selection. This structure is borrowed straight from Daryl Lovato’s MDEF example in the TML Source Code Library. (If I can make a small digression at this point, I would like to recommend the Source Code Library as a wonderful learning tool. Reading and modifying Source Code Library programs has taught me a lot about the Mac and its mysteries.)

DoSizeMsg and DoChoseMsg are both quite simple. All DoSizeMsg has to do is allow room for the necessary number of icons, plus the extra blank space in between. DoChoseMsg just searches for the icon that the cursor is over, and updates hiliting as necessary.

DoDrawMsg is a little more interesting, but still quite simple because we can make use of the icon support routines in the toolbox. This is where laziness really pays off; drawing all my circuit models through brute force code would have made this routine a nightmare. I suppose it would be good form to pre-load the icon resources for the menu, since a user could potentially end up in swap-a-floppy-land the way DoDrawMsg is now implemented. The Create method could easily preload icon resources, or the preload bit could be set with ResEdit.

Conclusion

The fanatical user might make some performance improvements to the IconMenuDef procedure. The item rectangles are calculated now, that could be sped up with look-up techniques. The item search itself could be sped up by doing something more elegant than a linear search. The icon menu seems quite fast to me as it is, however, so I don’t plan to fiddle with it. We non-fanatics need only zap up a few icons with ResEdit to have graphic menus.

{$L TestMenus/Rsrc }

program TestMenus;

uses
    Macintf, StdPoll, StdMenu, IconMenu;
    
const
 { Menu IDs }
 AppleMenuID = 256;
 AboutAlertID = 1000;
 FileMenuID = 257;
 EditMenuID = 258;
 CktMenuID = 259; { not a resource id }
 FirstCktIcon = 500;
 NumCktIcons = 7;
 IconsWide = 3;
 BfSpace = 3;
 
var
 { Instances of Menu Handlers }
 AppleMenu : AppleMenuHdlr;
 FileMenu : StdFileMenuHdlr;
 EditMenu : StdEditMenuHdlr;
 CktMenu : IconMenuHdlr;

 { Event polling variables }
 TheEvent : EventRecord;
 EventIsForMe : Boolean;  

{
|DoMenuChoice - do a menu selection
}
procedure DoMenuChoice (MenuCode : LongInt);
begin 
 case HiWord(MenuCode) of
 AppleMenuID: AppleMenu.Choose (LoWord(MenuCode));
 FileMenuID : FileMenu.Choose (LoWord(MenuCode));
 EditMenuID : EditMenu.Choose (LoWord(MenuCode));
 CktMenuID: CktMenu.Choose (LoWord(MenuCode)) end;
 HiliteMenu (0) end;

{
|PollEvent - check event queue and dispatch event, if any
}
procedure PollEvent;
var
 TempWindow : WindowPtr;
begin 
 EventIsForMe := GetNextEvent(everyEvent,TheEvent);
 if EventIsForMe 
 then case TheEvent.what of 
 mouseDown : case FindWindow(TheEvent.where,TempWindow) of
 inMenuBar: DoMenuChoice(MenuSelect(TheEvent.where));
 inSysWindow : SystemClick (TheEvent, TempWindow);
 otherwise { ignore } end;
 keyDown : if BitAnd(TheEvent.modifiers,CmdKey) <> 0
 then DoMenuChoice(MenuKey(CHR(BitAnd( TheEvent.message,CharCodeMask))));
 otherwise { ignore } end end;

{
|InitApplication
}
procedure InitApplication;
begin
 Done := False;

 { Create the menus }
 New (AppleMenu); 
 AppleMenu.Setup (AboutAlertID);
 AppleMenu.Create (AppleMenuID);
 
 New (FileMenu);
 FileMenu.Create (FileMenuID);
 
 New (EditMenu);
 EditMenu.Create (EditMenuID);
 
 New (CktMenu);
 CktMenu.Setup (FirstCktIcon, NumCktIcons, IconsWide, 
 BfSpace, ‘Model’);
 CktMenu.Create (CktMenuID);
 
 DrawMenuBar;

 InitCursor end;
 
{
|Main
}
begin
  InitTheMac;
  InitApplication;
  repeat
   SystemTask;
 PollEvent;
   until done end.


{$A+} { Interlinear source on compile to .asm }
{$R+} { Range checking }

unit StdPoll;

INTERFACE

uses 
 MacIntf;

var
 Done : Boolean; { program is all done }
 
procedure InitTheMac;

IMPLEMENTATION 

procedure InitTheMac;
begin 
 InitGraf (@ThePort);
 InitFonts;
 InitWindows;
 InitMenus;
 TEInit;
 InitDialogs (NIL) end;
end.

{
|StdMenu provides standard menu objects.
}
unit StdMenu;

interface

uses MacIntf, StdPoll;

const
 { Standard File menu item numbers }
 NewItem = 1;
 OpenItem = 2;
 CloseItem = 3;
 { ------ }
 SaveItem = 5;
 SaveAsItem = 6;
 RevertItem = 7;
 { ------ }
 PageSetupItem = 9;
 PrintItem = 10;
 { ------ }
 QuitItem = 12;

type  
 { 
 | MenuHdlr is the base object for all menus.
 | The Create method installs the menu at the end of
 | the menu bar.  The Choose method should be overridden
 | with code to perform a menu choice.
 }
 MenuHdlr = object
 TheMenu : MenuHandle;
 procedure Create (RsrcID : Integer);
 procedure Choose (Choice : Integer);
 end;
 
 {
 | AppleMenuHdlr provides all the functionallity of
 | a standard Apple menu.  It must be Setup with an 
 | alert id for the About  message before Create is
 | called.
 }
 AppleMenuHdlr = object (MenuHdlr)
 AboutID : Integer;
 procedure Create (RsrcID : Integer); override;
 procedure Choose (Choice : Integer); override;
 procedure Setup (AlertID : Integer);
 end;

 {
 | StdFileMenuHdlr is a minimal File menu.  The Choose
 | method can Close DA’s and Quit.
 }
 StdFileMenuHdlr = object (MenuHdlr)
 procedure Choose (Choice : Integer); override;
 end;
 
 {
 | StdEditMenuHdlr is a minimal Edit menu.  The Choose
 | method supports DA editing.
 }
 StdEditMenuHdlr = object (MenuHdlr)
 procedure Choose (Choice : Integer); override;
 end;
 
implementation 

{
|Generic Menu Handler
}
procedure MenuHdlr.Create (RsrcID : Integer);
begin
 { Read in a standard menu resource.
 | Remember: Object variables are Handles! 
 |’Self’ is set only
 | as you enter the method, so HLock it if you call any
 | potential heap-scramblers! }
 HLock(Handle(Self));
 TheMenu := GetMenu (RsrcID);
 InsertMenu (TheMenu, 0);
 HUnlock(Handle(Self)) end;

procedure MenuHdlr.Choose (Choice : Integer);
begin end;

{
|Apple Menu Handler
}
procedure AppleMenuHdlr.Create (RsrcID : Integer);
begin
 { Read in the Apple menu stub, and add DA’s }
 HLock(Handle(Self));
 TheMenu := GetMenu (RsrcID);
 AddResMenu (TheMenu, ‘DRVR’);
 InsertMenu (TheMenu, 0);
 HUnlock(Handle(Self)) end;
 
procedure AppleMenuHdlr.Choose (Choice : Integer);
var
 AccName : Str255;
 AccNumber : integer;
begin
 { Post alert or open DA }
 if Choice = 1
 then AccNumber := Alert (AboutID, NIL)
 else begin
 GetItem (TheMenu, Choice, AccName);
 AccNumber := OpenDeskAcc (AccName) end end;
 
procedure AppleMenuHdlr.Setup (AlertID : Integer);
begin
 AboutID := AlertID end;

{
|Standard File Menu
}
procedure StdFileMenuHdlr.Choose (Choice : Integer);
var
 FrontWP : windowPeek;
begin
 case Choice of
 NewItem : ;
 OpenItem : ;
 CloseItem : begin { If frontmost window DA, close it. }
 FrontWP := windowPeek(frontWindow);
 if FrontWP^.windowKind < 0
 then CloseDeskAcc(FrontWP^.windowKind) end;
 SaveItem : ;
 SaveAsItem : ;
 RevertItem : ;
 PageSetupItem : ;
 PrintItem : ;
 QuitItem : Done := true;
 otherwise  { nothing } end end;

{
|Standard Edit menu
}
procedure StdEditMenuHdlr.Choose (Choice : Integer);
var
 Trash : Boolean;
begin
 Trash := SystemEdit (Choice-1) end;

end. { of StdMenu unit }

{
|Icon menu MDEF unit
|
|Creates and manages a menu of Icons. 
}
unit IconMenu;

interface

uses
 Macintf, StdPoll, StdMenu;
 
type
 IconMenuHdlr = object (MenuHdlr)
 StartIcon, { The resource ID of first icon }
 NumIcons,{ How many icons to use (ID’s in 
 sequence) }
 IconsWide, { Menu shape... }
 IconsTall, { More menu shape. }
 BufferSpace{ Extra white pixels around each icon }
 : Integer;
 Title  { The name of the menu }
 : Str255;
 
 procedure Create (RsrcID : Integer); override;
 procedure Setup (
 StartIconReq, 
 NumIconsReq,
 IconsWideReq,
 BufferSpaceReq 
 : Integer;
 TitleReq
 : Str255);  end;
 
 IconMenuPtr = ^IconMenuInfo;
 IconMenuHandle = ^ IconMenuPtr;
 
 IconMenuInfo = record
 StdStuff : MenuInfo; { The default MenuInfo record }
 Handler : IconMenuHdlr { Reference to the above 
 handler object }
 end; 

implementation

const
   IconSize = 32;{ How big is an icon }

{
|IconMenuDef is installed as the MDEF procedure. 
|See IM Vol. I, p. 362
}
procedure IconMenuDef (
 Message : Integer;
 SelectedMenu : IconMenuHandle;
 var MenuRect : Rect;
 HitPt : Point;
 var WhichItem : Integer);

 {
 | ItemRect - function to find the rectangle ( in global 
 | coordinates) of a given item number.
 }
 function ItemRect (
 ItemNum : Integer;
 MenuRect : Rect; 
   SelectedMenu : IconMenuHandle) : Rect;
   
 var
 TempRect 
 : Rect;
 ItemLess1,
 ItemSize 
 : Integer;
   
 begin
   { If ItemNum is a real item, then return the }
 { global coordinates of the item’s rectangle; }
 { otherwise return empty rect. }
 if (ItemNum >= 1) 
 and (ItemNum <= SelectedMenu^^.Handler.NumIcons)
 then with SelectedMenu^^.Handler do begin 
 ItemLess1 := ItemNum - 1;
 ItemSize := IconSize + 2 * BufferSpace;
 TempRect.top := (ItemLess1 div IconsWide) 
 * ItemSize + MenuRect.top;
 TempRect.left := (ItemLess1 mod IconsWide) 
 * ItemSize + MenuRect.left;
 TempRect.bottom := TempRect.top + ItemSize;
 TempRect.right := TempRect.left + ItemSize end
 else begin
   TempRect.top := 0;
   TempRect.left := 0;
   TempRect.bottom := 0;
   TempRect.right := 0 end;
   ItemRect := TempRect end; 
 
 {
 | DoDrawMessage - handle the menu manager Draw command
 }
 procedure DoDrawMessage (
 SelectedMenu : IconMenuHandle;
   MenuRect : Rect);
   
 var
        Selection : Integer; { Current selection }
        SelRect : Rect; { Current selection’s Rect }
        TheIcon : Handle; { Handle to selection’s Icon }
      
 begin
 { Get every icon in the menu and plot it. }
 Hlock(Handle(SelectedMenu));
 with SelectedMenu^^.Handler do begin
        for Selection := 1 to NumIcons do begin
   SelRect := ItemRect(Selection, MenuRect, SelectedMenu);
   InsetRect(SelRect,BufferSpace,BufferSpace);
   TheIcon := GetIcon (StartIcon + Selection - 1);
   PlotIcon (SelRect, TheIcon) end end;
 HUnlock(Handle(SelectedMenu)) end; 
 
 {
 | DoChooseMessage - handle menu manager Choose command
 }
 function DoChooseMessage (
 SelectedMenu : IconMenuHandle;
   MenuRect : Rect;
 HitPoint : Point;
 OldSelection : Integer) : Integer;
      var
        SelRect : Rect;
        Found : boolean;
        Selection : Integer;
        OldSelRect : Rect;
      begin
 Selection := 1;
 Found:= false;
 { Find out which item mouse is over, if any. }
      repeat
        SelRect := ItemRect (Selection, MenuRect, SelectedMenu);
 Found := PtInRect (HitPoint,SelRect); 
 if not Found then Selection := Selection + 1;
      until ((Selection > (SelectedMenu^^.Handler.NumIcons))
 or (Found));
        { Update hiliting as necessary }
 if Found 
 then begin { in an item }
   if (Selection <> OldSelection) 
 then begin { in a different item, change hiliting }
        OldSelRect := ItemRect(OldSelection, 
 MenuRect, SelectedMenu);
        InvertRect(OldSelRect);
        InvertRect(SelRect) end;
   DoChooseMessage := Selection end
        else begin { not in a item, unhilite old }
        OldSelRect := ItemRect(OldSelection, MenuRect, SelectedMenu);
        InvertRect (OldSelRect);
 DoChooseMessage := 0 end end;

 {
 | DoSizeMessage - handle the menu manager Size command
 }
   procedure DoSizeMessage (
 var Menu : IconMenuHandle);
      begin
        with Menu^^.Handler do begin
          Menu^^.StdStuff.menuWidth:= IconsWide*(IconSize + 2 * BufferSpace);
          Menu^^.StdStuff.menuHeight:= IconsTall*(IconSize + 2 * BufferSpace)
 end end;

{
|IconMenuDef - main
}
begin
   case message of
        mSizeMsg : DoSizeMessage (SelectedMenu);
        mDrawMsg : DoDrawMessage (SelectedMenu, MenuRect);
 mChooseMsg : WhichItem := DoChooseMessage (
 SelectedMenu,MenuRect,HitPt,WhichItem) end end;

function Min (a,b : Integer) : Integer;
begin 
 if a < b
 then Min := a
 else Min := b end;

procedure IconMenuHdlr.Setup (
 StartIconReq, 
 NumIconsReq,
 IconsWideReq,
 BufferSpaceReq 
 : Integer;
 TitleReq
 : Str255);
begin
 StartIcon := StartIconReq;
 NumIcons := NumIconsReq;
 IconsWide := IconsWideReq;
 { Calculate IconsTall from NumIcons and IconsWide }
 IconsTall := NumIcons div IconsWide 
 + Min (NumIcons mod IconsWide, 1);
 BufferSpace := BufferSpaceReq;
 Title := TitleReq end;

procedure IconMenuHdlr.Create (RsrcID : Integer);
{ RsrcID isn’t a resource ID in this case, just a menu id }
var
 TrickyHandle : IconMenuHandle; { Used for type coercion }

begin 
 HLock(Handle(Self));
 TheMenu := NewMenu (RsrcID, Title); 
 { Get a plain menu record }
 
 SetHandleSize (Handle(TheMenu), SizeOf(IconMenuInfo)); 
 { Stretch it }
 if MemError = 0
 then begin
 { Assign the icon MDEF proc }
 TheMenu^^.menuProc := NewHandle(0); {Important! }
 TheMenu^^.menuProc^ := @IconMenuDef;
 { Stuff in reference to the MenuHandler object }
 TrickyHandle := IconMenuHandle (TheMenu);
 TrickyHandle^^.Handler := SELF;
 { Insert at end of menu bar }
 CalcMenuSize (TheMenu);
 InsertMenu (TheMenu,0) end
 else
 SysBeep (1);
 HUnlock(Handle(Self)) end;
 
end. { of IconMenu unit }


!PAS$Xfer

/Globals -4
TestMenus
PAS$Library
macintf
stdpoll
stdmenu
iconmenu


* IconMenu.R resources
*

IconMenu.rsrc
????????

Type EEIN = STR 
  ,0    ;;0 by convention
Icons in Menus by David Curtis \A9 MacTutor 1988.

Type BNDL
  ,128
  EEIN  0
  ICN# 1
  0 128
  FREF 1
  0 128

Type FREF
  ,128
  APPL  0 ;; local id 0 for icon list
  
* ------ Multifinder --------

Type SIZE = GNRL
 ,-1
.I
16384 ;; $4000 = bit 14 set
.L
148000  ;;  recomended
.L
128000  ;;  minimum


Type ALRT
  ,1000 (0)
60 128 260 368 
100
4444 

Type DITL
  ,100 (0)
2

Button 
133 128 153 188 
OK

staticText 
60 41 80 159 
About Menu Test


Type ICON = GNRL
  ,505 (0)
.H
0000 0000 0000 0000 0036 D800 0049 2400 
0049 2400 71C9 270E 8900 0111 8F00 01F1 
8900 0111 7104 410E 0104 8100 0105 0100 
01FD FF00 0005 0000 0004 8000 0004 4000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 7000 000E 
8800 0011 8FFF FFF1 8800 0011 7000 000E 

Type ICON = GNRL
  ,504 (0)
.H
0000 4000 0000 8000 0001 0000 0002 0000 
0004 0000 7008 000E 8810 0011 8FFF FFF1 
8800 0011 7000 000E 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 4000 0000 8000 
0001 0000 0002 0000 0004 0000 7008 000E 
8810 0011 8FFF FFF1 8800 0011 7000 000E 

Type ICON = GNRL
  ,503 (0)
.H
0000 0000 0000 0000 0000 0000 0000 0000 
0001 0800 7001 100E 8801 2011 8FFF 3FF1 
8801 2011 7001 100E 0001 0800 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 7000 000E 
8800 0011 8FFF FFF1 8800 0011 7000 000E 

Type ICON = GNRL
  ,506 (0)
.H
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 7000 000E 8800 0011 8FFF FFF1 
8A04 0111 7204 010E 0204 0100 0104 0100 
0087 0100 0100 8100 0200 8100 0407 0FE0 
0800 8000 0400 87C0 0207 0920 0100 8100 
0080 8100 0107 0100 0200 8100 0400 8100 
0807 0100 0404 0100 0204 0100 7204 010E 
8A04 0111 8FFF FFF1 8800 0011 7000 000E 

Type ICON = GNRL
  ,501 (0)
.H
0000 0000 0000 0000 0000 0000 0000 0000 
006D B600 7092 490E 8892 4911 8F92 49F1
8800 0011 7000 000E 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 7000 000E
8800 0011 8FFF FFF1 8800 0011 7000 000E


Type ICON = GNRL
  ,500 (0)
.H
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 7000 000E 8800 0011 8FFF FFF1
8800 8011 7000 800E 0000 8000 0000 E000
0000 1000 0000 1000 0000 E000 0000 1000
0000 1000 0000 E000 0000 1000 0000 1000
0000 E000 0000 1000 0000 1000 0000 E000
0000 1000 0000 1000 0000 E000 7000 800E
8800 8011 8FFF FFF1 8800 0011 7000 000E

Type ICON = GNRL
  ,502 (0)
.H
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 7000 000E 8800 0011 8FFF FFF1 
8800 8011 7000 800E 0000 8000 0000 8000 
0000 8000 0000 8000 0007 F000 0000 0000 
0000 0000 0001 C000 0002 A000 0004 9000 
0000 8000 0000 8000 0000 8000 0000 8000 
0000 8000 0000 8000 0000 8000 7000 800E 
8800 8011 8FFF FFF1 8800 0011 7000 000E 

Type MENU
  ,256 (0)
\14
About Test Menus 
(--<Ä

Type MENU
  ,257 (0)
File
(New/N
(Open
Close
(--
(Save
(Save As 
(Revert 
(--
(Page Setup 
(Print 
(--<Ä
Quit/Q

Type MENU
  ,258 (0)
Edit
Undo
(--<Ä
Cut/X
Copy/C
Paste/V
(--
Clear

Type ICN# = GNRL
  ,128 (4)  ;; The Appl. Icon
.H
003FFC0 000400200 00800100 01000080
0200004 004000020 09FFFFD0 13ABF568
23FFFFE 440422082 807E2081 80423F81
807E208 180002081 80003F81 80002081
801E208 1800E3F81 800E2081 801A2081
80303F8 180602081 40C02082 21803F84
1300208 808003F90 04000020 02000040
0100008 000800100 00400200 003FFC00
*
003FFC0 0007FFE00 00FFFF00 01FFFF80
03FFFFC 007FFFFE0 0FFFFFF0 1FFFFFF8
3FFFFFF C7FFFFFFE FFFFFFFF FFFFFFFF
FFFFFFF FFFFFFFFF FFFFFFFF FFFFFFFF
FFFFFFF FFFFFFFFF FFFFFFFF FFFFFFFF
FFFFFFF FFFFFFFFF 7FFFFFFE 3FFFFFFC
1FFFFFF 80FFFFFF0 07FFFFE0 03FFFFC0
01FFFF8 000FFFF00 007FFE00 003FFC00

David wins our Program of the Month award for this timely and interesting approach to using objects to manage menus. It is also refreshing to find that an old horse like TML Pascal can do some powerful things the new boys on the block can't do. Thanks David for a most interesting look at doing icon menus!

 
AAPL
$116.17
Apple Inc.
-0.14
MSFT
$47.65
Microsoft Corpora
-1.05
GOOG
$537.79
Google Inc.
+2.96

MacTech Search:
Community Search:

Software Updates via MacUpdate

StatsBar 1.9 - Monitor system processes...
StatsBar gives you a comprehensive and detailed analysis of the following areas of your Mac: CPU usage Memory usage Disk usage Network and bandwidth usage Battery power and health (MacBooks only)... Read more
Cyberduck 4.6 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
Evernote 6.0.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
calibre 2.11 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Herald 5.0.1 - Notification plugin for M...
Note: Versions 2.1.3 (for OS X 10.7), 3.0.6 (for OS X 10.8), and 4.0.8 (for OS X 10.9) are no longer supported by the developer. Herald is a notification plugin for Mail.app, Apple's Mac OS X email... Read more
Firetask 3.7 - Innovative task managemen...
Firetask uniquely combines the advantages of classical priority-and-due-date-based task management with GTD. Stay focused and on top of your commitments - Firetask's "Today" view shows all relevant... Read more
TechTool Pro 7.0.6 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PhotoDesk 3.0.1 - Instagram client for p...
PhotoDesk lets you view, like, comment, and download Instagram pictures/videos! (NO Uploads! / Image Posting! Instagram forbids that! AND you *need* an *existing* Instagram account). But you can do... Read more
SuperDuper! 2.7.3 - Advanced disk clonin...
SuperDuper! is an advanced, yet easy to use disk copying program. It can, of course, make a straight copy, or "clone" -- useful when you want to move all your data from one machine to another, or do... Read more

Latest Forum Discussions

See All

Golfinity – Tips, Tricks, Strategies, an...
Dig this: Would you like to know what we thought of being an infinite golfer? Check out our Golfinity review! Golfinity offers unlimited ways to test your skills at golf. Here are a few ways to make sure your score doesn’t get too high and your... | Read more »
Dark Hearts, The Sequel to Haunting Meli...
Dark Hearts, The Sequel to Haunting Melissa, is Available Now Posted by Jessica Fisher on November 21st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Meowza! Toyze Brings Talking Tom to Life...
Meowza! | Read more »
Square Enix Announces New Tactical RPG f...
Square Enix Announces New Tactical RPG for Mobile, Heavenstrike Rivals. Posted by Jessica Fisher on November 21st, 2014 [ permalink ] With their epic stories and gorgeous graphics, | Read more »
Quest for Revenge (Games)
Quest for Revenge 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: The great Kingdom of the west has fallen. The gods ignore the prayers of the desperate. A dark warlord has extinguished... | Read more »
Threadz is a New Writing Adventure for Y...
Threadz is a New Writing Adventure for You and Your Friends Posted by Jessica Fisher on November 21st, 2014 [ permalink ] In the tradition of round-robin storytelling, | Read more »
SteelSeries Stratus XL Hardware Review
Made by: SteelSeries Price: $59.99 Hardware/iOS Integration Rating: 4 out of 5 stars Usability Rating: 4.5 out of 5 stars Reuse Value Rating: 4.25 out of 5 stars Build Quality Rating: 4.5 out of 5 stars Overall Rating: 4.31 out of 5 stars | Read more »
ACDSee (Photography)
ACDSee 1.0.0 Device: iOS iPhone Category: Photography Price: $1.99, Version: 1.0.0 (iTunes) Description: Capture, perfect, and share your photos with ACDSee. The ACDSee iPhone app combines an innovative camera, a powerful photo... | Read more »
ProTube for YouTube (Entertainment)
ProTube for YouTube 2.0.2 Device: iOS Universal Category: Entertainment Price: $1.99, Version: 2.0.2 (iTunes) Description: ProTube is the ultimate, fully featured YouTube app. With it's highly polished design, ProTube offers ad-free... | Read more »
Weather or Not - Reports and Forecasts...
Weather or Not - Reports and Forecasts for your Calendar 1.0.0 Device: iOS iPhone Category: Weather Price: $2.99, Version: 1.0.0 (iTunes) Description: Weather or Not is a beautiful and intuitive way to check the weather and... | Read more »

Price Scanner via MacPrices.net

New 13-inch 1.4GHz MacBook Air on sale for $8...
 Adorama has the 2014 13″ 1.4GHz/128GB MacBook Air on sale for $899.99 including free shipping plus NY & NJ tax only. Their price is $100 off MSRP. B&H Photo has the 13″ 1.4GHz/128GB MacBook... Read more
Apple Expected to Reverse Nine-Month Tablet S...
Apple and Samsung combined accounted for 62 percent of the nearly 36 million branded tablets shipped in 3Q 2014, according to early vendor shipment share estimates from market intelligence firm ABI... Read more
Stratos: 30 Percent of US Smartphone Owners t...
Stratos, Inc., creator of the Bluetooth Connected Card Platform, has announced results from its 2014 Holiday Mobile Payments Survey. The consumer survey found that nearly one out of three (30 percent... Read more
2014 1.4GHz Mac mini on sale for $449, save $...
 B&H Photo has lowered their price on the new 1.4GHz Mac mini to $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... Read more
64GB iPod touch on sale for $249, save $50
Best Buy has the 64GB iPod touch on sale for $249 on their online store for a limited time. Their price is $50 off MSRP. Choose free shipping or free local store pickup (if available). Sale price for... Read more
15″ 2.2GHz Retina MacBook Pro on sale for $17...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale for $1799.99 for a limited time. Shipping is free, and B&H charges NY sales tax only. B&H will also include free copies of... Read more
New Logitech AnyAngle Case/Stand Brings Flexi...
Logitec has announced the newest addition to its suite of tablet products — the Logitech AnyAngle. A protective case with an any-angle stand for iPad Air 2 and all iPad mini models, AnyAngle is the... Read more
2013 15-inch 2.0GHz Retina MacBook Pro availa...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1499 including free shipping plus NY sales tax only. Their price is $500 off original MSRP. B&H will... Read more
16GB Retina iPad mini on sale today for $199,...
 Staples has 2nd generation 16GB Retina iPad minis on sale for $199 on their online store for a limited time. Their price is $100 off MSRP. Choose free shipping or free local store pickup (if... Read more
Developers Start Designing Apps for Apple Wat...
Apple has announced the availability of WatchKit, software that gives developers a set of tools to easily create experiences designed specifically for Apple Watch. Apple’s developer community can now... Read more

Jobs Board

*Apple* Solutions Consultant (ASC)- Retail S...
**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
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Store Leader Program - College Gradu...
Job Description: Job Summary As an Apple Store Leader Program agent, you can continue your education as you major in the art of leadership at the Apple Store. You'll 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
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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.