home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / TxtPlayer / app.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  42.1 KB  |  1,547 lines

  1. //------------------------------------------------------------------------------
  2. // File: app.cpp
  3. //
  4. // Desc: DirectShow sample code - application code for TxtPlayer sample
  5. //
  6. // Copyright (c) 1994 - 2001, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <atlbase.h>
  11. #include <atlconv.cpp>
  12. #include <mmreg.h>
  13. #include <commctrl.h>
  14.  
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17.  
  18. #include "project.h"
  19. #include "mpgcodec.h"
  20.  
  21.  
  22. /* -------------------------------------------------------------------------
  23. ** Global variables that are initialized at run time and then stay constant.
  24. ** -------------------------------------------------------------------------
  25. */
  26. HINSTANCE           hInst;
  27. HICON               hIconVideoCd;
  28. HWND                hwndApp;
  29. HWND                g_hwndToolbar;
  30. HWND                g_hwndStatusbar;
  31. HWND                g_hwndTrackbar;
  32. CMpegMovie          *pMpegMovie;
  33. double              g_TrackBarScale = 1.0;
  34. BOOL                g_bPlay = FALSE;
  35. int                 dyToolbar, dyStatusbar, dyTrackbar;
  36. int                 FrameStepCount;
  37.  
  38.  
  39. /* -------------------------------------------------------------------------
  40. ** True Globals - these may change during execution of the program.
  41. ** -------------------------------------------------------------------------
  42. */
  43. TCHAR               g_achFileName[MAX_PATH];
  44. OPENFILENAME        ofn;
  45. DWORD               g_State = VCD_NO_CD;
  46. LONG                lMovieOrgX, lMovieOrgY;
  47. int                 g_TimeFormat = IDM_TIME;
  48.  
  49. extern RECENTFILES  aRecentFiles[MAX_RECENT_FILES];
  50. extern int          nRecentFiles;
  51.  
  52. char                g_szLine21Text[4 * 41];
  53.  
  54. const char  g_Line21Msg[] =
  55. /*        10        20        30
  56.  0123456789012345678901234567890123456789
  57. */
  58. "Here is some random text used to        "
  59. "demonstrate how Line21 can be rendered  "
  60. "using the new Video Mixing Renderer.    "
  61. "The font used to render the text is     "
  62. "resized as the video destination        "
  63. "rectangle changes.  This means that the "
  64. "text is always shown with the highest   "
  65. "possible image quality.  Also, you will "
  66. "notice that the text is Alpha Blended   "
  67. "with the underlying video, which is     "
  68. "only possible using the new VMR.        ";
  69.  
  70.  
  71. LRESULT CALLBACK AboutDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  72.  
  73.  
  74. /* -------------------------------------------------------------------------
  75. ** Constants
  76. ** -------------------------------------------------------------------------
  77. */
  78. const TCHAR szClassName[] = TEXT("VMRTxtPlayer_CLASS");
  79. const TCHAR g_szNULL[]    = TEXT("\0");
  80. const TCHAR g_szEmpty[]   = TEXT("");
  81. const TCHAR g_szMovieX[]  = TEXT("MovieOriginX");
  82. const TCHAR g_szMovieY[]  = TEXT("MovieOriginY");
  83.  
  84. const int STR_MAX_STRING_LEN = 256;
  85.  
  86. const int   dxBitmap        = 16;
  87. const int   dyBitmap        = 15;
  88. const int   dxButtonSep     = 8;
  89. const TCHAR g_chNULL        = TEXT('\0');
  90.  
  91. const TBBUTTON tbButtons[DEFAULT_TBAR_SIZE] = {
  92.     { IDX_SEPARATOR,    1,                    0,               TBSTYLE_SEP           },
  93.     { IDX_1,            IDM_MOVIE_PLAY,       TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  94.     { IDX_2,            IDM_MOVIE_PAUSE,      TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  95.     { IDX_3,            IDM_MOVIE_STOP,       TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  96.     { IDX_SEPARATOR,    2,                    0,               TBSTYLE_SEP           },
  97.     { IDX_4,            IDM_MOVIE_PREVTRACK,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  98.     { IDX_5,            IDM_MOVIE_SKIP_BACK,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  99.     { IDX_6,            IDM_MOVIE_SKIP_FORE,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 },
  100.     { IDX_SEPARATOR,    3,                    0,               TBSTYLE_SEP           },
  101.     { IDX_12,           IDM_MOVIE_STEP,       TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1 }
  102. };
  103.  
  104.  
  105. /******************************Public*Routine******************************\
  106. * WinMain
  107. *
  108. *
  109. * Windows recognizes this function by name as the initial entry point
  110. * for the program.  This function calls the application initialization
  111. * routine, if no other instance of the program is running, and always
  112. * calls the instance initialization routine.  It then executes a message
  113. * retrieval and dispatch loop that is the top-level control structure
  114. * for the remainder of execution.  The loop is terminated when a WM_QUIT
  115. * message is received, at which time this function exits the application
  116. * instance by returning the value passed by PostQuitMessage().
  117. *
  118. * If this function must abort before entering the message loop, it
  119. * returns the conventional value NULL.
  120. *
  121. \**************************************************************************/
  122. int PASCAL
  123. WinMain(
  124.     HINSTANCE hInstance,
  125.     HINSTANCE hPrevInstance,
  126.     LPSTR lpCmdLineOld,
  127.     int nCmdShow
  128.     )
  129. {
  130.     USES_CONVERSION;
  131.     LPTSTR lpCmdLine = A2T(lpCmdLineOld);
  132.  
  133.     HRESULT hres = CoInitialize(NULL);
  134.     if(hres == S_FALSE)
  135.     {
  136.         CoUninitialize();
  137.         return FALSE;
  138.     }
  139.  
  140.     if(!hPrevInstance)
  141.     {
  142.         if(!InitApplication(hInstance))
  143.         {
  144.             return FALSE;
  145.         }
  146.     }
  147.  
  148.     /*
  149.     ** Perform initializations that apply to a specific instance
  150.     */
  151.     if(!InitInstance(hInstance, nCmdShow))
  152.     {
  153.         return FALSE;
  154.     }
  155.  
  156.     /* Verify that the VMR is present on this system */
  157.     if(!VerifyVMR())
  158.         return FALSE;
  159.  
  160.     /* Look for options */
  161.     while(lpCmdLine && (*lpCmdLine == '-' || *lpCmdLine == '/'))
  162.     {
  163.         if ((lpCmdLine[1] == 'P') || (lpCmdLine[1] == 'p'))
  164.         {
  165.             g_bPlay = TRUE;
  166.             lpCmdLine += 2;
  167.         }
  168.         else
  169.         {
  170.             break;
  171.         }
  172.         while(lpCmdLine[0] == ' ')
  173.         {
  174.             lpCmdLine++;
  175.         }
  176.     }
  177.  
  178.  
  179.     if(lpCmdLine != NULL && lstrlen(lpCmdLine) > 0)
  180.     {
  181.         ProcessOpen(lpCmdLine, g_bPlay);
  182.         SetPlayButtonsEnableState();
  183.     }
  184.  
  185.     /*
  186.     ** Acquire and dispatch messages until a WM_QUIT message is received.
  187.     */
  188.     return DoMainLoop();
  189. }
  190.  
  191.  
  192. /*****************************Private*Routine******************************\
  193. * DoMainLoop
  194. *
  195. * Process the main message loop
  196. *
  197. \**************************************************************************/
  198. int
  199. DoMainLoop(
  200.     void
  201.     )
  202. {
  203.     MSG         msg;
  204.     HANDLE      ahObjects[1];   // handles that need to be waited on
  205.     const int   cObjects = 1;   // no of objects that we are waiting on
  206.     HACCEL      haccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATOR));
  207.  
  208.     //
  209.     // Message loop lasts until we get a WM_QUIT message
  210.     //
  211.     for(;;)
  212.     {
  213.         if(pMpegMovie != NULL)
  214.         {
  215.             ahObjects[0] = pMpegMovie->GetMovieEventHandle();
  216.         }
  217.         else
  218.         {
  219.             ahObjects[0] = NULL;
  220.         }
  221.  
  222.         if(ahObjects[0] == NULL)
  223.         {
  224.             WaitMessage();
  225.         }
  226.         else
  227.         {
  228.             //
  229.             // wait for any message sent or posted to this queue
  230.             // or for a graph notification
  231.             //
  232.             DWORD result;
  233.  
  234.             result = MsgWaitForMultipleObjects(cObjects, ahObjects, FALSE,
  235.                 INFINITE, QS_ALLINPUT);
  236.             if(result != (WAIT_OBJECT_0 + cObjects))
  237.             {
  238.                 if(result == WAIT_OBJECT_0)
  239.                 {
  240.                     VideoCd_OnGraphNotify();
  241.                 }
  242.                 continue;
  243.             }
  244.         }
  245.  
  246.         //
  247.         // When here, we either have a message or no event handle
  248.         // has been created yet.
  249.         //
  250.         // read all of the messages in this next loop,
  251.         // removing each message as we read it
  252.         //
  253.         while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  254.         {
  255.             if(msg.message == WM_QUIT)
  256.             {
  257.                 return (int) msg.wParam;
  258.             }
  259.  
  260.             if(!TranslateAccelerator(hwndApp, haccel, &msg))
  261.             {
  262.                 TranslateMessage(&msg);
  263.                 DispatchMessage(&msg);
  264.             }
  265.         }
  266.     }
  267.  
  268. } // DoMainLoop
  269.  
  270.  
  271. /*****************************Private*Routine******************************\
  272. * InitApplication(HANDLE)
  273. *
  274. * This function is called at initialization time only if no other
  275. * instances of the application are running.  This function performs
  276. * initialization tasks that can be done once for any number of running
  277. * instances.
  278. *
  279. * In this case, we initialize a window class by filling out a data
  280. * structure of type WNDCLASS and calling the Windows RegisterClass()
  281. * function.  Since all instances of this application use the same window
  282. * class, we only need to do this when the first instance is initialized.
  283. *
  284. \**************************************************************************/
  285. BOOL
  286. InitApplication(
  287.     HINSTANCE hInstance
  288.     )
  289. {
  290.     WNDCLASS  wc;
  291.  
  292.     /*
  293.     ** Fill in window class structure with parameters that describe the
  294.     ** main window.
  295.     */
  296.     hIconVideoCd     = LoadIcon(hInstance, MAKEINTRESOURCE(IDR_VIDEOCD_ICON));
  297.  
  298.     wc.style         = CS_VREDRAW | CS_HREDRAW;
  299.     wc.lpfnWndProc   = VideoCdWndProc;
  300.     wc.cbClsExtra    = 0;
  301.     wc.cbWndExtra    = 0;
  302.     wc.hInstance     = hInstance;
  303.     wc.hIcon         = hIconVideoCd;
  304.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  305.     wc.hbrBackground = (HBRUSH)NULL; // (COLOR_BTNFACE + 1);
  306.     wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAIN_MENU);
  307.     wc.lpszClassName = szClassName;
  308.  
  309.     /*
  310.     ** Register the window class and return success/failure code.
  311.     */
  312.     return RegisterClass(&wc);
  313. }
  314.  
  315.  
  316. /*****************************Private*Routine******************************\
  317. * InitInstance
  318. *
  319. *
  320. * This function is called at initialization time for every instance of
  321. * this application.  This function performs initialization tasks that
  322. * cannot be shared by multiple instances.
  323. *
  324. * In this case, we save the instance handle in a static variable and
  325. * create and display the main program window.
  326. *
  327. \**************************************************************************/
  328. BOOL
  329. InitInstance(
  330.     HINSTANCE hInstance,
  331.     int nCmdShow
  332.     )
  333. {
  334.     HWND    hwnd;
  335.     RECT    rc;
  336.     POINT   pt;
  337.  
  338.     /*
  339.     ** Save the instance handle in static variable, which will be used in
  340.     ** many subsequence calls from this application to Windows.
  341.     */
  342.     hInst = hInstance;
  343.  
  344.     if(! LoadWindowPos(&rc))
  345.     {
  346.         rc.left = rc.top = 0;
  347.         rc.bottom = rc.right = 400;
  348.     }
  349.  
  350.     /*
  351.     ** Create a main window for this application instance.
  352.     */
  353.     hwnd = CreateWindow(szClassName, IdStr(STR_APP_TITLE),
  354.                         WS_THICKFRAME | WS_POPUP | WS_CAPTION  |
  355.                         WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
  356.                         WS_CLIPCHILDREN,
  357.                         rc.left, rc.top,
  358.                         rc.right - rc.left, rc.bottom - rc.top,
  359.                         NULL, NULL, hInstance, NULL);
  360.  
  361.     /*
  362.     ** If window could not be created, return "failure"
  363.     */
  364.     if(NULL == hwnd)
  365.     {
  366.         return FALSE;
  367.     }
  368.  
  369.     hwndApp = hwnd;
  370.     nRecentFiles = GetRecentFiles(nRecentFiles);
  371.  
  372.     pt.x = lMovieOrgX = ProfileIntIn(g_szMovieX, 0);
  373.     pt.y = lMovieOrgY = ProfileIntIn(g_szMovieY, 0);
  374.  
  375.     // if we fail to get the working area (screen-tray), then assume
  376.     // the screen is 640x480
  377.     //
  378.     if(!SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE))
  379.     {
  380.         rc.top = rc.left = 0;
  381.         rc.right = 640;
  382.         rc.bottom = 480;
  383.     }
  384.  
  385.     if(!PtInRect(&rc, pt))
  386.     {
  387.         lMovieOrgX = lMovieOrgY = 0L;
  388.     }
  389.  
  390.     /*
  391.     ** Make the window visible; update its client area; and return "success"
  392.     */
  393.     SetPlayButtonsEnableState();
  394.     ShowWindow(hwnd, nCmdShow);
  395.     UpdateWindow(hwnd);
  396.  
  397.     return TRUE;
  398. }
  399.  
  400. /*****************************Private*Routine******************************\
  401. * GetMoviePosition
  402. *
  403. * Place the movie in the center of the client window.  We do not stretch the
  404. * the movie yet !
  405. *
  406. \**************************************************************************/
  407. void
  408. GetMoviePosition(
  409.     HWND hwnd,
  410.     long* xPos,
  411.     long* yPos,
  412.     long* pcx,
  413.     long* pcy
  414.     )
  415. {
  416.     RECT rc;
  417.     GetClientRect(hwnd, &rc);
  418.  
  419.     rc.top += (dyToolbar + dyTrackbar);
  420.     rc.bottom -= dyStatusbar;
  421.  
  422.     *xPos = rc.left;
  423.     *yPos = rc.top;
  424.     *pcx = rc.right - rc.left;
  425.     *pcy = rc.bottom - rc.top;
  426. }
  427.  
  428.  
  429. /*****************************Private*Routine******************************\
  430. * RepositionMovie
  431. *
  432. \**************************************************************************/
  433. void
  434. RepositionMovie(HWND hwnd)
  435. {
  436.     if(pMpegMovie)
  437.     {
  438.         // Allow the video to play for a short time (otherwise, VMR has no way 
  439.         // to reallocate the DDraw surface) and [possibly] return to the point 
  440.         // where we started.
  441.         REFTIME rtPausedPosition = 0L;
  442.         BOOL    bNeedToRewind = FALSE;
  443.         BOOL    bStopped = FALSE;
  444.  
  445.         if( MOVIE_PLAYING != pMpegMovie->StatusMovie() )
  446.         {
  447.             if( MOVIE_STOPPED == pMpegMovie->StatusMovie() )
  448.                 bStopped = TRUE;
  449.  
  450.             rtPausedPosition = pMpegMovie->GetCurrentPosition();
  451.             bNeedToRewind = TRUE;
  452.             pMpegMovie->PlayMovie();
  453.         }
  454.  
  455.         long xPos, yPos, cx, cy;
  456.         GetMoviePosition(hwnd, &xPos, &yPos, &cx, &cy);
  457.         pMpegMovie->PutMoviePosition(xPos, yPos, cx, cy);
  458.     
  459.         // Repaint the video window
  460.         HDC hdcWin = GetDC(NULL);
  461.         pMpegMovie->RepaintVideo(hwnd, hdcWin);
  462.         ReleaseDC(hwnd, hdcWin);
  463.  
  464.         // Stop or pause the video to return to its previous state.
  465.         // Seek to the previously displayed frame.
  466.         if( bNeedToRewind )
  467.         {
  468.             if( bStopped )
  469.             {
  470.                 pMpegMovie->StopMovie();
  471.             }
  472.             else
  473.             {
  474.                 pMpegMovie->PauseMovie();
  475.             }
  476.             pMpegMovie->SeekToPosition( rtPausedPosition, TRUE);
  477.         }
  478.     }
  479. }
  480.  
  481.  
  482. /*****************************Private*Routine******************************\
  483. * VideoCd_OnMove
  484. *
  485. \**************************************************************************/
  486. void
  487. VideoCd_OnMove(
  488.     HWND hwnd,
  489.     int x,
  490.     int y
  491.     )
  492. {
  493.     if(pMpegMovie)
  494.     {
  495.         if(pMpegMovie->GetStateMovie() != State_Running)
  496.         {
  497.             RepositionMovie(hwnd);
  498.         }
  499.         else
  500.         {
  501.             long xPos, yPos, cx, cy;
  502.  
  503.             // Reposition movie but don't invalidate the rect, since
  504.             // the next video frame will handle the redraw.
  505.             GetMoviePosition(hwnd, &xPos, &yPos, &cx, &cy);
  506.             pMpegMovie->PutMoviePosition(xPos, yPos, cx, cy);
  507.         }
  508.     }
  509. }
  510.  
  511.  
  512. /******************************Public*Routine******************************\
  513. * VideoCdWndProc
  514. *
  515. \**************************************************************************/
  516. LRESULT CALLBACK
  517. VideoCdWndProc(
  518.     HWND hwnd,
  519.     UINT message,
  520.     WPARAM wParam,
  521.     LPARAM lParam
  522.     )
  523. {
  524.     switch(message)
  525.     {
  526.         HANDLE_MSG(hwnd, WM_CREATE,            VideoCd_OnCreate);
  527.         HANDLE_MSG(hwnd, WM_PAINT,             VideoCd_OnPaint);
  528.         HANDLE_MSG(hwnd, WM_COMMAND,           VideoCd_OnCommand);
  529.         HANDLE_MSG(hwnd, WM_CLOSE,             VideoCd_OnClose);
  530.         HANDLE_MSG(hwnd, WM_QUERYENDSESSION,   VideoCd_OnQueryEndSession);
  531.         HANDLE_MSG(hwnd, WM_DESTROY,           VideoCd_OnDestroy);
  532.         HANDLE_MSG(hwnd, WM_SIZE,              VideoCd_OnSize);
  533.         HANDLE_MSG(hwnd, WM_SYSCOLORCHANGE,    VideoCd_OnSysColorChange);
  534.         HANDLE_MSG(hwnd, WM_MENUSELECT,        VideoCd_OnMenuSelect);
  535.         HANDLE_MSG(hwnd, WM_INITMENUPOPUP,     VideoCd_OnInitMenuPopup);
  536.         HANDLE_MSG(hwnd, WM_HSCROLL,           VideoCd_OnHScroll);
  537.         HANDLE_MSG(hwnd, WM_TIMER,             VideoCd_OnTimer);
  538.         HANDLE_MSG(hwnd, WM_NOTIFY,            VideoCd_OnNotify);
  539.         HANDLE_MSG(hwnd, WM_DROPFILES,         VideoCd_OnDropFiles);
  540.         HANDLE_MSG(hwnd, WM_MOVE,              VideoCd_OnMove);
  541.  
  542.         // Note: we do not use HANDLE_MSG here as we want to call
  543.         // DefWindowProc after we have notifed the FilterGraph Resource Manager,
  544.         // otherwise our window will not finish its activation process.
  545.  
  546.         case WM_ACTIVATE: VideoCd_OnActivate(hwnd, wParam, lParam);
  547.  
  548.             // IMPORTANT - let this drop through to DefWindowProc
  549.  
  550.         default:
  551.             return DefWindowProc(hwnd, message, wParam, lParam);
  552.     }
  553.  
  554.     return 0L;
  555. }
  556.  
  557.  
  558. /*****************************Private*Routine******************************\
  559. * VideoCd_OnCreate
  560. *
  561. \**************************************************************************/
  562. BOOL
  563. VideoCd_OnCreate(
  564.     HWND hwnd,
  565.     LPCREATESTRUCT lpCreateStruct
  566.     )
  567. {
  568.     RECT rc;
  569.     int Pane[2];
  570.  
  571.     InitCommonControls();
  572.  
  573.     /*
  574.     ** Create the toolbar and statusbar.
  575.     */
  576.     g_hwndToolbar = CreateToolbarEx(hwnd,
  577.         WS_VISIBLE | WS_CHILD |
  578.         TBSTYLE_TOOLTIPS | CCS_NODIVIDER,
  579.         ID_TOOLBAR, NUMBER_OF_BITMAPS,
  580.         hInst, IDR_TOOLBAR, tbButtons,
  581.         DEFAULT_TBAR_SIZE, dxBitmap, dyBitmap,
  582.         dxBitmap, dyBitmap, sizeof(TBBUTTON));
  583.  
  584.     if(g_hwndToolbar == NULL)
  585.     {
  586.         return FALSE;
  587.     }
  588.  
  589.     g_hwndStatusbar = CreateStatusWindow(WS_VISIBLE | WS_CHILD | CCS_BOTTOM,
  590.         TEXT("Example Text"), hwnd, ID_STATUSBAR);
  591.  
  592.     GetWindowRect(g_hwndToolbar, &rc);
  593.     dyToolbar = rc.bottom - rc.top;
  594.  
  595.     GetWindowRect(g_hwndStatusbar, &rc);
  596.     dyStatusbar = rc.bottom - rc.top;
  597.     dyTrackbar = 30;
  598.  
  599.     GetClientRect(hwnd, &rc);
  600.     Pane[0] = (rc.right - rc.left) / 2 ;
  601.     Pane[1] = -1;
  602.     SendMessage(g_hwndStatusbar, SB_SETPARTS, 2, (LPARAM)Pane);
  603.  
  604.  
  605.     g_hwndTrackbar = CreateWindowEx(0, TRACKBAR_CLASS, TEXT("Trackbar Control"),
  606.         WS_CHILD | WS_VISIBLE |
  607.         TBS_AUTOTICKS | TBS_ENABLESELRANGE,
  608.         LEFT_MARGIN, dyToolbar - 1,
  609.         (rc.right - rc.left) - (2* LEFT_MARGIN),
  610.         dyTrackbar, hwnd, (HMENU)ID_TRACKBAR,
  611.         hInst, NULL);
  612.  
  613.     SetDurationLength((REFTIME)0);
  614.     SetCurrentPosition((REFTIME)0);
  615.     SetTimer(hwnd, StatusTimer, 100, NULL);
  616.  
  617.     if(g_hwndStatusbar == NULL || g_hwndTrackbar == NULL)
  618.     {
  619.         return FALSE;
  620.     }
  621.  
  622.     // accept filemanager WM_DROPFILES messages
  623.     DragAcceptFiles(hwnd, TRUE);
  624.  
  625.     return TRUE;
  626. }
  627.  
  628.  
  629. /*****************************Private*Routine******************************\
  630. * VideoCd_OnActivate
  631. *
  632. \**************************************************************************/
  633.  
  634. void
  635. VideoCd_OnActivate(
  636.     HWND hwnd,
  637.     WPARAM wParam,
  638.     LPARAM lParam
  639.     )
  640. {
  641.     // If gaining focus, tell the renderer to set focus and 
  642.     // repaint the video (which is necessary if playback is paused)
  643.     if((UINT)LOWORD(wParam))
  644.     {
  645.         // we are being activated - tell the Filter graph (for Sound follows focus)
  646.         if(pMpegMovie)
  647.         {
  648.             pMpegMovie->SetFocus();
  649.             RepositionMovie(hwnd);
  650.         }
  651.     }
  652. }
  653.  
  654.  
  655. /*****************************Private*Routine******************************\
  656. * VideoCd_OnHScroll
  657. *
  658. \**************************************************************************/
  659. void
  660. VideoCd_OnHScroll(
  661.     HWND hwnd,
  662.     HWND hwndCtl,
  663.     UINT code,
  664.     int pos
  665.     )
  666. {
  667.     static BOOL fWasPlaying = FALSE;
  668.     static BOOL fBeginScroll = FALSE;
  669.  
  670.     if(pMpegMovie == NULL)
  671.         return;
  672.  
  673.     if(hwndCtl == g_hwndTrackbar)
  674.     {
  675.         REFTIME     rtCurrPos;
  676.         REFTIME     rtTrackPos;
  677.         REFTIME     rtDuration;
  678.  
  679.         pos = (int)SendMessage(g_hwndTrackbar, TBM_GETPOS, 0, 0);
  680.         rtTrackPos = (REFTIME)pos * g_TrackBarScale;
  681.  
  682.         switch(code)
  683.         {
  684.             case TB_BOTTOM:
  685.                 rtDuration = pMpegMovie->GetDuration();
  686.                 rtCurrPos = pMpegMovie->GetCurrentPosition();
  687.                 VcdPlayerSeekCmd(rtDuration - rtCurrPos);
  688.                 SetCurrentPosition(pMpegMovie->GetCurrentPosition());
  689.                 break;
  690.  
  691.             case TB_TOP:
  692.                 rtCurrPos = pMpegMovie->GetCurrentPosition();
  693.                 VcdPlayerSeekCmd(-rtCurrPos);
  694.                 SetCurrentPosition(pMpegMovie->GetCurrentPosition());
  695.                 break;
  696.  
  697.             case TB_LINEDOWN:
  698.                 VcdPlayerSeekCmd(10.0);
  699.                 SetCurrentPosition(pMpegMovie->GetCurrentPosition());
  700.                 break;
  701.  
  702.             case TB_LINEUP:
  703.                 VcdPlayerSeekCmd(-10.0);
  704.                 SetCurrentPosition(pMpegMovie->GetCurrentPosition());
  705.                 break;
  706.  
  707.             case TB_ENDTRACK:
  708.                 fBeginScroll = FALSE;
  709.                 if(fWasPlaying)
  710.                 {
  711.                     VcdPlayerPauseCmd();
  712.                     fWasPlaying = FALSE;
  713.                 }
  714.                 break;
  715.  
  716.             case TB_THUMBTRACK:
  717.                 if(!fBeginScroll)
  718.                 {
  719.                     fBeginScroll = TRUE;
  720.                     fWasPlaying = (g_State & VCD_PLAYING);
  721.                     if(fWasPlaying)
  722.                     {
  723.                         VcdPlayerPauseCmd();
  724.                     }
  725.                 }
  726.  
  727.             // Fall through
  728.             case TB_PAGEUP:
  729.             case TB_PAGEDOWN:
  730.                 rtCurrPos = pMpegMovie->GetCurrentPosition();
  731.                 VcdPlayerSeekCmd(rtTrackPos - rtCurrPos);
  732.                 SetCurrentPosition(pMpegMovie->GetCurrentPosition());
  733.                 break;
  734.         }
  735.     }
  736. }
  737.  
  738.  
  739. /*****************************Private*Routine******************************\
  740. * VideoCd_OnTimer
  741. *
  742. \**************************************************************************/
  743. void
  744. VideoCd_OnTimer(
  745.     HWND hwnd,
  746.     UINT id
  747.     )
  748. {
  749.     if(pMpegMovie && pMpegMovie->StatusMovie() == MOVIE_PLAYING)
  750.     {
  751.         switch(id)
  752.         {
  753.             case StatusTimer:
  754.             {
  755.                 REFTIME rt = pMpegMovie->GetCurrentPosition();
  756.                 TCHAR   szFmt[64];
  757.                 char    sz[64];
  758.                 long cx, cy;
  759.                 static int iCharCount = 0;
  760.                 static int iCharOffset = 40;
  761.  
  762.                 pMpegMovie->GetNativeMovieSize(&cx, &cy);
  763. #ifdef UNICODE
  764.                 wsprintfA(sz, "%ls", FormatRefTime(szFmt, rt));
  765. #else
  766.                 wsprintfA(sz, "%s", FormatRefTime(szFmt, rt));
  767. #endif
  768.                 //
  769.                 // Prepare the text array
  770.                 //
  771.                 memset(g_szLine21Text, ' ', sizeof(g_szLine21Text));
  772.                 g_szLine21Text[ 40] = '\n';
  773.                 g_szLine21Text[ 81] = '\n';
  774.                 g_szLine21Text[122] = '\n';
  775.                 g_szLine21Text[163] = '\0';
  776.  
  777.                 // add time
  778.                 memcpy(g_szLine21Text, sz, lstrlenA(sz));
  779.  
  780.  
  781.                 char* lpL1 = &g_szLine21Text[ 41];
  782.                 char* lpL2 = &g_szLine21Text[ 82];
  783.                 char* lpL3 = &g_szLine21Text[123];
  784.  
  785.                 if(iCharCount <= 40)
  786.                 {
  787.                     memcpy(lpL3, g_Line21Msg, iCharCount);
  788.                 }
  789.                 else if(iCharCount <= 80)
  790.                 {
  791.                     memcpy(lpL2, g_Line21Msg +  0,              40);
  792.                     memcpy(lpL3, g_Line21Msg + 40, iCharCount - 40);
  793.                 }
  794.                 else if(iCharCount <= 120)
  795.                 {
  796.                     memcpy(lpL1, g_Line21Msg +  0,              40);
  797.                     memcpy(lpL2, g_Line21Msg + 40,              40);
  798.                     memcpy(lpL3, g_Line21Msg + 80, iCharCount - 80);
  799.                 }
  800.                 else
  801.                 {
  802.                     memcpy(lpL1, g_Line21Msg + iCharOffset +  0, 40);
  803.                     memcpy(lpL2, g_Line21Msg + iCharOffset + 40, 40);
  804.                     memcpy(lpL3, g_Line21Msg + iCharOffset + 80, iCharCount - (iCharOffset + 80));
  805.  
  806.                     if(iCharCount % 40 == 0)
  807.                     {
  808.                         iCharOffset += 40;
  809.                     }
  810.                 }
  811.  
  812.                 iCharCount++;
  813.  
  814.                 if(iCharCount > (sizeof(g_Line21Msg) - 1))
  815.                 {
  816.                     iCharCount = 1;
  817.                     iCharOffset = 40;
  818.                 }
  819.  
  820.                 pMpegMovie->SetAppText(g_szLine21Text);
  821.                 SetCurrentPosition(rt);
  822.             }
  823.             break;
  824.         }
  825.     }
  826. }
  827.  
  828.  
  829. /*****************************Private*Routine******************************\
  830. * VideoCd_OnPaint
  831. *
  832. \**************************************************************************/
  833. void
  834. VideoCd_OnPaint(
  835.     HWND hwnd
  836.     )
  837. {
  838.     PAINTSTRUCT ps;
  839.     HDC         hdc;
  840.     RECT        rc1, rc2;
  841.  
  842.     /*
  843.     ** Draw a frame around the movie playback area.
  844.     */
  845.     GetClientRect(hwnd, &rc2);
  846.  
  847.     hdc = BeginPaint(hwnd, &ps);
  848.  
  849.     if(pMpegMovie)
  850.     {
  851.         long xPos, yPos, cx, cy;
  852.         GetMoviePosition(hwnd, &xPos, &yPos, &cx, &cy);
  853.         SetRect(&rc1, xPos, yPos, xPos + cx, yPos + cy);
  854.  
  855.         HRGN rgnClient = CreateRectRgnIndirect(&rc2);
  856.         HRGN rgnVideo  = CreateRectRgnIndirect(&rc1);
  857.         CombineRgn(rgnClient, rgnClient, rgnVideo, RGN_DIFF);
  858.  
  859.         HBRUSH hbr = GetSysColorBrush(COLOR_BTNFACE);
  860.         FillRgn(hdc, rgnClient, hbr);
  861.         DeleteObject(hbr);
  862.         DeleteObject(rgnClient);
  863.         DeleteObject(rgnVideo);
  864.  
  865.         pMpegMovie->RepaintVideo(hwnd, hdc);
  866.     }
  867.     else
  868.     {
  869.         FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
  870.     }
  871.  
  872.     EndPaint(hwnd, &ps);
  873. }
  874.  
  875.  
  876. /*****************************Private*Routine******************************\
  877. * VideoCd_OnCommand
  878. *
  879. \**************************************************************************/
  880. void
  881. VideoCd_OnCommand(
  882.     HWND hwnd,
  883.     int id,
  884.     HWND hwndCtl,
  885.     UINT codeNotify
  886.     )
  887. {
  888.     switch(id)
  889.     {
  890.         case IDM_FILE_OPEN:
  891.             if(VcdPlayerOpenCmd())
  892.                 VcdPlayerPlayCmd();
  893.             break;
  894.  
  895.         case IDM_FILE_CLOSE:
  896.             VcdPlayerCloseCmd();
  897.             QzFreeUnusedLibraries();
  898.             break;
  899.  
  900.         case IDM_FILE_EXIT:
  901.             PostMessage(hwnd, WM_CLOSE, 0, 0L);
  902.             break;
  903.  
  904.         case IDM_MOVIE_PLAY:
  905.             VcdPlayerPlayCmd();
  906.             break;
  907.  
  908.         case IDM_MOVIE_STOP:
  909.             VcdPlayerStopCmd();
  910.             VcdPlayerRewindCmd();
  911.             break;
  912.  
  913.         case IDM_MOVIE_PAUSE:
  914.             VcdPlayerPauseCmd();
  915.             break;
  916.  
  917.         case IDM_MOVIE_SKIP_FORE:
  918.             VcdPlayerSeekCmd(1.0);
  919.             break;
  920.  
  921.         case IDM_MOVIE_SKIP_BACK:
  922.             VcdPlayerSeekCmd(-1.0);
  923.             break;
  924.  
  925.         case IDM_MOVIE_PREVTRACK:
  926.             if(pMpegMovie)
  927.             {
  928.                 VcdPlayerSeekCmd(-pMpegMovie->GetCurrentPosition());
  929.             }
  930.             break;
  931.  
  932.         case IDM_MOVIE_STEP:
  933.             VcdPlayerPauseCmd();
  934.             VcdPlayerStepCmd();
  935.             break;
  936.  
  937.         case IDM_TIME:
  938.         case IDM_FRAME:
  939.         case IDM_FIELD:
  940.         case IDM_SAMPLE:
  941.         case IDM_BYTES:
  942.             if(pMpegMovie)
  943.             {
  944.                 g_TimeFormat = VcdPlayerChangeTimeFormat(id);
  945.             }
  946.             break;
  947.  
  948.         case IDM_HELP_ABOUT:
  949.             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX),
  950.                 hwnd,  (DLGPROC) AboutDlgProc);
  951.             break;
  952.  
  953.         default:
  954.             if(id > ID_RECENT_FILE_BASE
  955.                 && id <= (ID_RECENT_FILE_BASE + MAX_RECENT_FILES + 1))
  956.             {
  957.                 ProcessOpen(aRecentFiles[id - ID_RECENT_FILE_BASE - 1]);
  958.                 VcdPlayerPlayCmd();
  959.             }
  960.             break;
  961.     }
  962.  
  963.     SetPlayButtonsEnableState();
  964. }
  965.  
  966.  
  967. /******************************Public*Routine******************************\
  968. * VideoCd_OnDestroy
  969. *
  970. \**************************************************************************/
  971. void
  972. VideoCd_OnDestroy(
  973.     HWND hwnd
  974.     )
  975. {
  976.     PostQuitMessage(0);
  977. }
  978.  
  979.  
  980. /******************************Public*Routine******************************\
  981. * VideoCd_OnClose
  982. *
  983. \**************************************************************************/
  984. void
  985. VideoCd_OnClose(
  986.     HWND hwnd
  987.     )
  988. {
  989.     // stop accepting dropped filenames
  990.     DragAcceptFiles(hwnd, FALSE);
  991.  
  992.     VcdPlayerCloseCmd();
  993.     ProfileIntOut(g_szMovieX, lMovieOrgX);
  994.     ProfileIntOut(g_szMovieY, lMovieOrgY);
  995.  
  996.     SaveWindowPos(hwnd);
  997.     DestroyWindow(hwnd);
  998. }
  999.  
  1000. /******************************Public*Routine******************************\
  1001. * VideoCd_OnQueryEndSession
  1002. *
  1003. \**************************************************************************/
  1004. BOOL
  1005. VideoCd_OnQueryEndSession(
  1006.     HWND hwnd
  1007.     )
  1008. {
  1009.     SaveWindowPos(hwnd);
  1010.     return TRUE;
  1011. }
  1012.  
  1013.  
  1014. /******************************Public*Routine******************************\
  1015. * VideoCd_OnSize
  1016. *
  1017. \**************************************************************************/
  1018. void
  1019. VideoCd_OnSize(
  1020.     HWND hwnd,
  1021.     UINT state,
  1022.     int dx,
  1023.     int dy
  1024.     )
  1025. {
  1026.     if(IsWindow(g_hwndStatusbar))
  1027.     {
  1028.         int Pane[2] = {dx/2-8, -1};
  1029.  
  1030.         SendMessage(g_hwndStatusbar, WM_SIZE, 0, 0L);
  1031.         SendMessage(g_hwndStatusbar, SB_SETPARTS, 2, (LPARAM)Pane);
  1032.     }
  1033.  
  1034.     if(IsWindow(g_hwndTrackbar))
  1035.     {
  1036.         SetWindowPos(g_hwndTrackbar, HWND_TOP, LEFT_MARGIN, dyToolbar - 1,
  1037.             dx - (2 * LEFT_MARGIN), dyTrackbar, SWP_NOZORDER);
  1038.     }
  1039.  
  1040.     if(IsWindow(g_hwndToolbar))
  1041.     {
  1042.         SendMessage(g_hwndToolbar, WM_SIZE, 0, 0L);
  1043.     }
  1044.  
  1045.     RepositionMovie(hwnd);
  1046. }
  1047.  
  1048.  
  1049. /*****************************Private*Routine******************************\
  1050. * VideoCd_OnSysColorChange
  1051. *
  1052. \**************************************************************************/
  1053. void
  1054. VideoCd_OnSysColorChange(
  1055.     HWND hwnd
  1056.     )
  1057. {
  1058.     FORWARD_WM_SYSCOLORCHANGE(g_hwndToolbar, SendMessage);
  1059.     FORWARD_WM_SYSCOLORCHANGE(g_hwndStatusbar, SendMessage);
  1060. }
  1061.  
  1062.  
  1063. /*****************************Private*Routine******************************\
  1064. * VideoCd_OnInitMenuPopup
  1065. *
  1066. \**************************************************************************/
  1067. void
  1068. VideoCd_OnInitMenuPopup(
  1069.     HWND hwnd,
  1070.     HMENU hMenu,
  1071.     UINT item,
  1072.     BOOL fSystemMenu
  1073.     )
  1074. {
  1075.     UINT uFlags;
  1076.  
  1077.     switch(item)
  1078.     {
  1079.         case 0: // File menu
  1080.             if(g_State & (VCD_IN_USE | VCD_NO_CD | VCD_DATA_CD_LOADED))
  1081.             {
  1082.                 uFlags = (MF_BYCOMMAND | MF_GRAYED);
  1083.             }
  1084.             else
  1085.             {
  1086.                 uFlags = (MF_BYCOMMAND | MF_ENABLED);
  1087.             }
  1088.             EnableMenuItem(hMenu, IDM_FILE_CLOSE, uFlags);
  1089.             break;
  1090.     }
  1091. }
  1092.  
  1093.  
  1094. /*****************************Private*Routine******************************\
  1095. * VideoCd_OnGraphNotify
  1096. *
  1097. * This is where we get any notifications from the filter graph.
  1098. *
  1099. \**************************************************************************/
  1100. void
  1101. VideoCd_OnGraphNotify(
  1102.     void
  1103.     )
  1104. {
  1105.     long lEventCode;
  1106.  
  1107.     lEventCode = pMpegMovie->GetMovieEventCode();
  1108.  
  1109.     switch(lEventCode)
  1110.     {
  1111.         case EC_STEP_COMPLETE:
  1112.             g_State &= ~VCD_STEPPING;
  1113.             SetPlayButtonsEnableState();
  1114.             break;
  1115.  
  1116.         case EC_COMPLETE:
  1117.             VcdPlayerRewindCmd();
  1118.             break;
  1119.  
  1120.         case EC_USERABORT:
  1121.         case EC_ERRORABORT:
  1122.             VcdPlayerStopCmd();
  1123.             SetPlayButtonsEnableState();
  1124.             break;
  1125.  
  1126.         default:
  1127.             break;
  1128.     }
  1129. }
  1130.  
  1131.  
  1132. /*****************************Private*Routine******************************\
  1133. * VideoCd_OnNotify
  1134. *
  1135. * This is where we get the text for the little tooltips
  1136. *
  1137. \**************************************************************************/
  1138. LRESULT
  1139. VideoCd_OnNotify(
  1140.     HWND hwnd,
  1141.     int idFrom,
  1142.     NMHDR FAR* pnmhdr
  1143.     )
  1144. {
  1145.     switch(pnmhdr->code)
  1146.     {
  1147.         case TTN_NEEDTEXT:
  1148.             {
  1149.                 LPTOOLTIPTEXT   lpTt;
  1150.  
  1151.                 lpTt = (LPTOOLTIPTEXT)pnmhdr;
  1152.                 LoadString(hInst, (UINT) lpTt->hdr.idFrom, lpTt->szText,
  1153.                     sizeof(lpTt->szText));
  1154.             }
  1155.             break;
  1156.     }
  1157.  
  1158.     return 0;
  1159. }
  1160.  
  1161.  
  1162. /*****************************Private*Routine******************************\
  1163. * VideoCd_OnMenuSelect
  1164. *
  1165. \**************************************************************************/
  1166. void
  1167. VideoCd_OnMenuSelect(
  1168.     HWND hwnd,
  1169.     HMENU hmenu,
  1170.     int item,
  1171.     HMENU hmenuPopup,
  1172.     UINT flags
  1173.     )
  1174. {
  1175.     TCHAR szString[STR_MAX_STRING_LEN + 1];
  1176.  
  1177.     /*
  1178.     ** Is it time to end the menu help ?
  1179.     */
  1180.     if((flags == 0xFFFFFFFF) && (hmenu == NULL))
  1181.     {
  1182.         SendMessage(g_hwndStatusbar, SB_SIMPLE, 0, 0L);
  1183.     }
  1184.  
  1185.     /*
  1186.     ** Do we have a separator, popup, or the system menu ?
  1187.     */
  1188.     else if(flags & MF_POPUP)
  1189.     {
  1190.         SendMessage(g_hwndStatusbar, SB_SIMPLE, 0, 0L);
  1191.     }
  1192.     else if(flags & MF_SYSMENU)
  1193.     {
  1194.         switch(item)
  1195.         {
  1196.             case SC_RESTORE:
  1197.                 lstrcpy(szString, IdStr(STR_SYSMENU_RESTORE));
  1198.                 break;
  1199.  
  1200.             case SC_MOVE:
  1201.                 lstrcpy(szString, IdStr(STR_SYSMENU_MOVE));
  1202.                 break;
  1203.  
  1204.             case SC_MINIMIZE:
  1205.                 lstrcpy(szString, IdStr(STR_SYSMENU_MINIMIZE));
  1206.                 break;
  1207.  
  1208.             case SC_MAXIMIZE:
  1209.                 lstrcpy(szString, IdStr(STR_SYSMENU_MAXIMIZE));
  1210.                 break;
  1211.  
  1212.             case SC_TASKLIST:
  1213.                 lstrcpy(szString, IdStr(STR_SYSMENU_TASK_LIST));
  1214.                 break;
  1215.  
  1216.             case SC_CLOSE:
  1217.                 lstrcpy(szString, IdStr(STR_SYSMENU_CLOSE));
  1218.                 break;
  1219.         }
  1220.  
  1221.         SendMessage(g_hwndStatusbar, SB_SETTEXT, SBT_NOBORDERS|255,
  1222.             (LPARAM)(LPTSTR)szString);
  1223.         SendMessage(g_hwndStatusbar, SB_SIMPLE, 1, 0L);
  1224.         UpdateWindow(g_hwndStatusbar);
  1225.  
  1226.     }
  1227.  
  1228.     /*
  1229.     ** Hopefully it's one of ours
  1230.     */
  1231.     else
  1232.     {
  1233.         if((flags & MF_SEPARATOR))
  1234.         {
  1235.             szString[0] = g_chNULL;
  1236.         }
  1237.         else
  1238.         {
  1239.             lstrcpy(szString, IdStr(item + MENU_STRING_BASE));
  1240.  
  1241.         }
  1242.  
  1243.         SendMessage(g_hwndStatusbar, SB_SETTEXT, SBT_NOBORDERS|255,
  1244.             (LPARAM)(LPTSTR)szString);
  1245.         SendMessage(g_hwndStatusbar, SB_SIMPLE, 1, 0L);
  1246.         UpdateWindow(g_hwndStatusbar);
  1247.     }
  1248. }
  1249.  
  1250. /*****************************Private*Routine******************************\
  1251. * VideoCd_OnDropFiles
  1252. *
  1253. * -- handle a file-manager drop of a filename to indicate a movie we should
  1254. *    open.
  1255. *
  1256. \**************************************************************************/
  1257. void
  1258. VideoCd_OnDropFiles(
  1259.     HWND hwnd,
  1260.     HDROP hdrop)
  1261. {
  1262.     // if there is more than one file, simply open the first one
  1263.  
  1264.     // find the length of the path (plus the null
  1265.     int cch = DragQueryFile(hdrop, 0, NULL, 0) + 1;
  1266.     TCHAR * pName = new TCHAR[cch];
  1267.  
  1268.     DragQueryFile(hdrop, 0, pName, cch);
  1269.  
  1270.     // open the file
  1271.     ProcessOpen(pName);
  1272.  
  1273.     // update the toolbar state
  1274.     SetPlayButtonsEnableState();
  1275.  
  1276.     // free up used resources
  1277.     delete [] pName;
  1278.     DragFinish(hdrop);
  1279. }
  1280.  
  1281.  
  1282. /******************************Public*Routine******************************\
  1283. * SetPlayButtonsEnableState
  1284. *
  1285. * Sets the play buttons enable state to match the state of the current
  1286. * cdrom device.  See below...
  1287. *
  1288. *
  1289. *                 VCD Player buttons enable state table
  1290. * -------------------------------------------------------------------
  1291. * │E=Enabled D=Disabled      │ Play │ Pause │ Eject │ Stop  │ Other │
  1292. * -------------------------------------------------------------------
  1293. * │Disk in use               │  D   │  D    │  D    │   D   │   D   │
  1294. * -------------------------------------------------------------------
  1295. * │No video cd or data cdrom │  D   │  D    │  E    │   D   │   D   │
  1296. * -------------------------------------------------------------------
  1297. * │Video cd (playing)        │  D   │  E    │  E    │   E   │   E   │
  1298. * -------------------------------------------------------------------
  1299. * │Video cd (paused)         │  E   │  D    │  E    │   E   │   E   │
  1300. * -------------------------------------------------------------------
  1301. * │Video cd (stopped)        │  E   │  D    │  E    │   D   │   E   │
  1302. * -------------------------------------------------------------------
  1303. *
  1304. *
  1305. \**************************************************************************/
  1306. void
  1307. SetPlayButtonsEnableState(
  1308.     void
  1309.     )
  1310. {
  1311.     BOOL    fEnable;
  1312.     BOOL    fVideoLoaded;
  1313.  
  1314.     /*
  1315.     ** Do we have a video cd loaded.
  1316.     */
  1317.     if(g_State & (VCD_NO_CD | VCD_DATA_CD_LOADED | VCD_IN_USE))
  1318.         fVideoLoaded = FALSE;
  1319.     else
  1320.         fVideoLoaded = TRUE;
  1321.  
  1322.     /*
  1323.     ** Do the play button
  1324.     */
  1325.     if(fVideoLoaded
  1326.         && ((g_State & VCD_STOPPED) || (g_State & VCD_PAUSED)))
  1327.         fEnable = TRUE;
  1328.     else
  1329.         fEnable = FALSE;
  1330.  
  1331.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON, IDM_MOVIE_PLAY, fEnable);
  1332.  
  1333.     /*
  1334.     ** Do the stop button
  1335.     */
  1336.     if(fVideoLoaded
  1337.         && ((g_State & VCD_PLAYING) || (g_State & VCD_PAUSED)))
  1338.         fEnable = TRUE;
  1339.     else
  1340.         fEnable = FALSE;
  1341.  
  1342.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON, IDM_MOVIE_STOP, fEnable);
  1343.  
  1344.  
  1345.     /*
  1346.     ** Do the pause button
  1347.     */
  1348.     if(fVideoLoaded && (g_State & VCD_PLAYING))
  1349.         fEnable = TRUE;
  1350.     else
  1351.         fEnable = FALSE;
  1352.  
  1353.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON, IDM_MOVIE_PAUSE, fEnable);
  1354.  
  1355.  
  1356.     fEnable = FALSE;
  1357.     if(fVideoLoaded && pMpegMovie->CanMovieFrameStep())
  1358.     {
  1359.         if(!(g_State & VCD_STEPPING))
  1360.             fEnable = TRUE;
  1361.     }
  1362.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON, IDM_MOVIE_STEP, fEnable);
  1363.  
  1364.     /*
  1365.     ** Do the seeking buttons
  1366.     */
  1367.     if((g_State & VCD_PAUSED) || (!fVideoLoaded))
  1368.         fEnable = FALSE;
  1369.     else
  1370.         fEnable = TRUE;
  1371.  
  1372.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON,
  1373.         IDM_MOVIE_SKIP_FORE, fEnable);
  1374.  
  1375.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON,
  1376.         IDM_MOVIE_SKIP_BACK, fEnable);
  1377.  
  1378.     SendMessage(g_hwndToolbar, TB_ENABLEBUTTON,
  1379.         IDM_MOVIE_PREVTRACK, fEnable);
  1380. }
  1381.  
  1382.  
  1383. /*****************************Private*Routine******************************\
  1384. * GetAdjustedClientRect
  1385. *
  1386. * Calculate the size of the client rect and then adjusts it to take into
  1387. * account the space taken by the toolbar and status bar.
  1388. *
  1389. \**************************************************************************/
  1390. void
  1391. GetAdjustedClientRect(
  1392.     RECT *prc
  1393.     )
  1394. {
  1395.     RECT    rcTool;
  1396.  
  1397.     GetClientRect(hwndApp, prc);
  1398.  
  1399.     GetWindowRect(g_hwndToolbar, &rcTool);
  1400.     prc->top += (rcTool.bottom - rcTool.top);
  1401.  
  1402.     GetWindowRect(g_hwndTrackbar, &rcTool);
  1403.     prc->top += (rcTool.bottom - rcTool.top);
  1404.  
  1405.     GetWindowRect(g_hwndStatusbar, &rcTool);
  1406.     prc->bottom -= (rcTool.bottom - rcTool.top);
  1407. }
  1408.  
  1409.  
  1410. /******************************Public*Routine******************************\
  1411. * IdStr
  1412. *
  1413. * Loads the given string resource ID into the passed storage.
  1414. *
  1415. \**************************************************************************/
  1416. LPCTSTR
  1417. IdStr(
  1418.     int idResource
  1419.     )
  1420. {
  1421.     static TCHAR    chBuffer[ STR_MAX_STRING_LEN ];
  1422.  
  1423.     if(LoadString(hInst, idResource, chBuffer, STR_MAX_STRING_LEN) == 0)
  1424.     {
  1425.         return g_szEmpty;
  1426.     }
  1427.  
  1428.     return chBuffer;
  1429. }
  1430.  
  1431.  
  1432. /*****************************Private*Routine******************************\
  1433. * SetDurationLength
  1434. *
  1435. * Updates pane 0 on the status bar
  1436. *
  1437. \**************************************************************************/
  1438. void
  1439. SetDurationLength(
  1440.     REFTIME rt
  1441.     )
  1442. {
  1443.     TCHAR   szFmt[64];
  1444.     TCHAR   sz[64];
  1445.  
  1446.     g_TrackBarScale = 1.0;
  1447.     while(rt / g_TrackBarScale > 30000)
  1448.     {
  1449.         g_TrackBarScale *= 10;
  1450.     }
  1451.  
  1452.     SendMessage(g_hwndTrackbar, TBM_SETRANGE, TRUE,
  1453.         MAKELONG(0, (WORD)(rt / g_TrackBarScale)));
  1454.  
  1455.     SendMessage(g_hwndTrackbar, TBM_SETTICFREQ, (WPARAM)((int)(rt / g_TrackBarScale) / 9), 0);
  1456.     SendMessage(g_hwndTrackbar, TBM_SETPAGESIZE, 0, (LPARAM)((int)(rt / g_TrackBarScale) / 9));
  1457.  
  1458.     wsprintf(sz, TEXT("Length: %s"), FormatRefTime(szFmt, rt));
  1459.     SendMessage(g_hwndStatusbar, SB_SETTEXT, 0, (LPARAM)sz);
  1460. }
  1461.  
  1462.  
  1463. /*****************************Private*Routine******************************\
  1464. * SetCurrentPosition
  1465. *
  1466. * Updates pane 1 on the status bar
  1467. *
  1468. \**************************************************************************/
  1469. void
  1470. SetCurrentPosition(
  1471.     REFTIME rt
  1472.     )
  1473. {
  1474.     TCHAR   szFmt[64];
  1475.     TCHAR   sz[64], szCurrent[64];
  1476.  
  1477.     SendMessage(g_hwndTrackbar, TBM_SETPOS, TRUE, (LPARAM)(rt / g_TrackBarScale));
  1478.  
  1479.     wsprintf(sz, TEXT("Elapsed: %s"), FormatRefTime(szFmt, rt));
  1480.  
  1481.     // Read the current status bar text
  1482.     SendMessage(g_hwndStatusbar, SB_GETTEXT, 1, (LPARAM)szCurrent);
  1483.  
  1484.     // If this time is different, update the status bar display
  1485.     if (_tcscmp(sz, szCurrent))
  1486.         SendMessage(g_hwndStatusbar, SB_SETTEXT, 1, (LPARAM)sz);
  1487. }
  1488.  
  1489.  
  1490. /*****************************Private*Routine******************************\
  1491. * FormatRefTime
  1492. *
  1493. * Formats the given RefTime into the passed in character buffer,
  1494. * returns a pointer to the character buffer.
  1495. *
  1496. \**************************************************************************/
  1497. TCHAR *
  1498. FormatRefTime(
  1499.     TCHAR *sz,
  1500.     REFTIME rt
  1501.     )
  1502. {
  1503.     // If we are not seeking in time then format differently
  1504.  
  1505.     if(pMpegMovie && pMpegMovie->GetTimeFormat() != TIME_FORMAT_MEDIA_TIME)
  1506.     {
  1507.         wsprintf(sz,TEXT("%s"),(LPCTSTR) CDisp((LONGLONG) rt,CDISP_DEC));
  1508.         return sz;
  1509.     }
  1510.  
  1511.     int hrs, mins, secs;
  1512.  
  1513.     rt += 0.49;
  1514.  
  1515.     hrs  =  (int)rt / 3600;
  1516.     mins = ((int)rt % 3600) / 60;
  1517.     secs = ((int)rt % 3600) % 60;
  1518.  
  1519.     wsprintf(sz, TEXT("%02d:%02d:%02d h:m:s"),hrs, mins, secs);
  1520.  
  1521.     return sz;
  1522. }
  1523.  
  1524.  
  1525. /*****************************Private*Routine******************************\
  1526. * AboutDlgProc
  1527. *
  1528. \**************************************************************************/
  1529. LRESULT CALLBACK AboutDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1530. {
  1531.     switch(message)
  1532.     {
  1533.         case WM_INITDIALOG:
  1534.             return TRUE;
  1535.  
  1536.         case WM_COMMAND:
  1537.             if(wParam == IDOK)
  1538.             {
  1539.                 EndDialog(hWnd, TRUE);
  1540.                 return TRUE;
  1541.             }
  1542.             break;
  1543.     }
  1544.     return FALSE;
  1545. }
  1546.  
  1547.