Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!efi!tim From: tim@efi.com (Tim Maroney) Newsgroups: comp.sys.mac.programmer Subject: Re: Pop-ups in SFFGetFile + SFFPutFile - How? Message-ID: <1990Oct5.203035.17693@efi.com> Date: 5 Oct 90 20:30:35 GMT References: <1990Oct5.025518.18973@gpu.utcs.utoronto.ca> Organization: Electronics For Imaging, Inc. Lines: 174 In article <1990Oct5.025518.18973@gpu.utcs.utoronto.ca> topix@gpu.utcs.utoronto.ca (R. Munroe) writes: >Anyone had any experience adding pop-up menus to a get file or put file >procedure? For example, programs like PhotoShop and most word processing >packages have an Open As ... and Save As ... choice in the file menu. >When you choose Open As ... or Save As ... you get a fairly standard >looking SFGetFile or SFPutFile dialog. The difference is that there is >a pop-up that lets you select file formats. How is that done? Is it a >simple process or do you have to spend a good month or two coding it into >your application? Any pointers to example code would be greatly appreciated. It's not too hard. Here's some completely uncommented C code that uses Dialog Manager utilities that you don't have, and also dialog and string list resources you don't have, and also precompiled C headers which (all together now) you don't have, which may either help you or baffle you completely.... Promise to pay me lots of money and I will make this more like sample code for general use. #pragma load HEADER #include "fileutils.h" #include "document.h" #include "xdialogs.h" /* globals used by Save As standard file dialog */ static WindowPtr theWindow; static MenuHandle theMenu; static Str255 typeName; static Boolean good; static pascal void SaveAsMenu(DialogPtr dialog, short item) { Rect r; GetIRect(dialog, item, &r); MoveTo(r.left + 2, r.bottom); LineTo(r.right, r.bottom); MoveTo(r.right, r.top + 2); LineTo(r.right, r.bottom); FrameRect(&r); InsetRect(&r, 2, 2); r.left += 10; TextBox(typeName + 1, typeName[0], &r, teJustLeft); } static Boolean SaveAsInit(DialogPtr dialog) { short i; DocOperations **ops; WindowExtra **extra; if ((extra = FindExtra(theWindow)) == 0) return false; SetUserProc(dialog, 10, (ProcPtr)SaveAsMenu); for (i = 0, ops = (*extra)->ops; i < (*ops)->numSaveTypes; i++) FillSaveAsTypes(theMenu, (*ops)->saveTypes[i], (*extra)->doc.type); if (CountMItems(theMenu) < 1) return false; GetItem(theMenu, 1, typeName); return true; } static void FixSaveAs(DialogPtr dialog) { Str255 name; GetDText(dialog, 7, name); if (name[0] == 0 || GetIHilite(dialog, 1) == 255) HiliteItem(dialog, 11, 255); else HiliteItem(dialog, 11, 0); } static void PopUpTypes(DialogPtr dialog) { short i, lim; Str255 name; long result; Rect r; Point pt; for (i = 1, lim = CountMItems(theMenu); i <= lim; i++) { GetItem(theMenu, i, name); if (IUCompString(name, typeName) == 0) break; } InsertMenu(theMenu, -1); GetIRect(dialog, 10, &r); SetPt(&pt, r.left + 1, r.top + 1); LocalToGlobal(&pt); GetIRect(dialog, 9, &r); InvertRect(&r); result = PopUpMenuSelect(theMenu, pt.v, pt.h, i); DeleteMenu((*theMenu)->menuID); InvertRect(&r); if (HiWord(result) == 0 || LoWord(result) == 0) return; GetItem(theMenu, LoWord(result), typeName); GetIRect(dialog, 10, &r); InsetRect(&r, 1, 1); EraseRect(&r); SaveAsMenu(dialog, 10); } static pascal short SaveAsItems(short item, DialogPtr dialog) { switch (item) { case -1: if (SaveAsInit(dialog)) break; case 2: good = false, item = 2; break; case 11: good = true, item = 1; break; case 10: PopUpTypes(dialog); break; } if (item != 2) FixSaveAs(dialog); return item; } static pascal Boolean SaveAsEvents(DialogPtr dialog, EventRecord *event, short *item) { if (event->what == keyDown || event->what == autoKey) { char c = event->message & 0xff; if (c == 0x1b || (c == '.' && (event->modifiers & cmdKey))) { *item = 2; return true; } if ((c == 3 || c == 13) && GetIHilite(dialog, 11) == 0) { *item = 11; return true; } if (c == 9 && GetIHilite(dialog, 6) == 0) { *item = 6; return true; } } return false; } SaveAs(WindowPtr window) { Point pt; short volume; long folder, type; SFReply reply; Str255 buf, name; if ((theMenu = NewMenu(1234, "\p ")) == 0) return MemError(); SetPt(&pt, 60, 60); GetWTitle(window, name); GetIndString(buf, 15, 6); theWindow = window; SFPPutFile(pt, buf, name, SaveAsItems, &reply, 1, SaveAsEvents); DisposHandle((Handle)theMenu); if (!good) return userCancelled; if ((type = TypeByName(typeName)) == 0) return badTypeErr; volume = -SFSaveDisk, folder = CurDirStore; return SaveTo(window, reply.fName, volume, folder, type); } Oh, all right, here are the Dialog Manager utilities.... Handle GetIHandle(DialogPtr dialog, short item) { short type; Handle h; Rect r; GetDItem(dialog, item, &type, &h, &r); return h; } void GetIRect(DialogPtr dialog, short item, Rect *r) { short type; Handle h; GetDItem(dialog, item, &type, &h, r); } short GetIType(DialogPtr dialog, short item) { short type; Handle h; Rect r; GetDItem(dialog, item, &type, &h, &r); return type; } void HiliteItem(DialogPtr dialog, short item, short hilite) { HiliteControl((ControlHandle)GetIHandle(dialog, item), hilite); } GetIHilite(DialogPtr dialog, short item) { ControlHandle ch = (ControlHandle)GetIHandle(dialog, item); return (*ch)->contrlHilite; } void SetITitle(DialogPtr dialog, short item, StringPtr s) { SetCTitle((ControlHandle)GetIHandle(dialog, item), s); } void SetIValue(DialogPtr dialog, short item, short v) { SetCtlValue((ControlHandle)GetIHandle(dialog, item), v); } GetIValue(DialogPtr dialog, short item) { return GetCtlValue((ControlHandle)GetIHandle(dialog, item)); } void GetDText(DialogPtr dialog, short item, StringPtr s) { GetIText(GetIHandle(dialog, item), s); } void SetDText(DialogPtr dialog, short item, StringPtr s) { SetIText(GetIHandle(dialog, item), s); } void SetUserProc(DialogPtr dialog, short item, ProcPtr proc) { Rect r; GetIRect(dialog, item, &r); SetDItem(dialog, item, userItem, (Handle)proc, &r); } void InvalItem(DialogPtr dialog, short item) { GrafPtr save; Rect r; GetPort(&save); SetPort(dialog); GetIRect(dialog, item, &r); InvalRect(&r); SetPort(save); }