Window & Popupmenu

I have a program that creates multiple windows using the same DLOG resource. My problem is that this window has a popupmenu CNTL resource that I append  menu items to depending on a certain criteria. But when I go to open another window using the same DLOG resource I end up with the same menu items in the new window but I don't want the same menu items, I want diferent items depending on criteria. Also If I close one of the windows the popupmenu disappears in the other windows. Obviously this is because the menu is disposed of (I think). How can I create a NewMenu( baseID +1, "\pOptions); for each window and install this dynamically created menu to the popupcontrol of the window. I am using a  CNTL resource, the control type is System 7 Popup, fixed width, window font.
dwp090598Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

boonstraCommented:
I think I answered something similar to this in <http://www.experts-exchange.com/jsp/qShow.jsp?ta=macprog&qid=10110269 >

You need to clone the popup for each window.

/* assume CNTL 128 is the popup control you want to clone */
/* 301, 3001, 302, 3002 are arbitrary, but they must be different for each window and unique from other CNTL and MENU
items in your resource file */

#define kControlID 128

/* create dialog 1*/
      dlg = CreateModelessDialog();

      GetDialogItem(dlg, kThePopupMenu, &tempType, (Handle *)&dummyHdl, &tempRect);
      controlHdl = DupPopUpControl(kControlID,301,3001,dlg);
      DisposeControl(dummyHdl);
      SetDialogItem(dlg, kThePopupMenu, tempType, (Handle)controlHdl, &tempRect);

      mHandle = (**((PopupPrivateData **)((**controlHdl).contrlData))).mHandle;
      AppendMenu(mHandle,"\pAdded Item 1");
      
/* create dialog 2*/
      dlg = CreateModelessDialog();
      GetDialogItem(dlg, kThePopupMenu, &tempType, (Handle *)&dummyHdl, &tempRect);
      controlHdl = DupPopUpControl(kControlID,302,3002,dlg);
      DisposeControl(dummyHdl);
      SetDialogItem(dlg, kThePopupMenu, tempType, (Handle)controlHdl, &tempRect);

      mHandle = (**((PopupPrivateData **)((**controlHdl).contrlData))).mHandle;
      AppendMenu(mHandle,"\pAdded Item 2");

where:

static ControlHandle DupPopUpControl(short controlID,
    short newControlID, short newMenuID, DialogPtr dlg) {
  ControlHandle newControlHdl;
  Handle oldControlHdl;
  MenuHandle mHandle;
  short mID;

  /* get control resource */
  oldControlHdl = GetResource('CNTL',controlID);
   
  /* extract menu ID from control resource */
  mID = *(short *)(*oldControlHdl+14);

  /* copy MENU resource */
  mHandle = (MenuHandle)GetResource('MENU',mID);
  (**mHandle).menuID = newMenuID;
  DetachResource((Handle)mHandle);
  AddResource((Handle)mHandle,'MENU',newMenuID,"\p");
   
  /* copy CNTL resource with new MENU ID */
  DetachResource((Handle)oldControlHdl);
  *(short *)(*oldControlHdl+14) = newMenuID;
  AddResource((Handle)oldControlHdl,'CNTL',newControlID,"\p");
 
  /* finally, attached the cloned control to the window */
  newControlHdl = GetNewControl(newControlID,dlg);
  return newControlHdl;
}
0
dwp090598Author Commented:
I am not trying to duplicate a control but change a popup menu control's menuhandle to a diferent menuHandle that I created using NewMenu(); This way I can have a diferent menu for each window opened.
0
boonstraCommented:
If you want to create an entirely new menu from scratch, then it would be best to create a new control from scratch and add it to each dialog.

But your original question said that you wanted to _append_ menu items to an original control.  So this solution has the base items in a popupmenu control, and then clones the menu so you can add items to each copy separately.

The reason it clones the control (and the associated menu) is that the menu identity is embedded in the control.  As long as the controls are the same, they point to the same menu.  To point to different menus, the controls need to be different.

I'll email you separately a test program that shows how the whole thing works.  Try it, I think it does what you want.
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

boonstraCommented:
Meant the above to be another attempt at an answer.
0
boonstraCommented:
boonstra changed the proposed answer to a comment
0
Alex CuryloCommented:
Well, I see one bug right off in boonstra's code; after the AppendMenu(), he didn't call SetControlMaximum(). Not doing this will confuse the Control Manager, because *it* doesn't know what the hell you just did to the menu :)

I think NewMenu is the right tack to be taking, but not with setting the popup control to the new menu; subtleties like the SetControlMaximum() thing just mentioned are far too likely to trip you up. Far far better to just create the new control on the fly once you have your menu in its final form, methinks.

First off, you need to have a way to pick an unused menu id:

short GetNextFreeMenuID(void)
      {
      short newID = 666;     // whatever's got lots of room following in your program

      while (::GetMenuHandle(newID))
            newID++;

      return newID;
      }

and then every time you open the duplicated dialog, do something like this:

void CreateDynamicMenu(DialogPtr inDialog)
      {
      // put a new empty menu in the menu list
      short menuID = GetNextMenuID();
      MenuHandle menu = ::NewMenu(menuID, "\p");
      ::InsertMenu(menu, -1);   ctrl;

      // Now, add all the items to the menu.
      // I would suggest putting all possible text items in an STR# resource
      // and copying applicable ones with GetIndString and AppendMenu.
      // Unless there's Menu Manager metachars in your text in which case
      // AppendMenu() dummy text and SetMenuItemText() the real text.

      Rect menuRect;
      // I would recommend using a userItem in the DLOG as a layout placeholder,
      // and then calling GetDialogItem on it here to fill in menuRect.

      // Now that we have a finished menu and know where it goes,
      // it's time to let the Control Manager in on the action :)
      ControlHandle ctrl = ::NewControl(inDialog, &menuRect, "\pPopup Menu", popupTitleJustLeft, menuID, 0, popupMenuProc, 0);
      }
0
dwp090598Author Commented:
I tried this code and I ended up with a new popupmenu but there doesn't seem to be a menu attached to the control. Is NewControl(inDialog, &menuRect, "\pPopup Menu", popupTitleJustLeft, menuID, 0, popupMenuProc, 0);  looking for a resource in the menuID paramater. Have you tried this code, maybe I am doing something wrong. Thanks for your help.
0
Alex CuryloCommented:
Well, I haven't run this exactly, but it's abstracted from code which does work :) The principles are explained in Technical Q&A TB42, at

http://developer.apple.com/qa/tb/tb42.html

If reading that over doesn't make whatever's wrong jump out as obvious, just stuff your project up and send it to alex@witty.com and I'll fix it then :)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dwp090598Author Commented:
Finally figured out how to create the menu.

Thanks - now I need more help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.