home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 11 / PC World Interactive 11.iso / share / multimed / effect / Common Files / WinFramework.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-17  |  51.2 KB  |  1,827 lines

  1. //////////
  2. //
  3. //    File:        WinFramework.c
  4. //
  5. //    Contains:    Basic support for playing QuickTime and QuickTime VR movies in a Windows application.
  6. //                WinFramework is a simple QuickTime viewer and editor framework. It handles windows,
  7. //                menus, messages, and other low-level things. Put your application-specific code into
  8. //                the file ComApplication.c (or other files).
  9. //
  10. //    Written by:    Tim Monroe
  11. //                Based (heavily!) on MDIPlayer sample code by Brian S. Friedkin (Aug 5, 1996).
  12. //
  13. //    Copyright:    ⌐ 1997-1998 by Apple Computer, Inc., all rights reserved.
  14. //
  15. //    Change History (most recent first):
  16. //
  17. //       <35>         03/14/98    rtm        fixed DoOpenCommandLineMovies
  18. //       <34>         03/14/98    rtm        added NativePathNameToFSSpec call to WinMain; changed OpenResFile to FSpOpenResFile
  19. //       <33>         02/28/98    rtm        removed call to DoApplicationEventLoopAction from main message loop
  20. //       <32>         02/13/98    rtm        added GetWindowWidth; reworked SizeWindowToMovie to call it
  21. //       <31>         02/09/98    rtm        added GetWindowReferenceFromPort
  22. //       <30>         02/06/98    rtm        added code to open the application's resource file (see WinMain);
  23. //                                    removed WM_MDIACTIVATE and WM_MOUSEACTIVATE handling from MovieWndProc
  24. //       <29>         02/02/98    rtm        added SetMenuState
  25. //       <28>         01/06/98    rtm        added WM_ACTIVATE handling to FrameWndProc, and added both WM_MDIACTIVATE
  26. //                                    and WM_MOUSEACTIVATE handling to MovieWndProc
  27. //       <27>         12/18/97    rtm        added QuitFramework, to mirror MacFramework.c
  28. //       <26>         12/12/97    rtm        added WM_MOUSEMOVE processing to MovieWndProc
  29. //       <25>         12/11/97    rtm        added GetDisplayName; finished reworking DoCreateMovieWindow
  30. //       <24>         12/10/97    rtm        started reworking DoCreateMovieWindow
  31. //       <23>         12/09/97    rtm        added DoOpenCommandLineMovies to handle movies dropped onto application icon
  32. //       <22>         12/08/97    rtm        added DoCautionAlert; finished support for Save; added Select All to Edit menu;
  33. //                                    added call to SHAddToRecentDocs in DoCreateMovieWindow
  34. //       <21>         12/05/97    rtm        added fDirty flag to window object; begun supporting Save and Save As
  35. //       <20>         12/03/97    rtm        fixed centering of Open File dialog box; see DialogProc
  36. //       <19>         11/06/97    rtm        fixed SizeWindowToMovie (now QT windows hide controller bar correctly)
  37. //       <18>         11/05/97    rtm        removed DoIdleProcessing; fixed bugs in DoCreateMovieWindow, AdjustMenus
  38. //       <17>         11/04/97    rtm        added HandleApplicationMenu call to FrameWndProc
  39. //       <16>         10/30/97    rtm        added GetPortFromWindowReference
  40. //       <15>         10/24/97    rtm        simplified SizeWindowToMovie, following latest MDIPlayer.c; removed
  41. //                                    GetWindowBorderWidth and GetWindowBorderHeight (called only by SizeWindowToMovie)
  42. //       <14>         10/23/97    rtm        moved InitializeQTVR and TerminateQTVR to ComApplication.c
  43. //       <13>         10/16/97    rtm        removed idle timer; removed MyGetMessage (QT emits idle events, eh?)
  44. //       <12>         10/14/97    rtm        upgraded to latest header files
  45. //       <11>         09/18/97    rtm        added GetFrontWindow and GetNextWindow; added gIdleTimer to emit idles
  46. //       <10>         09/15/97    rtm        added INIT_QTVR and TERM_QTVR to WinMain
  47. //       <9>         09/10/97    rtm        added MyGetMessage to send WM_IDLE messages when no messages are in queue;
  48. //                                    used EnumChildWindows to process idle messages for all movie windows
  49. //       <8>         09/10/97    rtm        changed DoOpenMovie into DoCreateMovieWindow and SetupMovieWindowWithController
  50. //                                    (based on functions of same names in VRShell's MacFramework.c)
  51. //       <7>         09/08/97    rtm        conditionalized code for creating grow box
  52. //       <6>         08/22/97    rtm        added code to DialogProc to center dialog boxes (from SimplePlayerSDI);
  53. //                                    factored out GetFile from DoOpenMovie; rewrote DoIdleProcessing
  54. //       <5>         08/21/97    rtm        changed child windows' icon spec to NULL; added WM_CLOSE case to DialogProc;
  55. //                                    added hooks for WinApplication.c; added GetAppDataFromFrontWindow et al.
  56. //       <4>         08/20/97    rtm        removed "CALLBACK" from declaration of ApplicationMCActionFilterProc and
  57. //                                    changed return type to Boolean; seems to fix some QuickTime movie problems;
  58. //                                    added GetMessagePos and GetMessageTime to event handling
  59. //       <3>         08/18/97    rtm        removed "&& gNumWindowsOpen" test from WM_INITMENU in FrameWndProc;
  60. //                                    added LOWORD stripping to WM_COMMAND switches (accelerators were being lost)
  61. //       <2>         07/03/97    rtm        made changes to compile with latest QT3.0 headers;
  62. //                                    ported to CodeWarrior IDE version 2.0
  63. //       <1>         07/02/97    rtm        first file; revised to personal coding style
  64. //       
  65. //////////
  66.  
  67. // TODO:
  68.  
  69. // application header files
  70. #include "WinFramework.h"
  71. #include "ComResource.h"
  72.  
  73. // Windows header files
  74. #include <shlobj.h>                                        // for SHAddToRecentDocs
  75.  
  76. // C runtime header files
  77. #include <stdlib.h>
  78. #include <malloc.h>
  79.  
  80. // global variables
  81. Rect                gLimitRect = {10, 10, 480, 640};    // max size for any window
  82.  
  83. BOOL                gShuttingDown = false;                // flag that keeps track of termination state
  84. HANDLE                ghInst;                                // the instance of this application
  85. HWND                ghWnd;                                // the MDI frame window; this window has the menu bar
  86. HWND                ghWndMDIClient;                     // the MDI client window
  87.  
  88. char                gChildName[] = "VRShellChild";
  89. char                gMovieType[] = "QuickTime Movie";
  90. Rect                gMCResizeBounds;
  91. BOOL                gShowGrowBox = true;
  92. int                    gNumWindowsOpen = 0;
  93. BOOL                gWeAreSizingWindow = false;
  94. BOOL                gWeAreCreatingWindow = false;
  95.  
  96. short                 gAppResFile = -1;                    // file reference number for this application's resource file
  97.  
  98. char                gAppName[20];                        // the name of this application
  99. LPSTR                gCmdLine;                            // the command line passed to WinMain
  100.  
  101. ModalFilterUPP        gModalFilterUPP = NULL;                // UPP to our custom dialog event filter
  102.  
  103.  
  104. //////////
  105. //
  106. // WinMain
  107. // The main function for this application.
  108. //
  109. //////////
  110.  
  111. int CALLBACK WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR theCmdLine, int nCmdShow)
  112. {
  113.     HANDLE                myAccel;
  114.     HWND                myWindowFrame;
  115.     MSG                    myMsg;
  116.     WNDCLASSEX            myWC;
  117.     char                myFileName[MAX_PATH];
  118.     DWORD                myLength;
  119.  
  120.     ghInst = hInstance;
  121.     gCmdLine = theCmdLine;
  122.     
  123.     if (hPrevInstance == NULL) {
  124.         LoadString(hInstance, IDS_APPNAME, gAppName, sizeof(gAppName));
  125.         
  126.         // register the frame window class
  127.         myWC.cbSize        = sizeof(WNDCLASSEX);
  128.         myWC.style         = CS_HREDRAW | CS_VREDRAW;
  129.         myWC.lpfnWndProc   = (WNDPROC)FrameWndProc;
  130.         myWC.cbClsExtra    = 0;
  131.         myWC.cbWndExtra    = 0;
  132.         myWC.hInstance     = hInstance;
  133.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
  134.         myWC.hCursor       = LoadCursor(NULL, IDC_ARROW);
  135.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  136.         myWC.lpszMenuName  = gAppName;
  137.         myWC.lpszClassName = gAppName;
  138.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 16, 16, 0);
  139.                                      
  140.         if (!RegisterClassEx(&myWC)) {
  141.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  142.                 return(false);
  143.         }
  144.  
  145.         // register the movie child window class
  146.         myWC.cbSize        = sizeof(WNDCLASSEX);
  147.         myWC.style         = 0;
  148.         myWC.lpfnWndProc   = (WNDPROC)MovieWndProc;
  149.         myWC.cbClsExtra    = 0;
  150.         myWC.cbWndExtra    = 0;
  151.         myWC.hInstance     = hInstance;
  152.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHILDICON));
  153.         // to avoid having QuickTime VR "fight" with the system over the cursor,
  154.         // we set the client area cursor to NULL; this means that for QuickTime
  155.         // movies, we'll need to change the cursor to an arrow manually; see the
  156.         // handling of the WM_MOUSEMOVE message in MovieWndProc
  157.         myWC.hCursor       = NULL;
  158.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  159.         myWC.lpszMenuName  = NULL;
  160.         myWC.lpszClassName = gChildName;
  161.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_CHILDICON), IMAGE_ICON, 16, 16, 0);
  162.                                      
  163.         if (!RegisterClassEx(&myWC)) {
  164.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  165.                 return(false);
  166.         }
  167.     }
  168.  
  169.     // load accelerators
  170.     myAccel = LoadAccelerators(hInstance, gAppName);
  171.  
  172.     // initialize QuickTime Media Layer
  173.     InitializeQTML(0L);
  174.     
  175.     // initialize QuickTime
  176.     EnterMovies();
  177.     
  178.     // get the application's resource file, if it exists
  179.     myLength = GetModuleFileName(NULL, myFileName, MAX_PATH);        // NULL means: the current process
  180.     if (myLength != 0) {
  181.         FSSpec            myFSSpec;
  182.         
  183.         NativePathNameToFSSpec(myFileName, &myFSSpec, 0L);
  184.  
  185.         gAppResFile = FSpOpenResFile(&myFSSpec, fsRdWrPerm);
  186.         if (gAppResFile != -1)
  187.             UseResFile(gAppResFile);
  188.     }
  189.  
  190.     // do any application-specific initialization that must occur before the frame window is created
  191.     InitApplication(kInitAppPhase_BeforeCreateFrameWindow);
  192.     
  193.     // create the main frame window
  194.     myWindowFrame = CreateWindow(gAppName, gAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  195.                                        CW_USEDEFAULT, 
  196.                                        CW_USEDEFAULT,
  197.                                      CW_USEDEFAULT, 
  198.                                      CW_USEDEFAULT,
  199.                                      NULL, 
  200.                                      NULL, 
  201.                                      hInstance, 
  202.                                      NULL);
  203.     ghWnd = myWindowFrame;
  204.     
  205.     // make sure we got a frame window
  206.     if (myWindowFrame == NULL)
  207.         return(myMsg.wParam);
  208.         
  209.     // show the window
  210.     ShowWindow(myWindowFrame, nCmdShow);
  211.     UpdateWindow(myWindowFrame);
  212.     
  213.     // do any application-specific initialization that must occur after the frame window is created
  214.     InitApplication(kInitAppPhase_AfterCreateFrameWindow);
  215.     
  216.     // process messages
  217.     while (GetMessage(&myMsg, NULL, 0, 0)) {
  218.         if (!TranslateMDISysAccel(ghWndMDIClient, &myMsg)) {
  219.             if (!TranslateAccelerator(myWindowFrame, myAccel, &myMsg)) {
  220.                 TranslateMessage(&myMsg);
  221.                 DispatchMessage(&myMsg);
  222.             }
  223.         }
  224.     }
  225.  
  226.     // terminate the QuickTime Media Layer
  227.     ExitMovies();
  228.     TerminateQTML();
  229.  
  230.     return(myMsg.wParam);            // returns the value from PostQuitMessage
  231. }
  232.  
  233.  
  234. //////////
  235. //
  236. // FrameWndProc
  237. // The window procedure for the MDI frame window.
  238. //
  239. //////////
  240.  
  241. LRESULT CALLBACK FrameWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  242. {
  243.     HWND                   myChild;
  244.  
  245.     switch (theMessage) {
  246.     
  247.         case WM_CREATE: {
  248.             CLIENTCREATESTRUCT        myClientStruct = {0};
  249.  
  250.             myClientStruct.hWindowMenu  = GetSubMenu(GetMenu(theWnd), WINDOWMENU);
  251.             myClientStruct.idFirstChild = IDM_WINDOWCHILD;
  252.             
  253.             // create the MDI client filling the client area
  254.             ghWndMDIClient = CreateWindow("mdiclient",
  255.                                          NULL,
  256.                                          WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
  257.                                          0, 0, 0, 0,
  258.                                          theWnd,
  259.                                          (HMENU)0xCAC,
  260.                                          ghInst,
  261.                                          (LPVOID)&myClientStruct);
  262.             
  263.             // set initial menu state
  264.             AdjustMenus(NULL, GetMenu(theWnd));
  265.             
  266.             if (ghWndMDIClient != NULL)
  267.                 ShowWindow(ghWndMDIClient, SW_SHOW);
  268.             
  269.             return(0);
  270.         }
  271.  
  272.         case WM_ACTIVATE:
  273.             // the MDI frame window is being activated or deactivated;
  274.             // activate or deactivate any active child window by sending this message to DefMDIChildProc 
  275.             myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  276.             if (IsWindow(myChild))
  277.                 SendMessage(myChild, WM_ACTIVATE, wParam, lParam);
  278.             break;
  279.  
  280.         case WM_COMMAND: {
  281.  
  282.             switch (LOWORD(wParam)) {
  283.                 case IDM_FILEOPEN:
  284.                     DoCreateMovieWindow(NULL, NULL);
  285.                     break;
  286.  
  287.                 case IDM_FILESAVE:
  288.                     // save the active child window
  289.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  290.                     if (IsWindow(myChild))
  291.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  292.                     return(0);
  293.  
  294.                 case IDM_FILECLOSE:
  295.                     // close the active child window
  296.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  297.                     if (IsWindow(myChild))
  298.                         SendMessage(myChild, WM_CLOSE, 0L, 0L);
  299.                     return(0);
  300.  
  301.                 case IDM_EXIT:
  302.                     // set our global flag to indicate we're shutting down
  303.                     gShuttingDown = true;
  304.                     
  305.                     // do application-specific processing that must occur before movie windows are closed
  306.                     StopApplication(kStopAppPhase_BeforeDestroyWindows);
  307.                     
  308.                     // close all open movie windows;
  309.                     // note that the user can cancel the shutting down
  310.                     SendMessage(theWnd, WM_COMMAND, (WPARAM)IDM_WINDOWCLOSEALL, 0L);
  311.                     
  312.                     // close the frame window, if we're still shutting down
  313.                     if (gShuttingDown)
  314.                         SendMessage(theWnd, WM_CLOSE, 0, 0L);
  315.                         
  316.                     return(0);
  317.  
  318.                 case IDM_WINDOWTILE:
  319.                     SendMessage(ghWndMDIClient, WM_MDITILE, 0, 0L);
  320.                     return(0);
  321.  
  322.                 case IDM_WINDOWCASCADE:
  323.                     SendMessage(ghWndMDIClient, WM_MDICASCADE, 0, 0L);
  324.                     return(0);
  325.  
  326.                 case IDM_WINDOWICONS:
  327.                     SendMessage(ghWndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  328.                     return(0);
  329.  
  330.                 case IDM_WINDOWCLOSEALL: {
  331.                     HWND    myWindow, myNextWindow;
  332.             
  333.                     // walk the window list and destroy any open windows
  334.                     myWindow = GetFrontMovieWindow();
  335.                     while (myWindow != NULL) {
  336.                         myNextWindow = GetNextMovieWindow(myWindow);
  337.                         SendMessage(myWindow, WM_CLOSE, 0L, 0L);
  338.                         myWindow = myNextWindow;
  339.                     }
  340.                     
  341.                     return(0);
  342.                 }
  343.  
  344.                 case IDM_ABOUT:
  345.                     ShowAboutBox();
  346.                     return(0);
  347.  
  348.                 default:                
  349.                     // pass this message to the active child window...
  350.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  351.                     if (IsWindow(myChild))
  352.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  353.  
  354.                     // ...then do any application-specific menu handling, if no movie windows are open...
  355.                     if (myChild == NULL)
  356.                         HandleApplicationMenu((UInt16)LOWORD(wParam));
  357.                     
  358.                     // ...and then pass it to DefFrameProc
  359.                     break;
  360.             }
  361.             break;
  362.         }
  363.  
  364.         case WM_OPENDROPPEDFILES:
  365.             // open any movie files that were dropped onto the application icon
  366.             DoOpenCommandLineMovies(gCmdLine);
  367.             return(0);
  368.  
  369.         case WM_INITMENU:
  370.             if (GetMenu(theWnd) == (HMENU)wParam)
  371.                 return(AdjustMenus((HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L), (HMENU)wParam));
  372.             return(1);
  373.  
  374.         case WM_CLOSE:
  375.             // if we're not already in the process of shutting down,
  376.             // simulate the selection of the Quit menu command
  377.             if (!gShuttingDown) {
  378.                 SendMessage(ghWnd, WM_COMMAND, IDM_EXIT, 0L);
  379.                 return(0);
  380.             }
  381.             break;
  382.             
  383.         case WM_DESTROY:
  384.             // do any application-specific shutdown
  385.             StopApplication(kStopAppPhase_AfterDestroyWindows);
  386.             PostQuitMessage(0);
  387.             break;
  388.     }
  389.     
  390.     return(DefFrameProc(theWnd, ghWndMDIClient, theMessage, wParam, lParam));
  391. }
  392.  
  393.  
  394. //////////
  395. //
  396. // MovieWndProc
  397. // The window procedure for a movie window.
  398. //
  399. //////////
  400.  
  401. LRESULT CALLBACK MovieWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  402. {
  403.     WPARAM                myWidth, myHeight;
  404.     MovieController        myMC = NULL;
  405.     Movie                myMovie = NULL;
  406.     WindowObject        myWindowObject = NULL;
  407.     MSG                    myMsg = {0};
  408.  
  409.     if (!gShuttingDown) {
  410.         // get the window object, movie, and movie controller for this window
  411.         myWindowObject = GetWindowObjectFromWindow(theWnd);
  412.         if (myWindowObject != NULL) {
  413.             myMC = (**myWindowObject).fController;
  414.             myMovie = (**myWindowObject).fMovie;
  415.         }
  416.     }
  417.  
  418.     // give the movie controller this message first
  419.     if (!gShuttingDown && myMC) {
  420.         EventRecord        myMacEvent;
  421.         LONG            myPoints = GetMessagePos();
  422.  
  423.         myMsg.hwnd = theWnd;
  424.         myMsg.message = theMessage;
  425.         myMsg.wParam = wParam;
  426.         myMsg.lParam = lParam;
  427.         myMsg.time = GetMessageTime();
  428.         myMsg.pt.x = LOWORD(myPoints);
  429.         myMsg.pt.y = HIWORD(myPoints);
  430.  
  431.         // translate a Windows event to a Mac event
  432.         WinEventToMacEvent(&myMsg, &myMacEvent);
  433.  
  434.         // pass the Mac event to the movie controller
  435.         MCIsPlayerEvent(myMC, (EventRecord *)&myMacEvent);
  436.     }
  437.  
  438.     switch (theMessage) {
  439.         case WM_CREATE:
  440.             // create some private storage
  441.             myWindowObject = (WindowObject)NewHandleClear(sizeof(WindowObjectRecord));
  442.             if (myWindowObject != NULL) {
  443.                 (**myWindowObject).fWindow = theWnd;
  444.                 (**myWindowObject).fController = NULL;
  445.                 (**myWindowObject).fInstance = NULL;
  446.                 (**myWindowObject).fAppData = NULL;
  447.             }
  448.  
  449.             SetWindowLong(theWnd, GWL_USERDATA, (LPARAM)myWindowObject);
  450.  
  451.             // associate a GrafPort with this window and set the port
  452.             CreatePortAssociation(theWnd, NULL, 0L);
  453.             MacSetPort(GetPortFromWindowReference(theWnd));
  454.             break;
  455.  
  456.         case WM_WINDOWPOSCHANGING:
  457.             // don't show the window until we have created a movie and
  458.             // can therefore properly size the window to contain the movie
  459.             if (gWeAreCreatingWindow) {
  460.                 WINDOWPOS    *lpWindowPos = (WINDOWPOS*)lParam;
  461.                 
  462.                 lpWindowPos->flags &= ~SWP_SHOWWINDOW;
  463.             }
  464.             break;
  465.  
  466.         case WM_SIZE:
  467.             // resize the movie and controller to fit the window
  468.             myWidth = LOWORD(lParam);
  469.             myHeight = HIWORD(lParam);
  470.             
  471.             if (!gWeAreSizingWindow && myMC) {
  472.                 Rect        myRect;
  473.                 
  474.                 myRect.top = 0;
  475.                 myRect.left = 0;
  476.                 myRect.right = myWidth;
  477.                 myRect.bottom = myHeight;
  478.                 
  479.                 MCSetControllerBoundsRect(myMC, &myRect);
  480.             }
  481.             break;
  482.  
  483.         case WM_MOUSEMOVE:
  484.             // for QuickTime movies (but NOT for QuickTime VR movies), set the cursor to the arrow cursor
  485.             if (myWindowObject != NULL)
  486.                 if ((**myWindowObject).fInstance == NULL)
  487.                     SetCursor(LoadCursor(NULL, IDC_ARROW));
  488.             break;
  489.  
  490.         case WM_PUMPMOVIE:
  491.             // we receive this message only to idle the movie
  492.             break;
  493.  
  494.         case WM_CHAR:
  495.             // do any application-specific key press handling
  496.             HandleApplicationKeyPress((char)wParam);
  497.             break;
  498.  
  499.         case WM_COMMAND: {
  500.  
  501.             switch (LOWORD(wParam)) {
  502.                             
  503.                 case IDM_FILESAVE:
  504.                     DoSaveMovie(theWnd);
  505.                     break;
  506.  
  507.                 case IDM_EDITUNDO:
  508.                     DoUndo(theWnd);
  509.                     break;
  510.  
  511.                 case IDM_EDITCUT:
  512.                     DoCut(theWnd);
  513.                     break;
  514.  
  515.                 case IDM_EDITCOPY:
  516.                     DoCopy(theWnd);
  517.                     break;
  518.  
  519.                 case IDM_EDITPASTE:
  520.                     DoPaste(theWnd);
  521.                     break;
  522.  
  523.                 case IDM_EDITCLEAR:
  524.                     DoClear(theWnd);
  525.                     break;
  526.                     
  527.                 case IDM_EDITSELECTALL:
  528.                     if (myMC != NULL)
  529.                         QTUtils_SelectAllMovie(myMC);
  530.                     break;
  531.                     
  532.                 default:
  533.                     // do any application-specific menu handling
  534.                     HandleApplicationMenu((UInt16)LOWORD(wParam));
  535.                     break;
  536.             }
  537.             
  538.             break;
  539.         }    // case WM_COMMAND
  540.  
  541.         case WM_GETMINMAXINFO:
  542.             CalcWindowMinMaxInfo(theWnd, (LPMINMAXINFO)lParam);
  543.             break;
  544.  
  545.         case WM_CLOSE:
  546.             // prepare to close the window, making sure that any changed data is saved or explicitly discarded;
  547.             // we can still cancel the window closing here
  548.             
  549.             myWindowObject = GetWindowObjectFromWindow(theWnd);
  550.             if (myWindowObject != NULL) {
  551.             
  552.                 // if the window's data is "dirty", give the user a chance to save it
  553.                 if ((**myWindowObject).fDirty) {
  554.                     int            myItem;
  555.                     char        myText[256];
  556.         
  557.                     // get the title of the window
  558.                     GetWindowText(theWnd, myText, sizeof(myText));
  559.         
  560.                     // display the "Save changes" dialog box
  561.                     myItem = DoCautionAlert(theWnd, IDS_SAVEDIALOG, MB_ICONEXCLAMATION, MB_YESNOCANCEL, gAppName, myText);
  562.                     switch (myItem) {
  563.                         case kSaveChanges:
  564.                             DoSaveMovie(theWnd);        // save the data in the window
  565.                             break;
  566.                             
  567.                         case kDontSaveChanges:
  568.                             break;                        // discard any unsaved changes (that is, don't do anything)
  569.                             
  570.                         case kCancelClose:
  571.                             gShuttingDown = false;        // do not close the window, and do not quit the application
  572.                             return(0);
  573.                         
  574.                         default:
  575.                             return(0);                    // unexpected item selected; just return
  576.                     }
  577.                 }
  578.             } // if (myWindowObject != NULL)
  579.             
  580.             // if we got to this point, it's okay to close and destroy the window
  581.             SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)theWnd, 0L);
  582.             break;
  583.  
  584.         case WM_DESTROY:
  585.             // when we get this message,
  586.             // the window has been removed from the screen and must be destroyed; no turning back!
  587.             myWindowObject = GetWindowObjectFromWindow(theWnd);
  588.             if (myWindowObject != NULL) {
  589.             
  590.                 myMC = (**myWindowObject).fController;
  591.                 myMovie = (**myWindowObject).fMovie;
  592.                                 
  593.                 // dispose movie and controller
  594.                 if (myMC != NULL) {
  595.                     MCSetActionFilterWithRefCon(myMC, NULL, 0);
  596.                     DisposeMovieController(myMC);
  597.                 }
  598.                 
  599.                 if (myMovie != NULL)
  600.                     DisposeMovie(myMovie);
  601.                     
  602.                 // do any application-specific window clean-up, then toss the window object
  603.                 RemoveApplicationWindowObject(myWindowObject);
  604.                 DisposeHandle((Handle)myWindowObject);
  605.             }
  606.         
  607.             SetWindowLong(theWnd, GWL_USERDATA, 0);
  608.  
  609.             // destroy the port association
  610.             DestroyPortAssociation((CGrafPtr)GetHWNDPort(theWnd));
  611.             
  612.             // decrement the count of open movie windows, if there are any
  613.             if (gNumWindowsOpen > 0)
  614.                 gNumWindowsOpen--;
  615.  
  616.             break;
  617.     }
  618.  
  619.     return(DefMDIChildProc(theWnd, theMessage, wParam, lParam));
  620. }
  621.  
  622.  
  623. //////////
  624. //
  625. // GetFile
  626. // Display the file-opening dialog box and return the name of the selected file (if any).
  627. //
  628. //////////
  629.  
  630. BOOL GetFile (char *theFileName)
  631. {
  632.     OPENFILENAME    myOFN = {0};
  633.  
  634.     // fill in the OPENFILENAME structure
  635.     memset(&myOFN, 0, sizeof(OPENFILENAME));    // first zero out the structure
  636.     *theFileName = '\0';
  637.     myOFN.lStructSize = sizeof(OPENFILENAME);
  638.     myOFN.hwndOwner = NULL;
  639.     myOFN.lpstrFile = (LPSTR)theFileName;
  640.     myOFN.nMaxFile  = 255;
  641.     myOFN.lpstrFilter  = "QuickTime Movies (*.mov) \0 *.mov\0All Files (*.*) \0 *.*\0";
  642.     myOFN.nFilterIndex = 1;
  643.     myOFN.lpstrInitialDir = NULL;
  644.     if (USEEXPLORERSTYLE)
  645.         myOFN.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK | OFN_EXPLORER;
  646.     else
  647.         myOFN.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  648.     myOFN.lCustData = kOpenDialogCustomData;
  649.     myOFN.lpfnHook = DialogProc;
  650.  
  651.     // present the file-opening dialog
  652.     if (GetOpenFileName(&myOFN))
  653.         return(true);
  654.     else
  655.         return(false);
  656. }
  657.  
  658.  
  659. //////////
  660. //
  661. // AdjustMenus 
  662. // Adjust the application's menus.
  663. //
  664. // The theWnd parameter is a handle to the active MDI *child* window, if any.
  665. //
  666. //////////
  667.  
  668. int AdjustMenus (HWND theWnd, HMENU theMenu)
  669. {
  670.     WindowObject        myWindowObject = NULL; 
  671.     MovieController        myMC = NULL;
  672.  
  673.     if (theWnd != NULL)
  674.         myWindowObject = GetWindowObjectFromWindow(theWnd);
  675.     
  676.     if (myWindowObject != NULL)
  677.         myMC = (**myWindowObject).fController;
  678.  
  679.     // configure the edit menu
  680.     if (myMC != NULL) {
  681.         long            myFlags;
  682.  
  683.         MCGetControllerInfo(myMC, &myFlags);
  684.  
  685.         EnableMenuItem(theMenu, IDM_EDITUNDO, myFlags & mcInfoUndoAvailable ? MF_ENABLED : MF_GRAYED);
  686.         EnableMenuItem(theMenu, IDM_EDITCUT, myFlags & mcInfoCutAvailable ? MF_ENABLED : MF_GRAYED);
  687.         EnableMenuItem(theMenu, IDM_EDITCOPY, myFlags & mcInfoCopyAvailable ? MF_ENABLED : MF_GRAYED);
  688.         EnableMenuItem(theMenu, IDM_EDITPASTE, myFlags & mcInfoPasteAvailable ? MF_ENABLED : MF_GRAYED);
  689.         EnableMenuItem(theMenu, IDM_EDITCLEAR, myFlags & mcInfoClearAvailable ? MF_ENABLED : MF_GRAYED);
  690.         EnableMenuItem(theMenu, IDM_EDITSELECTALL, myFlags & mcInfoEditingEnabled ? MF_ENABLED : MF_GRAYED);
  691.     } else {
  692.         EnableMenuItem(theMenu, IDM_EDITUNDO, MF_GRAYED);
  693.         EnableMenuItem(theMenu, IDM_EDITCUT, MF_GRAYED);
  694.         EnableMenuItem(theMenu, IDM_EDITCOPY, MF_GRAYED);
  695.         EnableMenuItem(theMenu, IDM_EDITPASTE,MF_GRAYED);
  696.         EnableMenuItem(theMenu, IDM_EDITCLEAR, MF_GRAYED);
  697.         EnableMenuItem(theMenu, IDM_EDITSELECTALL, MF_GRAYED);
  698.     }
  699.     
  700.     // enable the Close item if there are any movie windows opened, else disable
  701.     EnableMenuItem(theMenu, IDM_FILECLOSE, (gNumWindowsOpen) ? MF_ENABLED : MF_GRAYED);
  702.  
  703.     // enable the Save item if the movie window is dirty, else disable
  704.     if (myWindowObject != NULL)
  705.         EnableMenuItem(theMenu, IDM_FILESAVE, ((**myWindowObject).fDirty) ? MF_ENABLED : MF_GRAYED);
  706.     else
  707.         EnableMenuItem(theMenu, IDM_FILESAVE, MF_GRAYED);
  708.  
  709.     // adjust any application-specific menus
  710.     AdjustApplicationMenus(theWnd, theMenu);
  711.  
  712.     return(0);
  713. }
  714.  
  715.  
  716. //////////
  717. //
  718. // QuitFramework
  719. // Do any framework-specific shut-down.
  720. //
  721. //////////
  722.  
  723. void QuitFramework (void)
  724. {
  725.     // send a message to the MDI frame window telling it to close down and exit the application
  726.     SendMessage(ghWnd, WM_COMMAND, IDM_EXIT, 0L);
  727. }
  728.  
  729.  
  730. //////////
  731. //
  732. // SetupMovieWindowWithController
  733. // Configure the movie controller.
  734. //
  735. //////////
  736.  
  737. MovieController SetupMovieWindowWithController (Movie theMovie, HWND theWindow)
  738. {
  739.     MovieController            myMC;
  740.     Rect                    myRect;
  741.     WindowObject            myWindowObject;
  742.     
  743.     if ((theMovie == NULL) || (theWindow == NULL))
  744.         return(NULL);
  745.         
  746.     myWindowObject = GetWindowObjectFromWindow(theWindow);        // get our window specific data
  747.  
  748.     // resize the movie bounding rect and offset to 0,0
  749.     GetMovieBox(theMovie, &myRect);
  750.     MacOffsetRect(&myRect, -myRect.left, -myRect.top);
  751.     SetMovieBox(theMovie, &myRect);
  752.     AlignWindow(GetHWNDPort(theWindow), false, &myRect, NULL);
  753.  
  754.     // create the movie controller
  755.     myMC = NewMovieController(theMovie, &myRect, mcTopLeftMovie);
  756.     if (myMC == NULL)
  757.         return(NULL);
  758.         
  759.     // enable the default movie controller editing
  760.     MCEnableEditing(myMC, true);
  761.         
  762.     // suppress movie badge
  763.     MCDoAction(myMC, mcActionSetUseBadge, (void *)false);
  764.  
  765.     // set the initial looping state of the movie
  766.     QTUtils_SetLoopingStateFromFile(theMovie, myMC);
  767.     
  768.     // install an action filter that does any application-specific movie controller action processing
  769.     MCSetActionFilterWithRefCon(myMC, NewMCActionFilterWithRefConProc(ApplicationMCActionFilterProc), (long)myWindowObject);
  770.  
  771.     // add grow box for the movie controller
  772.     if (gShowGrowBox) {
  773.         RECT                myRect;
  774.  
  775.         GetWindowRect(GetDesktopWindow(), &myRect);
  776.         
  777.         OffsetRect(&myRect, -myRect.left, -myRect.top);
  778.         gMCResizeBounds.top = (short)myRect.top;
  779.         gMCResizeBounds.left = (short)myRect.left;
  780.         gMCResizeBounds.right = (short)myRect.right;
  781.         gMCResizeBounds.bottom = (short)myRect.bottom;
  782.  
  783.         MCDoAction(myMC, mcActionSetGrowBoxBounds, &gMCResizeBounds);
  784.     }
  785.     
  786.     // add any application-specific controller functionality
  787.     AddControllerFunctionality(myMC);
  788.         
  789.     return(myMC);
  790. }
  791.  
  792.  
  793. //////////
  794. //
  795. // DoOpenCommandLineMovies
  796. // Parse the command line when the application first starts up and
  797. // open as movie documents any files specified on the command line.
  798. //
  799. // Based on the routine ParseCmdLinePriv in GraphicImporter.c.
  800. //
  801. //////////
  802.  
  803. void DoOpenCommandLineMovies (LPSTR theCmdLine)
  804. {
  805.     LPSTR                myCmdLine;
  806.     FSSpec                myFSSpec;
  807.     SHFILEINFO            myFileInfo;
  808.     
  809.  
  810.     // make sure we've really got a command line for the current process
  811. //    if (theCmdLine == NULL)
  812.         myCmdLine = GetCommandLine();
  813. //    else
  814. //        myCmdLine = theCmdLine;
  815.  
  816.     // parse the command line
  817.     if (*myCmdLine) {
  818.         LPSTR            myTempLine;
  819.         
  820.         // the string preceding any white space is the name of the module (that is, the application)
  821.         myTempLine = strchr(myCmdLine, ' ');
  822.         if (myTempLine) {
  823.             myCmdLine = myTempLine;                  // skip the name of the application
  824.             while (*myCmdLine == ' ')
  825.                 myCmdLine++;                        // skip spaces to end of string or to first command
  826.  
  827.             while (*myCmdLine != '\0') {
  828.                 char     myFileName[MAX_PATH];
  829.                 char     myTempName[MAX_PATH];
  830.                 char     myBuffName[MAX_PATH];
  831.                 int     myIndex;
  832.                 
  833.                 // read thru the remaining string to find file names
  834.                 for (myIndex = 0; *myCmdLine != '\0'; myIndex++, myCmdLine++) {
  835.                     // if we encounter a space character, it might be a filename delimiter or a space in the filename;
  836.                     // we'll try to open the filename we have so far to see whether it's a valid filename; if not, the
  837.                     // space must be part of the filename we're constructing
  838.                     if (*myCmdLine == ' ') {
  839.                         HANDLE                myFindFile;
  840.                         WIN32_FIND_DATA        myFile;
  841.                     
  842.                         myTempName[myIndex] = '\0';
  843.                         strcpy(myBuffName, myTempName);
  844.                         
  845.                         myFindFile = FindFirstFile(myBuffName, &myFile);
  846.                         if (myFindFile != INVALID_HANDLE_VALUE) {
  847.                             // we found a file having the specified name; close our file search and
  848.                             // break out of our character-gobbling loop (since we've got a valid filename)
  849.                             FindClose(myFindFile);
  850.                             break;
  851.                         }
  852.                     }
  853.                 
  854.                     // if we made it here, *myCmdLine is part of the filename (possibly a space)
  855.                     myFileName[myIndex] = myTempName[myIndex] = *myCmdLine;
  856.                 }
  857.                 
  858.                 if (*myCmdLine != '\0')
  859.                     myCmdLine++;
  860.                 
  861.                 // add a terminating NULL character
  862.                 myFileName[myIndex] = '\0';
  863.  
  864.                 // make sure the filename picks out a QuickTime movie
  865.                 SHGetFileInfo(myFileName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_TYPENAME);
  866.                 if (strcmp(myFileInfo.szTypeName, gMovieType) != 0)
  867.                     continue;
  868.                 
  869.                 // make an FSSpec record
  870.                 NativePathNameToFSSpec(myFileName, &myFSSpec, 0L);
  871.  
  872.                 // open the file in a movie window
  873.                 DoCreateMovieWindow(NULL, &myFSSpec);
  874.             }
  875.  
  876.         } else
  877.             myCmdLine += strlen(myCmdLine);           // point to NULL
  878.     }
  879. }
  880.  
  881.  
  882. //////////
  883. //
  884. // DoCreateMovieWindow
  885. // Open a movie in a new movie window; returns true if successful.
  886. //
  887. // This function is called from several places in our framework. The following combinations are possible:
  888. //    Ñ theMovie == NULL, theFSSpec == NULL: no movie, no file; elicit a movie file from user and open it
  889. //    Ñ theMovie != NULL, theFSSpec == NULL: new movie, no file (yet)
  890. //    Ñ theMovie == NULL, theFSSpec != NULL: no movie, but we have an FSSpec; so just open the specified movie file
  891. //    Ñ theMovie != NULL, theFSSpec != NULL: [not supported here]
  892. //
  893. //////////
  894.  
  895. BOOL DoCreateMovieWindow (Movie theMovie, FSSpec *theFSSpec)
  896. {
  897.     WindowObject        myWindowObject = NULL;
  898.     MovieController        myMC = NULL;
  899.     WindowReference        myWindow = NULL;
  900.     FSSpec                myFSSpec;
  901.     Movie                myMovie = NULL;
  902.     short                myRefNum = 0;
  903.     short                myResID = 0;
  904.     DWORD                myVersion;
  905.     char                   myPathName[MAX_PATH];                // the full pathname of the file
  906.     char                myFileName[MAX_PATH];                // the movie file name
  907.     GrafPtr                mySavedPort;
  908.     OSErr                myErr = noErr;
  909.  
  910.     // get the current port; we may need to restore it if we cannot successfully create a new window
  911.     GetPort(&mySavedPort);
  912.     
  913.     // if we got neither a movie nor an FSSpec passed in, prompt the user for a movie file
  914.     if ((theMovie == NULL) && (theFSSpec == NULL)) {
  915.     
  916.         // display file-opening dialog box
  917.         if (!GetFile(myPathName))
  918.             goto bail;
  919.  
  920.         // add this document to the Documents list
  921.         SHAddToRecentDocs(SHARD_PATH, myPathName);
  922.  
  923.         // get the movie file name from the full pathname
  924.         GetDisplayName(myPathName, myFileName);
  925.         
  926.         // make an FSSpec record
  927.         FSMakeFSSpec(0, 0L, c2pstr(myPathName), &myFSSpec);
  928.     }
  929.     
  930.     // if we got only an FSSpec passed in, copy it into myFSSpec
  931.     if ((theMovie == NULL) && (theFSSpec != NULL)) {
  932.     
  933.         char                myTempName[MAX_PATH];
  934.         short                myLength;
  935.     
  936.         // get the movie file name from the name contained in the FSSpec
  937.         // (which is a Str255)
  938.         myLength = theFSSpec->name[0];
  939.         strncpy(myTempName, (char *)&theFSSpec->name[1], myLength);
  940.         myTempName[myLength] = '\0';
  941.         GetDisplayName(myTempName, myFileName);
  942.  
  943.         // add this document to the Documents list
  944.         SHAddToRecentDocs(SHARD_PATH, myTempName);
  945.  
  946.         // make an FSSpec record
  947.         FSMakeFSSpec(theFSSpec->vRefNum, theFSSpec->parID, theFSSpec->name, &myFSSpec);        
  948.     }
  949.     
  950.     // if we got no movie passed in, read one from the specified file
  951.     if (theMovie == NULL) {
  952.  
  953.         // ideally, we'd like read and write permission, but we'll settle for read-only permission
  954.         myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdWrPerm);
  955.         if (myErr != noErr)
  956.             myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdPerm);
  957.  
  958.         // if we couldn't open the file with even just read-only permission, bail....
  959.         if (myErr != noErr)
  960.             goto bail;
  961.  
  962.         // now fetch the first movie from the file
  963.         myResID = 0;
  964.         myErr = NewMovieFromFile(&myMovie, myRefNum, &myResID, NULL, newMovieActive, NULL);
  965.         if (myErr != noErr)
  966.             goto bail;
  967.         
  968.         CloseMovieFile(myRefNum);
  969.         
  970.     } else {
  971.         myMovie = theMovie;
  972.     }
  973.  
  974.     // at this point, myMovie is an open movie, but myFSSpec may or may not be a valid FSSpec
  975.     
  976.     // create a new window to display the movie in
  977.     gWeAreCreatingWindow = true;
  978.     
  979.     // create the child movie window
  980.     myVersion = GetVersion();
  981.     if ((myVersion < 0x80000000) || (LOBYTE(LOWORD(myVersion)) < 4)) {
  982.         // this is Windows NT or Win32s, so use the WM_MDICREATE message
  983.         MDICREATESTRUCT     mcs;
  984.  
  985.         mcs.szClass = gChildName;
  986.         mcs.szTitle = myFileName;
  987.         mcs.hOwner  = ghInst;
  988.         mcs.x       = CW_USEDEFAULT;
  989.         mcs.y       = CW_USEDEFAULT;
  990.         mcs.cx      = CW_USEDEFAULT;
  991.         mcs.cy      = CW_USEDEFAULT;
  992.         mcs.style   = 0;
  993.         mcs.lParam  = 0;
  994.  
  995.         myWindow = (HWND)SendMessage(ghWndMDIClient,
  996.                                     WM_MDICREATE,
  997.                                     0,
  998.                                     (LPARAM)(LPMDICREATESTRUCT)&mcs);
  999.     } else {
  1000.         // this method will only work with Windows 95, not Windows NT or Win32s
  1001.         myWindow = CreateWindowEx(WS_EX_MDICHILD,
  1002.                                    gChildName,
  1003.                                    myFileName,
  1004.                                    0,
  1005.                                    CW_USEDEFAULT,
  1006.                                    CW_USEDEFAULT,
  1007.                                    CW_USEDEFAULT,
  1008.                                    CW_USEDEFAULT,
  1009.                                    ghWndMDIClient, 
  1010.                                    NULL,
  1011.                                    ghInst,
  1012.                                    0);
  1013.     }
  1014.     
  1015.     gWeAreCreatingWindow = false;
  1016.     if (myWindow == NULL)
  1017.         goto bail;
  1018.  
  1019.     MacSetPort(GetPortFromWindowReference(myWindow));
  1020.     myWindowObject = GetWindowObjectFromWindow(myWindow);
  1021.     if (myWindowObject == NULL)
  1022.         goto bail;
  1023.         
  1024.     // set the window title
  1025.     SetWindowText(myWindow, myFileName);
  1026.  
  1027.     // make sure the movie uses the window GWorld in all situations
  1028.     SetMovieGWorld(myMovie, (CGrafPtr)GetPortFromWindowReference(myWindow), GetGWorldDevice((CGrafPtr)GetPortFromWindowReference(myWindow)));
  1029.  
  1030.     // create and configure the movie controller
  1031.     myMC = SetupMovieWindowWithController(myMovie, myWindow);
  1032.  
  1033.     // store movie info in the window record
  1034.     (**myWindowObject).fMovie = myMovie;
  1035.     (**myWindowObject).fController = myMC;
  1036.     (**myWindowObject).fFileResID = myResID;
  1037.     (**myWindowObject).fFileRefNum = myRefNum;
  1038.     (**myWindowObject).fCanResizeWindow = true;
  1039.     (**myWindowObject).fDirty = false;
  1040.     (**myWindowObject).fInstance = NULL;
  1041.     (**myWindowObject).fAppData = NULL;
  1042.     (**myWindowObject).fFileFSSpec = myFSSpec;
  1043.     
  1044.     // do any application-specific window object initialization
  1045.     InitApplicationWindowObject(myWindowObject);
  1046.     
  1047.     // size the window to fit the movie and controller
  1048.     SizeWindowToMovie(myWindowObject);
  1049.         
  1050.     // show the window
  1051.     ShowWindow(myWindow, SW_SHOW);
  1052.     UpdateWindow(myWindow);
  1053.  
  1054.     // one more movie window has been opened
  1055.     gNumWindowsOpen++;
  1056.  
  1057.     return(true);
  1058.  
  1059. bail:
  1060.     if (myWindow != NULL)
  1061.         SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)myWindow, 0L);
  1062.         
  1063.     if (myMC != NULL)
  1064.         DisposeMovieController(myMC);
  1065.         
  1066.     if (myMovie != NULL)
  1067.         DisposeMovie(myMovie);
  1068.         
  1069.     if (myRefNum != 0)
  1070.         CloseMovieFile(myRefNum);
  1071.         
  1072.     MacSetPort(mySavedPort);    // restore the port that was active when this function was called
  1073.  
  1074.     return(false);
  1075. }
  1076.  
  1077.  
  1078. //////////
  1079. //
  1080. // DoSaveMovie
  1081. // Save a movie.
  1082. //
  1083. //////////
  1084.  
  1085. static void DoSaveMovie (HWND theWnd)
  1086. {
  1087.     WindowObject        myWindowObject = NULL;
  1088.     Movie                 myMovie = NULL;
  1089.     OSErr                myErr = noErr;
  1090.  
  1091.     // get the window object associated with the specified window
  1092.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1093.     if (myWindowObject == NULL)
  1094.         return;
  1095.  
  1096.     myMovie = (**myWindowObject).fMovie;
  1097.     if (myMovie == NULL)
  1098.         return;
  1099.         
  1100.     // open the movie resource file, update the resource, and then close it again
  1101.     myErr = OpenMovieFile(&(**myWindowObject).fFileFSSpec, &(**myWindowObject).fFileRefNum, fsRdWrPerm);
  1102.     if (myErr != noErr)
  1103.         return;
  1104.     
  1105.     myErr = UpdateMovieResource(myMovie, (**myWindowObject).fFileRefNum, (**myWindowObject).fFileResID, NULL);
  1106.     
  1107.     CloseMovieFile((**myWindowObject).fFileRefNum);
  1108.  
  1109.     (**myWindowObject).fDirty = false;
  1110. }
  1111.  
  1112.  
  1113. //////////
  1114. //
  1115. // DoCut
  1116. // Cut a movie segment.
  1117. //
  1118. //////////
  1119.  
  1120. static void DoCut (HWND theWnd)
  1121. {
  1122.     MovieController        myMC = NULL;
  1123.     WindowObject        myWindowObject = NULL;
  1124.     
  1125.     // get the window object associated with the specified window
  1126.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1127.     if (myWindowObject == NULL)
  1128.         return;
  1129.  
  1130.     myMC = (**myWindowObject).fController;
  1131.     if (myMC != NULL) {
  1132.         Movie            myMovie;
  1133.         
  1134.         myMovie = MCCut(myMC);                // cut the segment
  1135.         if (myMovie != NULL) {
  1136.             PutMovieOnScrap(myMovie, 0L);    // place the segment into the scrap
  1137.             DisposeMovie(myMovie);
  1138.         }
  1139.         
  1140.         (**myWindowObject).fDirty = true;
  1141.     }
  1142. }
  1143.  
  1144.  
  1145. //////////
  1146. //
  1147. // DoCopy
  1148. // Copy a movie segment.
  1149. //
  1150. //////////
  1151.  
  1152. static void DoCopy (HWND theWnd)
  1153. {
  1154.     MovieController        myMC = NULL;
  1155.     WindowObject        myWindowObject = NULL;
  1156.     
  1157.     // get the window object associated with the specified window
  1158.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1159.     if (myWindowObject == NULL)
  1160.         return;
  1161.  
  1162.     myMC = (**myWindowObject).fController;
  1163.     if (myMC != NULL) {
  1164.         Movie            myMovie;
  1165.         
  1166.         myMovie = MCCopy(myMC);                // copy the segment
  1167.         if (myMovie != NULL) {
  1168.             PutMovieOnScrap(myMovie, 0L);    // place the segment into the scrap
  1169.             DisposeMovie(myMovie);
  1170.         }
  1171.     }
  1172. }
  1173.  
  1174.  
  1175. //////////
  1176. //
  1177. // DoPaste
  1178. // Paste a movie segment.
  1179. //
  1180. //////////
  1181.  
  1182. static void DoPaste (HWND theWnd)
  1183. {
  1184.     MovieController        myMC = NULL;
  1185.     WindowObject        myWindowObject = NULL;
  1186.     
  1187.     // get the window object associated with the specified window
  1188.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1189.     if (myWindowObject == NULL)
  1190.         return;
  1191.  
  1192.     myMC = (**myWindowObject).fController;
  1193.     if (myMC != NULL) {
  1194.         MCPaste(myMC, NULL);
  1195.         (**myWindowObject).fDirty = true;
  1196.     }
  1197. }
  1198.  
  1199.  
  1200. //////////
  1201. //
  1202. // DoClear
  1203. // Clear a movie segment.
  1204. //
  1205. //////////
  1206.  
  1207. static void DoClear (HWND theWnd)
  1208. {
  1209.     MovieController        myMC = NULL;
  1210.     WindowObject        myWindowObject = NULL;
  1211.     
  1212.     // get the window object associated with the specified window
  1213.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1214.     if (myWindowObject == NULL)
  1215.         return;
  1216.  
  1217.     myMC = (**myWindowObject).fController;
  1218.     if (myMC != NULL) {
  1219.         MCClear(myMC);
  1220.         (**myWindowObject).fDirty = true;
  1221.     }
  1222. }
  1223.  
  1224.  
  1225. //////////
  1226. //
  1227. // DoUndo
  1228. // Undo an editing operation.
  1229. //
  1230. //////////
  1231.  
  1232. static void DoUndo (HWND theWnd)
  1233. {
  1234.     MovieController        myMC = NULL;
  1235.     WindowObject        myWindowObject = NULL;
  1236.     
  1237.     // get the window object associated with the specified window
  1238.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1239.     if (myWindowObject == NULL)
  1240.         return;
  1241.  
  1242.     myMC = (**myWindowObject).fController;
  1243.     if (myMC != NULL) {
  1244.         MCUndo(myMC);
  1245.         (**myWindowObject).fDirty = true;
  1246.     }
  1247. }
  1248.  
  1249.  
  1250. //////////
  1251. //
  1252. // GetDisplayName
  1253. // Given a full pathname, return the part that trails the rightmost path separator,
  1254. // in long file name format (not in 8.3 format).
  1255. //
  1256. //////////
  1257.  
  1258. static void GetDisplayName (char *thePathName, char *theDispName)
  1259. {
  1260.     SHFILEINFO            myFileInfo;
  1261.     
  1262.     SHGetFileInfo(thePathName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_DISPLAYNAME);
  1263.     strcpy(theDispName, myFileInfo.szDisplayName);
  1264. }
  1265.  
  1266.  
  1267. //////////
  1268. //
  1269. // SizeWindowToMovie
  1270. // Set the window size to exactly fit the movie and controller (if visible).
  1271. //
  1272. //////////
  1273.  
  1274. void SizeWindowToMovie (WindowObject theWindowObject)
  1275. {
  1276.     Rect                myMovieBounds;
  1277.     MovieController        myMC = NULL;
  1278.     Movie                myMovie = NULL;
  1279.  
  1280.     gWeAreSizingWindow = true;
  1281.  
  1282.     if (theWindowObject == NULL)
  1283.         return;
  1284.         
  1285.     myMC = (**theWindowObject).fController;
  1286.     myMovie = (**theWindowObject).fMovie;
  1287.  
  1288.     if (MCGetVisible(myMC))
  1289.         MCGetControllerBoundsRect(myMC, &myMovieBounds);
  1290.     else
  1291.         GetMovieBox(myMovie, &myMovieBounds);
  1292.     
  1293.     // make sure that the movie has a non-zero width;
  1294.     // a zero height is okay (for example, with a music movie with no controller bar)
  1295.     if (myMovieBounds.right - myMovieBounds.left == 0) {
  1296.         myMovieBounds.left = 0;
  1297.         myMovieBounds.right = GetWindowWidth((**theWindowObject).fWindow);
  1298.     }
  1299.     
  1300.     SizeWindow(GetPortFromWindowReference((**theWindowObject).fWindow),
  1301.                                             myMovieBounds.right - myMovieBounds.left,
  1302.                                             myMovieBounds.bottom - myMovieBounds.top,
  1303.                                             true);
  1304.                                                 
  1305.     gWeAreSizingWindow = false;
  1306. }
  1307.  
  1308.  
  1309. //////////
  1310. //
  1311. // ShowAboutBox 
  1312. // Display and manage the About dialog box.
  1313. //
  1314. //////////
  1315.  
  1316. static void ShowAboutBox (void)
  1317. {
  1318.     DialogBox(ghInst, MAKEINTRESOURCE(IDD_ABOUT), ghWnd, (DLGPROC)DialogProc);
  1319. }
  1320.  
  1321.  
  1322. //////////
  1323. //
  1324. // DoCautionAlert 
  1325. // Display and manage a caution alert.
  1326. //
  1327. // Based on ShowUserMessage by Stephen Chernicoff, in his WiniEdit application
  1328. // (as described in the book "From Mac to Windows" on CodeWarrior reference CD).
  1329. //
  1330. //////////
  1331.  
  1332. int DoCautionAlert (HWND theWnd, UINT theID, UINT theIconStyle, UINT theButtonStyle, LPSTR theTitle, LPSTR theArgument)
  1333. {
  1334.     char            myTemplate[kAlertMessageMaxLength];
  1335.     char            myText[kAlertMessageMaxLength];
  1336.     UINT            myStyle;
  1337.     int                myItem;
  1338.     
  1339.     // beep, to get the user's attention (just like CautionAlert on MacOS)
  1340.     DoBeep();
  1341.     
  1342.     // load the message text template from a resource
  1343.     LoadString(ghInst, theID, myTemplate, sizeof(myTemplate));
  1344.     
  1345.     // insert argument into the message text template, to get the message text
  1346.     wsprintf(myText, myTemplate, theArgument);
  1347.     
  1348.     // set the dialog box style
  1349.     myStyle = theIconStyle | theButtonStyle | MB_APPLMODAL | MB_SETFOREGROUND;
  1350.  
  1351.     // display the dialog box
  1352.     myItem = MessageBox(theWnd, myText, theTitle, myStyle);
  1353.     
  1354.     return(myItem);
  1355. }
  1356.  
  1357.  
  1358. //////////
  1359. //
  1360. // DialogProc 
  1361. // Dialog callback procedure.
  1362. //
  1363. //////////
  1364.  
  1365. static UINT APIENTRY DialogProc (HWND theDialog, UINT theMessage, WPARAM wParam, LPARAM lParam)
  1366. {
  1367.     BOOL    isHandled = false;
  1368.  
  1369.     switch (theMessage) {
  1370.     
  1371.         case WM_INITDIALOG: {
  1372.             Point            myPoint;
  1373.             long            myWidth;
  1374.             long            myHeight;
  1375.             RECT            myRect;
  1376.             RECT            myDeskRect;
  1377.             HWND            myWindow;
  1378.             OPENFILENAME    *myOFNPtr = (OPENFILENAME *)lParam;
  1379.             
  1380.             myWindow = theDialog;
  1381.                 
  1382.             // check whether theDialog is the Open File common dialog box
  1383.             
  1384.             // we need to do this because, for the Open File dialog box, theDialog isn't
  1385.             // the actual visible dialog box, but an invisible child of the visible dialog box;
  1386.             // for WM_INITDIALOG, lParam is the address of the structure passed to GetOpenFileName,
  1387.             // so we can just look for the value we previously put into the lCustData field
  1388.             // to make sure that we've got the correct dialog.
  1389.             if (myOFNPtr != NULL)
  1390.                 if (myOFNPtr->lCustData == kOpenDialogCustomData)
  1391.                     myWindow = GetParent(theDialog);
  1392.                 
  1393.             // center the dialog window on the screen
  1394.             GetWindowRect(myWindow, &myRect);
  1395.             myWidth = myRect.right - myRect.left;
  1396.             myHeight = myRect.bottom - myRect.top;
  1397.             GetWindowRect(GetDesktopWindow(), &myDeskRect);
  1398.             myPoint.h = (short)((myDeskRect.right + myDeskRect.left)/2 - myWidth/2);
  1399.             myPoint.v = (short)((myDeskRect.top + myDeskRect.bottom)/3 - myHeight/3);
  1400.             SetWindowPos(myWindow, 0, myPoint.h, myPoint.v, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  1401.             
  1402.             // let Windows set the input focus
  1403.             isHandled = true;
  1404.             break;
  1405.         }
  1406.         
  1407.         case WM_CLOSE:
  1408.             EndDialog(theDialog, IDOK);
  1409.             isHandled = true;
  1410.             break;
  1411.         
  1412.         case WM_COMMAND:
  1413.             switch (LOWORD(wParam)) {
  1414.                 case IDOK:
  1415.                     EndDialog(theDialog, IDOK);
  1416.                     isHandled = true;
  1417.                     break;
  1418.                 default:
  1419.                     isHandled = false;
  1420.                     break;
  1421.             }
  1422.             break;
  1423.         
  1424.         default:
  1425.             isHandled = false;
  1426.             break;
  1427.     }
  1428.  
  1429.     return(isHandled);
  1430. }
  1431.  
  1432.  
  1433. //////////
  1434. //
  1435. // CalcWindowMinMaxInfo 
  1436. // Get minimum and maximum possible size of this window.
  1437. //
  1438. //////////
  1439.  
  1440. static void CalcWindowMinMaxInfo (HWND theWnd, LPMINMAXINFO lpMinMax)
  1441. {
  1442.     WindowObject        myWindowObject = NULL;
  1443.     MovieController        myMC = NULL;
  1444.     Movie                myMovie = NULL;
  1445.  
  1446.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1447.     if (myWindowObject != NULL) {
  1448.         myMC = (**myWindowObject).fController;
  1449.         myMovie = (**myWindowObject).fMovie;
  1450.     }
  1451.  
  1452.     if (myMC && myMovie) {
  1453.         Rect            myMovieBox;
  1454.         short            myControllerHeight = 0;                    // assume there's no controller bar
  1455.         
  1456.         if (MCGetVisible(myMC))
  1457.             myControllerHeight = QTVRUtils_GetControllerBarHeight(myMC);
  1458.  
  1459.         lpMinMax->ptMinTrackSize.x = gMCResizeBounds.left + (2 * GetSystemMetrics(SM_CXFRAME));
  1460.         
  1461.         GetMovieBox(myMovie, &myMovieBox);
  1462.         if (myMovieBox.bottom - myMovieBox.top != 0)
  1463.             lpMinMax->ptMinTrackSize.y = 
  1464.                 gMCResizeBounds.top +                            // growbounds height +
  1465.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  1466.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  1467.                 -1 +                                            // fudge factor +
  1468.                 myControllerHeight;                                // movie controller bar height
  1469.         else
  1470.             lpMinMax->ptMaxSize.y =
  1471.             lpMinMax->ptMaxTrackSize.y =
  1472.             lpMinMax->ptMinTrackSize.y = 
  1473.                 0 +                                                // height of audio only movie +
  1474.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  1475.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  1476.                 -1 +                                            // fudge factor +
  1477.                 myControllerHeight;                                // movie controller bar height
  1478.     }
  1479. }
  1480.  
  1481.  
  1482. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1483. //
  1484. // Window walking utilities.
  1485. //
  1486. // Use these two functions to iterate through all open movie windows belonging to the application.
  1487. //
  1488. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1489.  
  1490. //////////
  1491. //
  1492. // GetFrontMovieWindow
  1493. // Return a reference to the frontmost movie window.
  1494. //
  1495. //////////
  1496.  
  1497. WindowReference GetFrontMovieWindow (void)
  1498. {
  1499.     return(GetWindow(ghWndMDIClient, GW_CHILD));
  1500. }
  1501.  
  1502.  
  1503. //////////
  1504. //
  1505. // GetNextMovieWindow
  1506. // Return a reference to the next movie window.
  1507. //
  1508. //////////
  1509.  
  1510. WindowReference GetNextMovieWindow (WindowReference theWindow)
  1511. {
  1512.     return(GetWindow(theWindow, GW_HWNDNEXT));
  1513. }
  1514.  
  1515.  
  1516. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1517. //
  1518. // Data retrieval utilities.
  1519. //
  1520. // Use the following functions to retrieve the window object, the application-specific data, or the movie
  1521. // controller that is associated with a window.
  1522. //
  1523. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1524.  
  1525. //////////
  1526. //
  1527. // GetWindowObjectFromFrontWindow
  1528. // Get the window object associated with the frontmost child window.
  1529. //
  1530. //////////
  1531.  
  1532. WindowObject GetWindowObjectFromFrontWindow (void)
  1533. {
  1534.     HWND               myChild;
  1535.  
  1536.     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  1537.     return(GetWindowObjectFromWindow(myChild));
  1538. }
  1539.  
  1540.  
  1541. //////////
  1542. //
  1543. // GetWindowObjectFromWindow
  1544. // Get the window object associated with the specified window.
  1545. //
  1546. //////////
  1547.  
  1548. WindowObject GetWindowObjectFromWindow (HWND theWnd)
  1549. {
  1550.     WindowObject        myWindowObject = NULL;
  1551.  
  1552.     if (theWnd == NULL)
  1553.         return(NULL);
  1554.         
  1555.     myWindowObject = (WindowObject)GetWindowLong(theWnd, GWL_USERDATA);
  1556.  
  1557.     // make sure this is a window object
  1558.     if (!IsWindowObjectOurs(myWindowObject))
  1559.         return(NULL);
  1560.         
  1561.     return(myWindowObject);
  1562. }
  1563.  
  1564.  
  1565. //////////
  1566. //
  1567. // GetMCFromFrontWindow
  1568. // Get the movie controller (if any) associated with the frontmost child window.
  1569. //
  1570. //////////
  1571.  
  1572. MovieController GetMCFromFrontWindow (void)
  1573. {
  1574.     MovieController     myMC = NULL;
  1575.     WindowObject        myWindowObject = NULL;
  1576.         
  1577.     myWindowObject = GetWindowObjectFromFrontWindow();
  1578.     if (myWindowObject != NULL)
  1579.         myMC = (**myWindowObject).fController;
  1580.         
  1581.     return(myMC);
  1582. }
  1583.  
  1584.  
  1585. //////////
  1586. //
  1587. // GetMCFromWindow
  1588. // Get the movie controller (if any) associated with the specified window.
  1589. //
  1590. //////////
  1591.  
  1592. MovieController GetMCFromWindow (WindowReference theWindow)
  1593. {
  1594.     MovieController     myMC = NULL;
  1595.     WindowObject        myWindowObject = NULL;
  1596.         
  1597.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1598.     if (myWindowObject != NULL)
  1599.         myMC = (**myWindowObject).fController;
  1600.         
  1601.     return(myMC);
  1602. }
  1603.  
  1604.  
  1605. //////////
  1606. //
  1607. // GetQTVRInstanceFromFrontWindow
  1608. // Get the QTVRInstance (if any) associated with the frontmost child window.
  1609. //
  1610. //////////
  1611.  
  1612. QTVRInstance GetQTVRInstanceFromFrontWindow (void)
  1613. {
  1614.     QTVRInstance         myInstance = NULL;
  1615.     WindowObject        myWindowObject = NULL;
  1616.  
  1617.     myWindowObject = GetWindowObjectFromFrontWindow();
  1618.     if (myWindowObject != NULL)
  1619.         myInstance = (**myWindowObject).fInstance;
  1620.         
  1621.     return(myInstance);
  1622. }
  1623.  
  1624.  
  1625. //////////
  1626. //
  1627. // GetAppDataFromFrontWindow
  1628. // Get the application-specific data associated with the frontmost child window.
  1629. //
  1630. //////////
  1631.  
  1632. Handle GetAppDataFromFrontWindow (void)
  1633. {
  1634.     HWND               myChild;
  1635.  
  1636.     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  1637.     return(GetAppDataFromWindow(myChild));
  1638. }
  1639.  
  1640.  
  1641. //////////
  1642. //
  1643. // GetAppDataFromWindow
  1644. // Get the application-specific data associated with the specified window.
  1645. //
  1646. //////////
  1647.  
  1648. Handle GetAppDataFromWindow (HWND theWnd)
  1649. {
  1650.     WindowObject        myWindowObject = NULL;
  1651.     
  1652.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1653.     if (myWindowObject == NULL)
  1654.         return(NULL);
  1655.     else
  1656.         return(GetAppDataFromWindowObject(myWindowObject));
  1657. }
  1658.  
  1659.  
  1660. //////////
  1661. //
  1662. // GetAppDataFromWindowObject
  1663. // Get the application-specific data associated with the specified window object.
  1664. //
  1665. //////////
  1666.  
  1667. Handle GetAppDataFromWindowObject (WindowObject theWindowObject)
  1668. {
  1669.     Handle                myAppData = NULL;
  1670.             
  1671.     // make sure this is a window object belonging to our application
  1672.     if (!IsWindowObjectOurs(theWindowObject))
  1673.         return(myAppData);
  1674.     
  1675.     // get the app data handle from the window object
  1676.     myAppData = (**theWindowObject).fAppData;
  1677.     
  1678.     return(myAppData);
  1679. }
  1680.  
  1681.  
  1682. //////////
  1683. //
  1684. // IsWindowObjectOurs
  1685. // Does the specified window object belong to our application?
  1686. //
  1687. // ÑÑÑCurrently this is a no-op.ÑÑÑ
  1688. //
  1689. //////////
  1690.  
  1691. Boolean IsWindowObjectOurs (WindowObject theWindowObject)
  1692. {
  1693. #pragma unused(theWindowObject)
  1694.  
  1695.     return(true);
  1696. }
  1697.  
  1698.  
  1699. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1700. //
  1701. // Miscellaneous utilities.
  1702. //
  1703. // Use the following functions to play beeps, manipulate menus, and do other miscellaneous things. These
  1704. // functions are intended for use in cross-platform code.
  1705. //
  1706. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1707.  
  1708. //////////
  1709. //
  1710. // DoBeep
  1711. // Beep.
  1712. //
  1713. //////////
  1714.  
  1715. void DoBeep (void)
  1716. {
  1717.     MessageBeep(MB_OK);
  1718. }
  1719.  
  1720.  
  1721. //////////
  1722. //
  1723. // SetMenuState
  1724. // Set the enabled/disabled state of a menu.
  1725. //
  1726. //////////
  1727.  
  1728. void SetMenuState (MenuReference theMenu, UInt16 theMenuRank, short theState)
  1729. {
  1730.     SetMenuItemState(theMenu, theMenuRank, theState | MF_BYPOSITION);
  1731. }
  1732.  
  1733.  
  1734. //////////
  1735. //
  1736. // SetMenuItemState
  1737. // Set the enabled/disabled state of a menu item.
  1738. //
  1739. //////////
  1740.  
  1741. void SetMenuItemState (MenuReference theMenu, UInt16 theMenuItem, short theState)
  1742. {
  1743.     EnableMenuItem(theMenu, (UINT)theMenuItem, (UINT)theState);
  1744. }
  1745.  
  1746.  
  1747. //////////
  1748. //
  1749. // SetMenuItemLabel
  1750. // Set the label (that is, the text) of a menu item.
  1751. //
  1752. //////////
  1753.  
  1754. void SetMenuItemLabel (MenuReference theMenu, UInt16 theMenuItem, char *theText)
  1755. {
  1756.     ModifyMenu(theMenu, (UINT)theMenuItem, MF_BYCOMMAND | MF_STRING, (UINT)theMenuItem, (LPSTR)theText);
  1757. }
  1758.  
  1759.  
  1760. //////////
  1761. //
  1762. // SetMenuItemCheck
  1763. // Set the check mark state state of a menu item.
  1764. //
  1765. //////////
  1766.  
  1767. void SetMenuItemCheck (MenuReference theMenu, UInt16 theMenuItem, Boolean theState)
  1768. {
  1769.     CheckMenuItem(theMenu, (UINT)theMenuItem, theState ? MF_CHECKED : MF_UNCHECKED);
  1770. }
  1771.  
  1772.  
  1773. //////////
  1774. //
  1775. // GetPortFromWindowReference 
  1776. // Return the graphics port associated with a window reference.
  1777. //
  1778. //////////
  1779.  
  1780. GrafPtr GetPortFromWindowReference (WindowReference theWindow)
  1781. {
  1782.     GrafPtr        myPort = NULL;
  1783.     
  1784.     if (theWindow != NULL)
  1785.         myPort = (GrafPtr)GetHWNDPort(theWindow);
  1786.     
  1787.     return(myPort);
  1788. }
  1789.  
  1790.  
  1791. //////////
  1792. //
  1793. // GetWindowReferenceFromPort
  1794. // Return the window reference associated with a graphics port.
  1795. //
  1796. //////////
  1797.  
  1798. WindowReference GetWindowReferenceFromPort (GrafPtr thePort)
  1799. {
  1800.     WindowReference        myWindow = NULL;
  1801.     
  1802.     if (thePort != NULL)
  1803.         myWindow = (WindowReference)GetPortHWND(thePort);
  1804.     
  1805.     return(myWindow);
  1806. }
  1807.  
  1808.  
  1809. //////////
  1810. //
  1811. // GetWindowWidth
  1812. // Return the width of the specified window.
  1813. //
  1814. //////////
  1815.  
  1816. short GetWindowWidth (WindowReference theWindow)
  1817. {
  1818.     short        myWidth = 0;
  1819.     RECT        myRect;
  1820.     
  1821.     if (theWindow != NULL)
  1822.         if (GetWindowRect(theWindow, &myRect))
  1823.             myWidth = myRect.right - myRect.left;
  1824.  
  1825.     return(myWidth);
  1826. }
  1827.