Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Common Files/MacFramework.c
////////// |
// |
// File: MacFramework.c |
// |
// Contains: Code for the QuickTime sample code framework that is specific to the Macintosh. |
// This code handles windows, menus, events, and other low-level things. Put your |
// application-specific code into the file ComApplication.c. |
// |
// Written by: Tim Monroe |
// Based on the QTShell code written by Tim Monroe, which in turn was based on the MovieShell |
// code written by Apple DTS (Kent Sandvik). This current version is now very far removed from |
// MovieShell. |
// |
// Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <16> 06/28/02 rtm added HLock and HUnlock around call to InstallEventLoopTimer in |
// QTFrame_CreateMovieWindow; this fixes some mysterious crashes |
// <15> 03/11/02 rtm added support for Carbon events; set USE_CARBON_EVENTS to 1 to use |
// <14> 03/16/01 rtm added HideWindow to QTFrame_DestroyMovieWindow to prevent custom |
// window definition procs from being called during window tear-down |
// <13> 02/01/01 rtm fixed *Proc names to *UPP, to conform to Universal Headers 3.4b4 |
// <12> 08/11/00 rtm revised event-handling so that QTFrame_HandleEvent passes event to |
// the movie controller |
// <11> 07/06/00 rtm made changes to support new parameter to QTFrame_AdjustMenus |
// <10> 03/02/00 rtm made changes to get things running under CarbonLib |
// <9> 01/14/00 rtm reworked window-dragging and -updating code to support graphics files |
// <8> 12/23/99 rtm tweaked mouseDown handling in QTFrame_StandardModalDialogEventFilter |
// <7> 12/16/99 rtm added gMouseClickTime global variable and code to set it in mouseUp |
// case in QTFrame_HandleEvent |
// <6> 12/12/99 rtm tweaked inDrag handling in QTFrame_HandleEvent |
// <5> 11/30/99 rtm option-click in close box now closes all open movie windows (per HIG) |
// <4> 11/29/99 rtm reworked QTFrame_DestroyMovieWindow to use NavAskSaveChanges |
// <3> 11/16/99 rtm factored QTFrame_HandleEvent out of QTFrame_MainEventLoop, so we can |
// handle events from other code, if necessary |
// <2> 11/11/99 rtm made some preliminary changes for Carbon; still some work to be done |
// <1> 11/05/99 rtm first file; based on earlier sample code |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "MacFramework.h" |
////////// |
// |
// global variables |
// |
////////// |
Boolean gShuttingDown = false; // are we shutting down? |
Boolean gAppInForeground; // is our application in the foreground? |
Boolean gHasNewDialogCalls; // are the new Dialog Manager functions available? |
Str255 gWindowTitle = kDefaultWindowTitle; // default name for created windows |
Rect gWindowRect = kDefaultWindowRect; // default rectangle for created windows |
GrowZoneUPP gAppGrowZoneUPP; // UPP to our grow zone callback |
ModalFilterUPP gModalFilterUPP; // UPP to our custom dialog event filter |
UserItemUPP gUserItemProcUPP; // UPP to our custom dialog user item procedure |
Handle gEmergencyMemory; // handle to our emergency memory reserve |
short gAppResFile = kInvalidFileRefNum; // file reference number for this application's resource file |
FSSpec gAppFSSpec; // file specification for the application itself |
Str255 gAppName; // the name of this application |
long gMouseClickTime; // for double-click calculation |
extern Handle gValidFileTypes; // the list of file types that our application can open |
long gRunningUnderX = false; // are we running under Mac OS X? |
#if USE_CARBON_EVENTS |
EventHandlerUPP gAppEventHandlerUPP = NULL; |
EventHandlerUPP gWinEventHandlerUPP = NULL; |
EventHandlerUPP gWinEventModalHandlerUPP = NULL; |
EventLoopTimerUPP gWinTimerHandlerUPP = NULL; |
Boolean gMenuIsTracking = false; |
#endif |
#if USE_TASK_MGMT |
QTNextTaskNeededSoonerCallbackUPP |
gQTTaskSoonerUPP = NULL; |
#endif |
////////// |
// |
// main |
// The main function for this application. |
// |
// Set up the application's execution environment; make sure QuickTime (etc.) is installed, |
// then start handling events. |
// |
////////// |
int main (void) |
{ |
OSErr myErr = noErr; |
QTFrame_InitMacEnvironment(10L); |
// make sure that QuickTime is available and that we can initialize it |
if (!QTUtils_IsQuickTimeInstalled()) { |
QTFrame_ShowWarning("\pQuickTime is not installed on this computer. Exiting.", 0); |
ExitToShell(); |
} |
myErr = EnterMovies(); |
if (myErr != noErr) { |
QTFrame_ShowWarning("\pCould not initialize QuickTime. Exiting.", myErr); |
ExitToShell(); |
} |
// do any application-specific initialization |
QTApp_Init(kInitAppPhase_BothPhases); |
// get and process events until the user quits |
QTFrame_MainEventLoop(); |
ExitMovies(); |
ExitToShell(); |
return(0); |
} |
////////// |
// |
// QTFrame_InitMacEnvironment |
// Initialize the Macintosh runtime environment. |
// |
////////// |
static void QTFrame_InitMacEnvironment (long theNumMoreMasters) |
{ |
#if TARGET_API_MAC_CARBON |
#pragma unused(theNumMoreMasters) |
#endif |
short myVRefNum; |
long myDirID; |
#if USE_CARBON_EVENTS |
EventTypeSpec myEventSpec[] = { |
{kEventClassMenu, kEventMenuBeginTracking}, |
{kEventClassMenu, kEventMenuEndTracking}, |
{kEventClassCommand, kEventCommandProcess}, |
{kEventClassCommand, kEventCommandUpdateStatus} |
}; |
gAppEventHandlerUPP = NewEventHandlerUPP(QTFrame_CarbonEventAppHandler); |
if (gAppEventHandlerUPP != NULL) |
InstallEventHandler(GetApplicationEventTarget(), gAppEventHandlerUPP, GetEventTypeCount(myEventSpec), myEventSpec, NULL, NULL); |
gWinEventHandlerUPP = NewEventHandlerUPP(QTFrame_CarbonEventWindowHandler); |
gWinEventModalHandlerUPP = NewEventHandlerUPP(QTFrame_CarbonEventModalWindowHandler); |
gWinTimerHandlerUPP = NewEventLoopTimerUPP(QTFrame_CarbonEventWindowTimer); |
#if USE_TASK_MGMT |
gQTTaskSoonerUPP = NewQTNextTaskNeededSoonerCallbackUPP(QTFrame_NextTaskNeededSoonerProcedure); |
#endif |
#endif // USE_CARBON_EVENTS |
#if !TARGET_API_MAC_CARBON |
long myIndex; |
// add more space to the stack |
SetApplLimit((Ptr)(GetApplLimit() - kExtraStackSpaceSize)); |
// expand heap zone to its limit |
MaxApplZone(); |
// allocate some additional master pointer blocks |
for (myIndex = 0; myIndex < theNumMoreMasters; myIndex++) |
MoreMasters(); |
InitGraf(&qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(NULL); |
#endif |
InitCursor(); |
// initialize and install the menu bar |
QTFrame_InitMenuBar(); |
#if !TARGET_API_MAC_CARBON |
// install a grow zone procedure to handle low memory situations |
gEmergencyMemory = NewHandle(kEmergencyMemorySize); |
if (gEmergencyMemory != NULL) { |
gAppGrowZoneUPP = NewGrowZoneUPP(QTFrame_GrowZoneProcedure); |
SetGrowZone(gAppGrowZoneUPP); |
} |
#endif |
// initialize foreground/background state |
gAppInForeground = true; |
// see whether the new Dialog Manager functions are available |
#if TARGET_API_MAC_CARBON |
gHasNewDialogCalls = true; |
#else |
gHasNewDialogCalls = QTUtils_TrapAvailable(_DialogDispatch); |
#endif |
// create modal dialog filter and user item UPPs |
gModalFilterUPP = NewModalFilterUPP(QTFrame_StandardModalDialogEventFilter); |
gUserItemProcUPP = NewUserItemUPP(QTFrame_StandardUserItemProcedure); |
// get the application's resource file |
gAppResFile = CurResFile(); |
// get the application's name from the resource file |
GetIndString(gAppName, kAppNameResID, kAppNameResIndex); |
// get the application's location and save it in gAppFSSpec |
HGetVol(NULL, &myVRefNum, &myDirID); |
FSMakeFSSpec(myVRefNum, myDirID, gAppName, &gAppFSSpec); |
} |
////////// |
// |
// QTFrame_GrowZoneProcedure |
// A grow zone procedure. This is straight out of IM: Memory (pp. 1-46ff) |
// |
////////// |
PASCAL_RTN long QTFrame_GrowZoneProcedure (Size theBytesNeeded) |
{ |
#pragma unused(theBytesNeeded) |
long myA5; |
Size myBytesFreed; |
// get current A5; we might get called at a time that A5 isn't valid |
myA5 = SetCurrentA5(); |
if ((*gEmergencyMemory != NULL) && (gEmergencyMemory != GZSaveHnd())) { |
EmptyHandle(gEmergencyMemory); |
myBytesFreed = kEmergencyMemorySize; |
} else { |
myBytesFreed = 0; // no more memory to release |
} |
myA5 = SetA5(myA5); |
return(myBytesFreed); |
} |
////////// |
// |
// QTFrame_InitMenuBar |
// Set up the menu bar. |
// |
////////// |
static Boolean QTFrame_InitMenuBar (void) |
{ |
Handle myMenuBar = NULL; |
long myResponse; |
OSErr myErr = noErr; |
MenuRef myMenu = NULL; |
myMenuBar = GetNewMBar(kMenuBarResID); |
#if TARGET_API_MAC_CARBON |
// to get the theme-savvy menu bar, we need to call RegisterAppearanceClient. |
RegisterAppearanceClient(); |
#endif |
if (myMenuBar == NULL) |
return(false); |
SetMenuBar(myMenuBar); // install the menus |
DisposeHandle(myMenuBar); |
// see whether we are running under MacOS X; |
// if so, remove the Quit menu item and its preceding separator line |
myErr = Gestalt(gestaltSystemVersion, &myResponse); |
if (myErr == noErr) |
if (myResponse >= 0x00000A00) { |
DeleteMenuItem(GetMenuHandle(kFileMenuResID), MENU_ITEM(IDM_EXIT)); |
DeleteMenuItem(GetMenuHandle(kFileMenuResID), MENU_ITEM(IDM_EXIT) - 1); // the separator line |
gRunningUnderX = true; |
} |
#if !TARGET_API_MAC_CARBON |
AppendResMenu(GetMenuHandle(kAppleMenuResID), 'DRVR'); // add desk accessory names to Apple menu |
#endif |
#if USE_CARBON_EVENTS |
myMenu = GetMenuHandle(kAppleMenuResID); |
SetMenuItemCommandID(myMenu, kAboutMenuItem, COMMAND_ID(MENU_IDENTIFIER(kAppleMenuResID,kAboutMenuItem))); |
myMenu = GetMenuHandle(kFileMenuResID); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_FILENEW), COMMAND_ID(IDM_FILENEW)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_FILEOPEN), COMMAND_ID(IDM_FILEOPEN)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_FILECLOSE), COMMAND_ID(IDM_FILECLOSE)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_FILESAVE), COMMAND_ID(IDM_FILESAVE)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_FILESAVEAS), COMMAND_ID(IDM_FILESAVEAS)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EXIT), COMMAND_ID(IDM_EXIT)); |
myMenu = GetMenuHandle(kEditMenuResID); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITUNDO), COMMAND_ID(IDM_EDITUNDO)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITCUT), COMMAND_ID(IDM_EDITCUT)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITCOPY), COMMAND_ID(IDM_EDITCOPY)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITPASTE), COMMAND_ID(IDM_EDITPASTE)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITCLEAR), COMMAND_ID(IDM_EDITCLEAR)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITSELECTALL), COMMAND_ID(IDM_EDITSELECTALL)); |
SetMenuItemCommandID(myMenu, MENU_ITEM(IDM_EDITSELECTNONE), COMMAND_ID(IDM_EDITSELECTNONE)); |
#endif |
QTFrame_AdjustMenus(NULL, NULL, 0L); |
DrawMenuBar(); |
return(true); |
} |
////////// |
// |
// QTFrame_MainEventLoop |
// Retrieve and process events. |
// |
////////// |
static void QTFrame_MainEventLoop (void) |
{ |
#if USE_CARBON_EVENTS |
RunApplicationEventLoop(); |
#else |
EventRecord myEvent; |
long myDuration = kWNEMinimumSleep; |
while (!gShuttingDown) { |
#if !TARGET_API_MAC_CARBON |
// make sure we've still got our memory reserve; reallocate it if it's been used |
if ((gEmergencyMemory == NULL) || (*gEmergencyMemory == NULL)) |
ReallocateHandle(gEmergencyMemory, kEmergencyMemorySize); |
#endif |
#if USE_TASK_MGMT |
// get the number of ticks until QuickTime's next task |
QTGetTimeUntilNextTask(&myDuration, 60); |
if (myDuration == 0) |
myDuration = kWNEMinimumSleep; |
#endif |
// get the next event in the queue |
WaitNextEvent(everyEvent, &myEvent, myDuration, NULL); |
// handle the event |
QTFrame_HandleEvent(&myEvent); |
} // while (!gShuttingDown) |
#endif // USE_CARBON_EVENTS |
} |
////////// |
// |
// QTFrame_HandleEvent |
// Process an event. |
// |
////////// |
void QTFrame_HandleEvent (EventRecord *theEvent) |
{ |
WindowPtr myWindow = NULL; |
WindowObject myWindowObject = NULL; |
short myWindowPart; |
Rect myScreenRect; |
Boolean isEventHandled = false; |
// first, perform any application-specific event handling |
isEventHandled = QTApp_HandleEvent(theEvent); |
// then, if this event hasn't been handled, let all movie controllers have access to the event |
if (!isEventHandled) |
isEventHandled = QTFrame_CheckMovieControllers(theEvent); |
// then, if this event has been handled, return; otherwise, handle it here |
if (isEventHandled) |
return; |
myWindow = FrontWindow(); |
switch (theEvent->what) { |
case mouseUp: |
gMouseClickTime = TickCount(); // for double-click calculation |
break; |
case mouseDown: |
myWindowPart = FindWindow(theEvent->where, &myWindow); |
// menu bar and window-related events: |
switch (myWindowPart) { |
case inSysWindow: |
#if !TARGET_API_MAC_CARBON |
// a mouse click in a window belonging to a desk accessory |
SystemClick(theEvent, myWindow); |
#endif |
break; |
case inMenuBar: |
// a mouse click in the menu bar |
QTFrame_AdjustMenus(FrontWindow(), NULL, (long)theEvent->modifiers); |
QTFrame_HandleMenuCommand(MenuSelect(theEvent->where)); |
break; |
case inDrag: { |
Rect myRect; |
myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow); |
if (myWindowObject != NULL) { |
if ((**myWindowObject).fMovie != NULL) |
GetMovieBox((**myWindowObject).fMovie, &myRect); |
if ((**myWindowObject).fGraphicsImporter != NULL) |
GraphicsImportGetNaturalBounds((**myWindowObject).fGraphicsImporter, &myRect); |
GetRegionBounds(GetGrayRgn(), &myScreenRect); |
DragAlignedWindow(myWindow, theEvent->where, &myScreenRect, &myRect, NULL); |
} else { |
GetRegionBounds(GetGrayRgn(), &myScreenRect); |
DragWindow(myWindow, theEvent->where, &myScreenRect); |
} |
break; |
} |
case inContent: |
if (myWindow != FrontWindow()) { |
SelectWindow(myWindow); |
MacSetPort((GrafPtr)GetWindowPort(myWindow)); |
} else { |
QTApp_HandleContentClick(myWindow, theEvent); |
} |
break; |
case inGoAway: |
if (TrackGoAway(myWindow, theEvent->where)) { |
// if the option key is down, close all open movie windows; otherwise, close just the frontmost |
if (theEvent->modifiers & optionKey) |
QTFrame_CloseMovieWindows(); |
else |
QTFrame_DestroyMovieWindow(myWindow); |
} |
break; |
} // end switch(myWindowPart) |
break; |
// system-level events: |
case updateEvt: |
myWindow = (WindowPtr)theEvent->message; |
if (myWindow != NULL) { |
// if the window contains an image, draw it using GraphicsImportDraw |
myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow); |
if (myWindowObject != NULL) |
if ((**myWindowObject).fGraphicsImporter != NULL) |
GraphicsImportDraw((**myWindowObject).fGraphicsImporter); |
// now do any application-specific drawing |
QTApp_Draw(myWindow); |
} |
break; |
case keyDown: |
case autoKey: |
QTFrame_HandleKeyPress(theEvent); |
break; |
case diskEvt: { |
#if !TARGET_API_MAC_CARBON |
Point myPoint = {100, 100}; |
if (HiWord(theEvent->message) != noErr) |
(void)DIBadMount(myPoint, theEvent->message); |
#endif |
break; |
} |
case activateEvt: |
myWindow = (WindowReference)theEvent->message; |
if (QTFrame_IsMovieWindow(myWindow)) |
QTFrame_ActivateController(myWindow, ((theEvent->modifiers & activeFlag) != 0 )); |
break; |
case osEvt: |
switch ((theEvent->message >> 24) & 0x00ff) { // get high byte of message |
case suspendResumeMessage: |
// set the foreground/background state |
gAppInForeground = (theEvent->message & resumeFlag) != 0; |
// activate the front window, if there is one |
if (myWindow != NULL) |
QTFrame_ActivateController(myWindow, gAppInForeground); |
break; |
case mouseMovedMessage: |
break; |
} |
break; |
case kHighLevelEvent: |
AEProcessAppleEvent(theEvent); |
break; |
case nullEvent: |
// do idle-time processing for all open movie windows |
myWindow = QTFrame_GetFrontMovieWindow(); |
while (myWindow != NULL) { |
if (gAppInForeground) |
QTApp_Idle(myWindow); |
myWindow = QTFrame_GetNextMovieWindow(myWindow); |
} |
break; |
} // switch (theEvent->what) |
} |
////////// |
// |
// QTFrame_HandleMenuCommand |
// Handle a menu selection. |
// |
////////// |
Boolean QTFrame_HandleMenuCommand (long theMenuResult) |
{ |
short myMenuID, myMenuItem; |
Cursor myArrow; |
Boolean myIsHandled = false; |
MacSetCursor(GetQDGlobalsArrow(&myArrow)); |
myMenuID = HiWord(theMenuResult); |
myMenuItem = LoWord(theMenuResult); |
switch (myMenuID) { |
case kAppleMenuResID: |
switch (myMenuItem) { |
case kAboutMenuItem: // About box |
QTFrame_ShowAboutBox(); |
myIsHandled = true; |
break; |
default: // Apple menu handling |
#if !TARGET_API_MAC_CARBON |
{ |
Str255 myDAName; |
GetMenuItemText(GetMenuHandle(kAppleMenuResID), myMenuItem, myDAName); |
(void)OpenDeskAcc(myDAName); |
} |
myIsHandled = true; |
#endif |
break; |
} |
break; |
case kFileMenuResID: |
myIsHandled = QTFrame_HandleFileMenuItem(QTFrame_GetFrontMovieWindow(), MENU_IDENTIFIER(myMenuID, myMenuItem)); |
break; |
case kEditMenuResID: |
myIsHandled = QTFrame_HandleEditMenuItem(QTFrame_GetFrontMovieWindow(), MENU_IDENTIFIER(myMenuID, myMenuItem)); |
break; |
default: |
// do any application-specific menu handling |
myIsHandled = QTApp_HandleMenu(MENU_IDENTIFIER(myMenuID, myMenuItem)); |
break; |
} // switch (myMenuID) |
HiliteMenu(0); |
return(myIsHandled); |
} |
////////// |
// |
// QTFrame_HandleKeyPress |
// Handle key presses. This is modelled on Inside Macintosh: Macintosh Toolbox Essentials, p. 3-78. |
// |
////////// |
void QTFrame_HandleKeyPress (EventRecord *theEvent) |
{ |
char myKey; |
myKey = theEvent->message & charCodeMask; |
if (theEvent->modifiers & cmdKey) { |
// if the command key is down, it must be a keyboard shortcut for a menu selection; |
// adjust the menus and find the menu command that the shortcut picks out |
QTFrame_AdjustMenus(FrontWindow(), NULL, (long)theEvent->modifiers); |
QTFrame_HandleMenuCommand(MenuKey(myKey)); |
} else { |
// otherwise, we'll assume it's meant for our application |
QTApp_HandleKeyPress(myKey); |
} |
} |
////////// |
// |
// QTFrame_QuitFramework |
// Do any framework-specific shut-down. |
// |
////////// |
void QTFrame_QuitFramework (void) |
{ |
// set our global flag to indicate we're shutting down |
gShuttingDown = true; |
// do application-specific processing that must occur before movie windows are closed |
QTApp_Stop(kStopAppPhase_BeforeDestroyWindows); |
// close all open movie windows; note that the user can cancel the shutting down |
QTFrame_CloseMovieWindows(); |
// test the quit flag; a call to QTFrame_DestroyMovieWindow may have reset it |
if (!gShuttingDown) |
return; |
// do application-specific processing that must occur after movie windows are closed |
QTApp_Stop(kStopAppPhase_AfterDestroyWindows); |
// release our list of valid file types |
if (gValidFileTypes != NULL) |
DisposeHandle(gValidFileTypes); |
#if !TARGET_API_MAC_CARBON |
// release the grow zone memory |
if (gEmergencyMemory != NULL) |
DisposeHandle(gEmergencyMemory); |
#endif |
#if USE_CARBON_EVENTS |
QuitApplicationEventLoop(); |
if (gAppEventHandlerUPP != NULL) |
DisposeEventHandlerUPP(gAppEventHandlerUPP); |
if (gWinEventHandlerUPP != NULL) |
DisposeEventHandlerUPP(gWinEventHandlerUPP); |
if (gWinEventModalHandlerUPP != NULL) |
DisposeEventHandlerUPP(gWinEventModalHandlerUPP); |
if (gWinTimerHandlerUPP != NULL) |
DisposeEventLoopTimerUPP(gWinTimerHandlerUPP); |
#endif |
#if USE_TASK_MGMT |
if (gQTTaskSoonerUPP != NULL) |
DisposeQTNextTaskNeededSoonerCallbackUPP(gQTTaskSoonerUPP); |
#endif |
// release any routine descriptors |
if (gAppGrowZoneUPP != NULL) |
DisposeGrowZoneUPP(gAppGrowZoneUPP); |
if (gModalFilterUPP != NULL) |
DisposeModalFilterUPP(gModalFilterUPP); |
if (gUserItemProcUPP != NULL) |
DisposeUserItemUPP(gUserItemProcUPP); |
} |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
// |
// Framework utilities. |
// |
// The framework uses the following functions to create movies and handle dialog boxes. You probably won't |
// need to use them directly. |
// |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
////////// |
// |
// QTFrame_CreateMovieWindow |
// Create a new window to display the movie in. |
// |
////////// |
WindowReference QTFrame_CreateMovieWindow (void) |
{ |
WindowReference myWindow = NULL; |
// create a new window to display the movie in |
myWindow = NewCWindow(NULL, &gWindowRect, gWindowTitle, false, noGrowDocProc, (WindowPtr)-1L, true, 0); |
// create a new window object associated with the new window |
QTFrame_CreateWindowObject(myWindow); |
#if USE_CARBON_EVENTS |
{ |
WindowObject myWindowObject = NULL; |
EventTypeSpec myEventSpec[] = { |
{kEventClassKeyboard, kEventRawKeyDown}, |
{kEventClassKeyboard, kEventRawKeyRepeat}, |
{kEventClassKeyboard, kEventRawKeyUp}, |
{kEventClassWindow, kEventWindowUpdate}, |
{kEventClassWindow, kEventWindowDrawContent}, |
{kEventClassWindow, kEventWindowActivated}, |
{kEventClassWindow, kEventWindowDeactivated}, |
{kEventClassWindow, kEventWindowHandleContentClick}, |
{kEventClassWindow, kEventWindowClose} |
}; |
// install Carbon event handlers for this window |
InstallStandardEventHandler(GetWindowEventTarget(myWindow)); |
if (gWinEventHandlerUPP != NULL) |
InstallEventHandler(GetWindowEventTarget(myWindow), gWinEventHandlerUPP, GetEventTypeCount(myEventSpec), myEventSpec, QTFrame_GetWindowObjectFromWindow(myWindow), NULL); |
#if !USE_CARBON_MOVIE_CONTROL |
myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow); |
if (myWindowObject == NULL) |
return(myWindow); |
HLock((Handle)myWindowObject); |
if (gWinTimerHandlerUPP != NULL) |
InstallEventLoopTimer(GetMainEventLoop(), 0, TicksToEventTime(kWNEMinimumSleep), gWinTimerHandlerUPP, myWindowObject, &(**myWindowObject).fTimerRef); |
HUnlock((Handle)myWindowObject); |
#if USE_TASK_MGMT |
if ((gQTTaskSoonerUPP != NULL) && ((**myWindowObject).fTimerRef != NULL)) |
QTInstallNextTaskNeededSoonerCallback(gQTTaskSoonerUPP, 1000, 0, (void *)(**myWindowObject).fTimerRef); |
#endif // USE_TASK_MGMT |
#endif // !USE_CARBON_MOVIE_CONTROL |
} |
#endif |
return(myWindow); |
} |
////////// |
// |
// QTFrame_DestroyMovieWindow |
// Close the specified movie window. |
// |
////////// |
void QTFrame_DestroyMovieWindow (WindowReference theWindow) |
{ |
WindowObject myWindowObject = NULL; |
OSErr myErr = noErr; |
// get the window object associated with the specified window |
myWindowObject = QTFrame_GetWindowObjectFromWindow(theWindow); |
if (myWindowObject == NULL) { |
// if the window passed in isn't a movie window, just dispose of it and return |
if (theWindow != NULL) { |
DisposeWindow(theWindow); |
theWindow = NULL; |
} |
return; |
} |
// if the window's data is "dirty", give the user a chance to save it |
if ((**myWindowObject).fIsDirty) { |
Str255 myString; |
NavAskSaveChangesAction myAction; |
NavAskSaveChangesResult myResult; |
NavDialogOptions myDialogOptions; |
NavEventUPP myEventUPP = NewNavEventUPP(QTFrame_HandleNavEvent); |
// get the title of the window |
GetWTitle(theWindow, myString); |
// install the application and document names |
NavGetDefaultDialogOptions(&myDialogOptions); |
BlockMoveData(gAppName, myDialogOptions.clientName, gAppName[0] + 1); |
BlockMoveData(myString, myDialogOptions.savedFileName, myString[0] + 1); |
// specify the action |
myAction = gShuttingDown ? kNavSaveChangesQuittingApplication : kNavSaveChangesClosingDocument; |
// display the "Save changes" dialog box |
myErr = NavAskSaveChanges(&myDialogOptions, myAction, &myResult, myEventUPP, NULL); |
if (myErr != noErr) |
myResult = kNavAskSaveChangesCancel; |
switch (myResult) { |
case kNavAskSaveChangesSave: |
// save the data in the window |
QTFrame_UpdateMovieFile(theWindow); |
break; |
case kNavAskSaveChangesCancel: |
// do not close the window, and do not quit the application |
gShuttingDown = false; |
return; |
case kNavAskSaveChangesDontSave: |
// discard any unsaved changes (that is, don't do anything) |
break; |
} |
DisposeNavEventUPP(myEventUPP); |
} |
// if we got to this point, it's okay to hide, close, and destroy the window |
#if USE_CARBON_EVENTS |
if ((**myWindowObject).fTimerRef != NULL) { |
RemoveEventLoopTimer((**myWindowObject).fTimerRef); |
(**myWindowObject).fTimerRef = NULL; |
} |
#endif |
HideWindow(theWindow); |
QTFrame_CloseWindowObject(myWindowObject); |
DisposeWindow(theWindow); |
} |
////////// |
// |
// QTFrame_StandardUserItemProcedure |
// A standard user-item procedure to outline the OK button in a modal dialog. |
// |
////////// |
PASCAL_RTN void QTFrame_StandardUserItemProcedure (DialogPtr theDialog, short theItem) |
{ |
#pragma unused(theItem) |
short myItemKind; // for GetDialogItem |
Handle myItemHandle; // for GetDialogItem |
Rect myItemRect; // for GetDialogItem |
if (!gHasNewDialogCalls) { // no need to do any of this if the new Dialog Manager calls are available |
GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect); |
MacInsetRect(&myItemRect, -4, -4); |
PenSize(3, 3); |
FrameRoundRect(&myItemRect, 16, 16); |
PenSize(1, 1); |
} |
} |
////////// |
// |
// QTFrame_StandardModalDialogEventFilter |
// A standard modal dialog event filter. |
// |
////////// |
PASCAL_RTN Boolean QTFrame_StandardModalDialogEventFilter (DialogPtr theDialog, EventRecord *theEvent, short *theItemHit) |
{ |
Boolean myEventHandled = false; |
short myItemKind; // for GetDialogItem |
Handle myItemHandle; // for GetDialogItem |
Rect myItemRect; // for GetDialogItem |
unsigned long myTicks; // for Delay |
char myKey; |
WindowReference myWindow = NULL; |
short myPart; |
switch (theEvent->what) { |
case updateEvt: |
// update the specified window, if it's behind the modal dialog box |
myWindow = (WindowReference)theEvent->message; |
if ((myWindow != NULL) && (myWindow != GetDialogWindow(theDialog))) { |
QTFrame_HandleEvent(theEvent); |
myEventHandled = false; // so sayeth IM |
} |
break; |
case nullEvent: |
// do idle-time processing for all open windows in our window list |
if (gAppInForeground) |
QTFrame_IdleMovieWindows(); |
myEventHandled = false; |
break; |
case keyDown: |
case autoKey: |
// if new Dialog Manager calls are NOT available, handle certain key presses |
if (!gHasNewDialogCalls) { |
// first, map Command-period to Escape key... |
myKey = theEvent->message & charCodeMask; |
if (theEvent->modifiers & cmdKey) |
if (myKey == kPeriod) |
myKey = kEscapeKey; |
// ...then, handle the standard keyboard equivalents of OK and Cancel buttons |
switch (myKey) { |
case kReturnKey: |
case kEnterKey: |
*theItemHit = kStdOkItemIndex; |
GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect); |
HiliteControl((ControlHandle)myItemHandle, kControlButtonPart); |
Delay(kMyButtonDelay, &myTicks); |
HiliteControl((ControlHandle)myItemHandle, kControlNoPart); |
myEventHandled = true; |
break; |
case kEscapeKey: |
*theItemHit = kStdCancelItemIndex; |
GetDialogItem(theDialog, kStdCancelItemIndex, &myItemKind, &myItemHandle, &myItemRect); |
HiliteControl((ControlHandle)myItemHandle, kControlButtonPart); |
Delay(kMyButtonDelay, &myTicks); |
HiliteControl((ControlHandle)myItemHandle, kControlNoPart); |
myEventHandled = true; |
break; |
default: |
break; |
} |
} |
break; |
case mouseDown: |
myPart = FindWindow(theEvent->where, &myWindow); |
if ((myPart == inDrag) && (myWindow == GetDialogWindow(theDialog))) { |
Rect myScreenRect; |
GetRegionBounds(GetGrayRgn(), &myScreenRect); |
DragWindow(myWindow, theEvent->where, &myScreenRect); |
myEventHandled = true; |
} |
break; |
default: |
myEventHandled = false; |
break; |
} |
// let the OS's standard filter proc handle the event, if it hasn't already been handled |
if (gHasNewDialogCalls && (myEventHandled == false)) |
myEventHandled = StdFilterProc(theDialog, theEvent, theItemHit); |
return(myEventHandled); |
} |
////////// |
// |
// QTFrame_CheckMovieControllers |
// Let all movie controllers have a chance to process the event. |
// |
// Returns true if the event was handled by some movie controller, false otherwise |
// |
////////// |
static Boolean QTFrame_CheckMovieControllers (EventRecord *theEvent) |
{ |
WindowPtr myWindow = NULL; |
MovieController myMC = NULL; |
myWindow = QTFrame_GetFrontMovieWindow(); |
while (myWindow != NULL) { |
myMC = QTFrame_GetMCFromWindow(myWindow); |
if (myMC != NULL) |
if (MCIsPlayerEvent(myMC, theEvent)) |
return(true); |
myWindow = QTFrame_GetNextMovieWindow(myWindow); |
} |
return(false); |
} |
////////// |
// |
// QTFrame_ShowAboutBox |
// Display and manage the About dialog box. |
// |
////////// |
void QTFrame_ShowAboutBox (void) |
{ |
DialogPtr myDialog = NULL; |
WindowRef myWindow = NULL; |
short mySavedResFile; |
GrafPtr mySavedPort; |
short myItemKind; |
Handle myItemHandle; |
Rect myItemRect; |
#if USE_CARBON_EVENTS |
EventTypeSpec myEventSpec[] = { |
{kEventClassWindow, kEventWindowDrawContent}, |
{kEventClassControl, kEventControlHit} |
}; |
#else |
short myItem; |
#endif |
// get the current resource file and port |
mySavedResFile = CurResFile(); |
GetPort(&mySavedPort); |
// set the application's resource file; |
// otherwise, we'd get the dialog's resources from the current resource file, |
// which might not be the correct one.... |
UseResFile(gAppResFile); |
// deactivate any frontmost movie window |
QTFrame_ActivateController(QTFrame_GetFrontMovieWindow(), false); |
myDialog = GetNewDialog(kAboutBoxID, NULL, (WindowPtr)-1L); |
if (myDialog == NULL) |
goto bail; |
myWindow = GetDialogWindow(myDialog); |
if (myWindow == NULL) |
goto bail; |
SetPortDialogPort(myDialog); |
if (gHasNewDialogCalls) |
SetDialogDefaultItem(myDialog, kStdOkItemIndex); |
// make sure that the OK button is outlined in bold, even if new Dialog Manager calls not available |
GetDialogItem(myDialog, kOKButtonUserItem, &myItemKind, &myItemHandle, &myItemRect); |
SetDialogItem(myDialog, kOKButtonUserItem, myItemKind, (Handle)gUserItemProcUPP, &myItemRect); |
#if USE_CARBON_EVENTS |
// install a window handler for the dialog window |
GetDialogItem(myDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect); |
if (myItemHandle != NULL) |
SetWindowDefaultButton(myWindow, (ControlHandle)myItemHandle); |
InstallStandardEventHandler(GetWindowEventTarget(myWindow)); |
if (gWinEventModalHandlerUPP != NULL) |
InstallEventHandler(GetWindowEventTarget(myWindow), gWinEventModalHandlerUPP, GetEventTypeCount(myEventSpec), myEventSpec, (void *)myDialog, NULL); |
// display and handle events in the dialog box until the user clicks OK |
RunAppModalLoopForWindow(myWindow); |
#else |
// display and handle events in the dialog box until the user clicks OK |
do { |
ModalDialog(gModalFilterUPP, &myItem); |
} while (myItem != kStdOkItemIndex); |
#endif |
bail: |
// restore the previous resource file and port |
MacSetPort(mySavedPort); |
UseResFile(mySavedResFile); |
if (myDialog != NULL) |
DisposeDialog(myDialog); |
} |
////////// |
// |
// QTFrame_ShowWarning |
// Display a warning box. |
// |
////////// |
void QTFrame_ShowWarning (Str255 theMessage, OSErr theErr) |
{ |
Str255 myString; |
short mySavedResFile; |
// get the current resource file and set the application's resource file |
mySavedResFile = CurResFile(); |
UseResFile(gAppResFile); |
// insert argument into the message text template, to get the message text |
NumToString(theErr, myString); |
ParamText("\pWarning!", theMessage, theErr ? myString: NULL, NULL); |
// display the dialog box |
Alert(kAlertErrorID, gModalFilterUPP); |
// restore the original resource file |
UseResFile(mySavedResFile); |
} |
#if USE_CARBON_EVENTS |
////////// |
// |
// QTFrame_CarbonEventAppHandler |
// Handle Carbon events targeted at the application. |
// |
////////// |
PASCAL_RTN OSStatus QTFrame_CarbonEventAppHandler (EventHandlerCallRef theCallRef, EventRef theEvent, void *theRefCon) |
{ |
#pragma unused(theCallRef, theRefCon) |
UInt32 myClass, myKind; |
HICommand myCommand; |
OSStatus myErr = eventNotHandledErr; |
myClass = GetEventClass(theEvent); |
myKind = GetEventKind(theEvent); |
switch (myClass) { |
case kEventClassCommand: |
switch (myKind) { |
case kEventCommandProcess: |
myErr = GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(myCommand), NULL, &myCommand); |
if ((myErr == noErr) && ((myCommand.attributes & kHICommandFromMenu) != 0)) |
myErr = QTFrame_HandleMenuCommand(myCommand.commandID) ? noErr : eventNotHandledErr; |
break; |
case kEventCommandUpdateStatus: |
myErr = GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(myCommand), NULL, &myCommand); |
if ((myErr == noErr) && ((myCommand.attributes & kHICommandFromMenu) != 0)) |
QTFrame_AdjustMenus(FrontWindow(), NULL, 0L); |
break; |
} |
break; |
case kEventClassMenu: |
switch (myKind) { |
case kEventMenuBeginTracking: |
gMenuIsTracking = true; |
break; |
case kEventMenuEndTracking: |
gMenuIsTracking = false; |
break; |
} |
break; |
} |
return(myErr); |
} |
////////// |
// |
// QTFrame_CarbonEventWindowHandler |
// Handle Carbon events targeted at a movie window. |
// |
// On entry, theRefCon is the WindowObject for the window. |
// |
////////// |
PASCAL_RTN OSStatus QTFrame_CarbonEventWindowHandler (EventHandlerCallRef theCallRef, EventRef theEvent, void *theRefCon) |
{ |
#pragma unused(theCallRef) |
UInt32 myClass, myKind; |
UInt32 myModifiers; |
WindowRef myWindow = NULL; |
EventRecord myEvent; |
WindowObject myWindowObject = (WindowObject)theRefCon; |
OSStatus myErr = eventNotHandledErr; |
myClass = GetEventClass(theEvent); |
myKind = GetEventKind(theEvent); |
switch (myClass) { |
case kEventClassKeyboard: |
switch (myKind) { |
case kEventRawKeyDown: |
case kEventRawKeyRepeat: |
case kEventRawKeyUp: |
if (ConvertEventRefToEventRecord(theEvent, &myEvent)) |
QTFrame_HandleEvent(&myEvent); |
myErr = noErr; |
break; |
} |
break; |
case kEventClassWindow: |
switch (myKind) { |
case kEventWindowUpdate: |
case kEventWindowDrawContent: |
case kEventWindowActivated: |
case kEventWindowDeactivated: |
if (ConvertEventRefToEventRecord(theEvent, &myEvent)) |
QTFrame_HandleEvent(&myEvent); |
myErr = noErr; |
break; |
case kEventWindowHandleContentClick: |
myErr = GetEventParameter(theEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(myWindow), NULL, &myWindow); |
if (myErr == noErr) { |
GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(myModifiers), NULL, &myModifiers); |
GetEventParameter(theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &myEvent.where); |
GetEventParameter(theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &myEvent.when); |
myEvent.what = mouseDown; |
myEvent.message = (long)myWindow; |
myEvent.modifiers = myModifiers; |
myEvent.when = EventTimeToTicks(GetCurrentEventTime()); |
QTFrame_HandleEvent(&myEvent); |
myErr = noErr; |
} |
break; |
case kEventWindowClose: |
if (myWindowObject != NULL) { |
QTFrame_DestroyMovieWindow((**myWindowObject).fWindow); |
myErr = noErr; |
} |
break; |
default: |
break; |
} |
break; |
} |
return(myErr); |
} |
////////// |
// |
// QTFrame_CarbonEventModalWindowHandler |
// Handle Carbon events targeted at a modal dialog window. |
// |
// On entry, theRefCon is the DialogPtr for the dialog box. |
// |
////////// |
PASCAL_RTN OSStatus QTFrame_CarbonEventModalWindowHandler (EventHandlerCallRef theCallRef, EventRef theEvent, void *theRefCon) |
{ |
#pragma unused(theCallRef) |
UInt32 myClass, myKind; |
DialogPtr myDialog = (DialogPtr)theRefCon; |
OSStatus myErr = eventNotHandledErr; |
myClass = GetEventClass(theEvent); |
myKind = GetEventKind(theEvent); |
switch (myClass) { |
case kEventClassWindow: |
switch (myKind) { |
case kEventWindowDrawContent: |
if (myDialog != NULL) |
DrawDialog(myDialog); |
myErr = noErr; |
break; |
} |
break; |
case kEventClassControl: |
switch (myKind) { |
case kEventControlHit: |
if (myDialog != NULL) |
myErr = QuitAppModalLoopForWindow(GetDialogWindow(myDialog)); |
break; |
} |
break; |
} |
return(myErr); |
} |
////////// |
// |
// QTFrame_CarbonEventWindowTimer |
// Handle time-triggered actions for a specific window. |
// |
// The theRefCon paramter is a window object for the window to be tasked. |
// |
////////// |
PASCAL_RTN void QTFrame_CarbonEventWindowTimer (EventLoopTimerRef theTimer, void *theRefCon) |
{ |
WindowObject myWindowObject = (WindowObject)theRefCon; |
long myDuration = 0L; |
if (myWindowObject == NULL) |
return; |
// sanity check: make sure it's our timer |
if ((**myWindowObject).fTimerRef != theTimer) |
return; |
#if USE_TASK_MGMT |
// get the number of milliseconds until QuickTime's next task |
QTGetTimeUntilNextTask(&myDuration, 1000); |
if (myDuration == 0) |
myDuration = kMinAppTaskInMillisecs; |
// set the timer to fire at that time |
if (theTimer != NULL) |
SetEventLoopTimerNextFireTime(theTimer, myDuration * kEventDurationMillisecond); |
#endif |
// just issue a null event to our event-handling routine.... |
if (!gMenuIsTracking || gRunningUnderX) { |
EventRecord myEvent; |
myEvent.what = nullEvent; |
myEvent.message = 0; |
myEvent.modifiers = 0; |
myEvent.when = EventTimeToTicks(GetCurrentEventTime()); |
QTFrame_HandleEvent(&myEvent); |
} |
} |
#endif // USE_CARBON_EVENTS |
#if USE_TASK_MGMT |
////////// |
// |
// QTFrame_NextTaskNeededSoonerProcedure |
// Handle task-sooner notifications. |
// |
// We assume that theRefCon is an event loop timer reference. |
// |
////////// |
PASCAL_RTN void QTFrame_NextTaskNeededSoonerProcedure (TimeValue theDuration, unsigned long theFlags, void *theRefCon) |
{ |
#pragma unused(theFlags) |
EventLoopTimerRef myTimer = (EventLoopTimerRef)theRefCon; |
if (myTimer != NULL) |
SetEventLoopTimerNextFireTime(myTimer, theDuration * kEventDurationMillisecond); |
} |
#endif // USE_TASK_MGMT |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14