jasmerb@coil.cs.orst.edu (Bryce Roger Jasmer) (07/05/88)
I am having serious trouble getting my own menu definition working in a submenu. The menu definition will work all by itself when it is regular menu in the menubar, and the heirarchical menu works just fine with a standard menu attached as a submenu, but when the two are combined they won't work. I am using LSP and here is some of the code to create the menu: TopLevelMenu := GetMenu(TopLevelMenuID); tempString := ConCat(chr(hMenuCmd), chr(SubMenuID), 'SubMenu'); AppendMenu(TopLevelMenu, tempString); InsertMenu(TopLevelMenu, 0); SubMenu := GetMenu(SubMenuID); SubMenu^^.menuProc := NewHandle(0); SubMenu^^.menuProc^ := Ptr(@SubMenuProc); {defined elsewhere} InsertMenu(SubMenu, -1); CalcMenuSize(SubMenu); ------- I will click in the TopLevelMenu and drag down to the 'SubMenu' item, the Mac then draws the empty box that the my submenu will draw in, and then crashes at the "MenuSelect(theEvent.where)" function call. I would compile the menu definition into a MDEF resource but the menu definition needs to have access to some global data. Please send e-mail, I am desperate! I will summarize if the solution comes my way. Thank you VERY much. Bryce Jasmer jasmerb@coil.cs.orst.edu
singer@endor.harvard.edu (Rich Siegel) (07/05/88)
In article <5381@orstcs.CS.ORST.EDU> jasmerb@coil.cs.orst.edu (Bryce Roger Jasmer) writes: >SubMenu := GetMenu(SubMenuID); >SubMenu^^.menuProc := NewHandle(0); >SubMenu^^.menuProc^ := Ptr(@SubMenuProc); {defined elsewhere} The above three lines of code are BAD! They are ILLEGAL, IMMORAL, and are guaranteed to smash your heap. What you've done here is to define what's commonly known as a "fake" handle; by saying SubMenu^^.menuProc^ := Ptr(@SubMenuProc) you've thoroughly crushed the master pointer for that particular handle, which will sooner or later crash the memory manager. I have several instances in my code where I need custom definition functions. Furthermore, it's easiest to have these in source form in my project, so that I can easily modify and debug them. But the above strategy is the wrong way to do it. Instead, I declare a procedure as follows: PROCEDURE InstallDefProc(dpType : ResType; dpID : Integer; dpAddr: : Ptr); var jH : JumpHandle; begin jH := JumpHandle(GetResource(dpType, dpID)); if jH = NIL then begin jH := JumpHandle(NewHandle(SizeOf(JumpRec))); AddResource(Handle(jH), dpType, dpID, ''); end; jH^^.jmpInstr := $EF9; jH^^.jmpAddr := Ord4(dpAddr); ChangedResource(Handle(jH)); WriteResource(Handle(jH)); end; InstallDefProc relies on the following type definition: TYPE JumpRec = record jmpInstr : Integer; jmpAddr : LongInt; end; JumpPtr = ^JumpRec; JumpHandle = ^JumpPtr; What InstallDefProc does is store a "dummy" definition code resource in the application's resource file. This code resource consists of a JMP to an absolute address. Now, for your menu: menu := GetMenu(MenuID)); menu^^.menuProc := GetResource('MDEF', mdefID)); where "MenuID" and "mdefID" are constants that you supply. Some caveats: 1) You should call the "InstallDefProc" routine in your application's initialization code. 2) The pointer that you pass to InstallDefProc for the address of your defproc should be a pointer to a routine that's in a segment that is always loaded and locked; in other words, any defprocs you have should be in the main code segment ("Segment 1" in a Lightspeed Pascal project)). This whole business of bogus handles is unfortunate, ... (Thanks to Jon Hueras for giving me tips on doing all this for myself.) --Rich Rich Siegel THINK Technologies
darin@Apple.COM (Darin Adler) (07/05/88)
In article <4884@husc6.harvard.edu> singer@endor.UUCP (Rich Siegel) writes: > jH^^.jmpInstr := $EF9; Watch out for typos! This should have been: jH^^.jmpInstr := $4EF9; Darin Adler AppleLink: Adler4 UUCP: {sun,voder,nsc,mtxinu,dual}!apple!darin CSNET: darin@Apple.com