[comp.sys.mac.programmer] Changing a menu using a resource

lulue@manta.NOSC.MIL (Dan Lulue ) (05/17/88)

I want to be toggle a menu item from "Turn Herman On" to "Turn Herman
Of", and back.  The BOOK says that it is good practice to store the two
strings in a resource file instead of calling SetItem with the literal
strings [SetItem(menus(8),1,"Turn Herman On"), and SetItem(menus(8),1,
"Turn Herman Off")]..

Always wanting to be proper, I created two entries in the resource file
viz:

	resource 'STR ' (2083) {
		"Turn Herman On"
	};
	resource 'STR ' (2084) {
		"Turn Herman Off"
	};

and placed the following declarations in the include file:

#define ONID	2083	
#define OFFID	2084	

Is this correct so far?

Now GetResource returns a handle to the requested resource.  My question
is how to map that handle to the strings stored in the resource?  Once I
have a handle, what do I pass to SetItem??  Here is my GetResource call:

	Handle	theHandle;
		theHandle = GetResource ('STR ', OFFID);

A more generic question is "How does one figure out how to do something
the proper way when IM does not tell you how to do it the proper way?

Thank you very much in advance for any help you provide.

Dan.
lulue@nosc.mil

stew@endor.harvard.edu (Stew Rubenstein) (05/17/88)

In article <346@manta.NOSC.MIL> lulue@manta.NOSC.MIL (Dan Lulue ) writes:
>I want to be toggle a menu item from "Turn Herman On" to "Turn Herman
>Of", and back.
 [omitted]
>Is this correct so far?

Yup, perfect.

>Now GetResource returns a handle to the requested resource.  My question
>is how to map that handle to the strings stored in the resource?  Once I
>have a handle, what do I pass to SetItem??  Here is my GetResource call:
>
>	Handle	theHandle;
>		theHandle = GetResource ('STR ', OFFID);

A Handle is just a pointer to a pointer.  SetItem takes a StringPtr,
so if you have a menu called Albert with items Herman, George, etc.,
you typically do something like:

#define MENU_albert 1

MenuHandle albertMenu;
enum {	/* Items in the Albert menu */
	albertHerman = 1,
	albertGeorge,
	albertDashedLine1,	/* Don't forget placeholders */
	albertFred,
	...
};

and then to set the item:
	
	theHandle = GetResource ('STR ', OFFID);
	HLock (theHandle)
	SetItem (albertMenu, albertHerman, (StringPtr) *theHandle);
	HPurge (theHandle);

One other thing to worry about, depending on what development system
you're using - SetItem may expect a C string (null-terminated) and
GetResource returns a handle to a Pascal string (count byte prefixed).
LightSpeed C does it right - SetItem expects a P string so the code
above is correct.  The standard MPW interfaces do this silly
conversion, so you have to PtoCstr(*theHandle); before and
CtoPstr(*theHandle) after the SetItem.

>A more generic question is "How does one figure out how to do
something >the proper way when IM does not tell you how to do it the
proper way?

This is the kind of thing you learn by examining sample code.  Also, I
can highly recommend Knaster's books (How to Write Macintosh Programs
and Macintosh Programming Secrets, I think they're called).
Stew Rubenstein
Cambridge Scientific Computing, Inc.
UUCPnet:    seismo!harvard!rubenstein            CompuServe: 76525,421
Internet:   rubenstein@harvard.harvard.edu       MCIMail:    CSC

guido@cwi.nl (Guido van Rossum) (05/17/88)

In article <4602@husc6.harvard.edu> stew@endor.UUCP (Stew Rubenstein) writes:
>	theHandle = GetResource ('STR ', OFFID);
>	HLock (theHandle)
>	SetItem (albertMenu, albertHerman, (StringPtr) *theHandle);
>	HPurge (theHandle);
>
>One other thing to worry about, depending on what development system
>you're using - SetItem may expect a C string (null-terminated) and
>GetResource returns a handle to a Pascal string (count byte prefixed).
>LightSpeed C does it right - SetItem expects a P string so the code
>above is correct.  The standard MPW interfaces do this silly
>conversion, so you have to PtoCstr(*theHandle); before and
>CtoPstr(*theHandle) after the SetItem.

There's a toolbox function called (I believe) GetString which does
just this (retrieve a 'STR ' resource by ID) and is matched with the
string convention of each compiler's toolbox interface.  If I remember
it well it doesn't return a handle but stores the string in a 256-byte
buffer you pass, which saves the locking and purging of the handle.

BTW, in MPW it's p2cstr, not PtoCstr.
--
Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam
guido@piring.cwi.nl or mcvax!piring!guido or guido%piring.cwi.nl@uunet.uu.net
...unvoluntary LSC/MPW porting expert...

han@Apple.COM (Byron Han, fire fighter) (05/17/88)

In article <346@manta.NOSC.MIL> lulue@manta.NOSC.MIL (Dan Lulue ) writes:
>
>I want to be toggle a menu item from "Turn Herman On" to "Turn Herman
>Of", and back.  The BOOK says that it is good practice to store the two
>strings in a resource file instead of calling SetItem with the literal
>strings [SetItem(menus(8),1,"Turn Herman On"), and SetItem(menus(8),1,
>"Turn Herman Off")]..
>
Philosophical point here...  it is sometimes confusing to have a menu item
change its name.  Have you considered...

 Foobarmenu        Foobarmenu
 ----------       -----------
 item1             item1
 item2             item2
XHerman On         Herman On

using a checkmark?  I remember the god awful confusion with respect to
the original MacTerminal have Save Lines Off Top/Don't Save Lines Off Top.

I personally even find Show Clipboard/Hide Clipboard confusing.  I would
rather have a checkmark beside Show Clipboard to indicate showing the clip.

Of course, this can easily degenerate into a religious issue.  I merely
bring up some philosphical points that may be of interest.  Plus this


This does not represent an official Apple policy statement.  Just my
own personal rambling.
-- 
Byron Han,  Licensed to Dream.             "Macintosh - there is no substitute."
Apple Computer, Inc. MS 27Y                -------------------------------------
ATTnet:408-973-6450     applelink:HAN1     domain:han@apple.COM       MacNET:HAN
GENIE:BYRONHAN    COMPUSERVE:72167,1664    UUCP:{sun,voder,nsc,decwrl}!apple!han