home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / midiplyr / timewnd.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  14KB  |  466 lines

  1. /*****************************************************************************
  2. *
  3. *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. *  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. *  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. *  A PARTICULAR PURPOSE.
  7. *
  8. *  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. *
  10. ******************************************************************************
  11. *
  12. * TimeWnd.C
  13. *
  14. * Message handlers and other code for the time window
  15. *
  16. *****************************************************************************/
  17.  
  18. #pragma warning(disable:4756)
  19.  
  20. #define _INC_SHELLAPI
  21. #include <windows.h>
  22. #undef _INC_SHELLAPI
  23.  
  24. #include <shellapi.h>
  25. #include <windowsx.h>
  26. #include <mmsystem.h>
  27. #include <commdlg.h>
  28. #include <commctrl.h>
  29. #include <ctype.h>
  30.  
  31. #include "debug.h"
  32.  
  33. #include "MIDIPlyr.H"
  34.  
  35. /* Into gszFormatHMS[]
  36. */
  37. #define HOUR_INDEX          0
  38. #define MIN_INDEX           3
  39. #define SEC_INDEX           6
  40.  
  41. #define MIN_SEP_INDEX       2
  42. #define SEC_SEP_INDEX       5
  43.  
  44. #define TIMER_ID            0
  45. #define TIMER_INTERVAL      100
  46.  
  47. PRIVATE HFONT           ghFont          = NULL;
  48. PRIVATE char BCODE      gszFormatHMS[]  = "44:44:44";
  49. PRIVATE char BCODE      gszFormatTicks[]= "444444444";
  50.  
  51. #define MAX_CBFMT (max(sizeof(gszFormatHMS), sizeof(gszFormatTicks)))
  52.  
  53. PRIVATE BOOL            gbRepaint       = TRUE;
  54. PRIVATE int             gnPosY;
  55. PRIVATE int             ganPosX[MAX_CBFMT];
  56.  
  57. PRIVATE int             gnTimerOn       = 0;
  58.  
  59. PRIVATE VOID NEAR PASCAL PaintTime(HDC hDC);
  60.  
  61. PRIVATE BOOL NEAR PASCAL TWnd_OnCreate(HWND hWnd, CREATESTRUCT FAR* lpCreateStruct);
  62. PRIVATE VOID NEAR PASCAL TWnd_OnSize(HWND hWnd, UINT state, int cx, int cy);
  63. PRIVATE VOID NEAR PASCAL TWnd_OnPaint(HWND hWnd);
  64. PRIVATE VOID NEAR PASCAL TWnd_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify);
  65. PRIVATE VOID NEAR PASCAL TWnd_OnDestroy(HWND hWnd);
  66. PRIVATE VOID NEAR PASCAL TWnd_OnTimer(HWND hWnd, UINT id);
  67.  
  68. /*****************************************************************************
  69. *
  70. * PaintTime
  71. *
  72. * Paint the current sequencer time into the time window.
  73. *
  74. * HWND hDC                  - DC to paint time into
  75. *
  76. * Repaint the time. Unless gbRepaint is set, just repaint the sections
  77. * of the time that need updating. Clear gbRepaint when done.
  78. *
  79. *****************************************************************************/
  80. static UINT oldh = 0;
  81. static UINT oldm = 0;
  82. static UINT olds = 0;
  83.  
  84. static char szOldTicks[MAX_CBFMT];
  85.  
  86. PRIVATE VOID NEAR PASCAL PaintTime(
  87.     HDC                     hDC)           
  88. {
  89.     TICKS                   tkTime;
  90.     DWORD                   msTime;
  91.     int                     ii;
  92.     int                     cb;
  93.     char                    szWork[MAX_CBFMT];
  94.     HFONT                   hFont;
  95.     UINT                    h;
  96.     UINT                    m;
  97.     UINT                    s;
  98.     BOOL                    fRepaintedSec;
  99.     BOOL                    fRepaintedMin;
  100.  
  101.     if (MMSYSERR_NOERROR != seqTime(gpSeq, &tkTime))
  102.         return;
  103.  
  104.     SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
  105.     hFont = SelectObject(hDC, ghFont);
  106.     
  107.     if (gnTimeFormat == IDS_TICKS)
  108.     {
  109.         wsprintf(szWork, "%9lu", (DWORD)tkTime);
  110.  
  111.         for (ii = 0; ii < 9; ii++)
  112.         {
  113.             if (gbRepaint || szOldTicks[ii] != szWork[ii])
  114.                 EmbossedTextOut(
  115.                                 hDC,
  116.                                 ganPosX[ii],
  117.                                 gnPosY,
  118.                                 szWork+ii,
  119.                                 1,
  120.                                 (COLORREF)-1,
  121.                                 (COLORREF)-1,
  122.                                 3,
  123.                                 3);
  124.             szOldTicks[ii] = szWork[ii];
  125.         }
  126.     }
  127.     else
  128.     {
  129.         msTime = seqTicksToMillisecs(gpSeq, tkTime) / 1000L;
  130.  
  131.         h = (UINT)(msTime / 3600L);    msTime %= 3600L;
  132.         m = (UINT)(msTime / 60L);      msTime %= 60L;
  133.         s = (UINT)msTime;
  134.  
  135.         cb = lstrlen(gszFormatHMS);
  136.  
  137.         if (gbRepaint || h != oldh)
  138.         {
  139.             szWork[0] = '0' + (char)(h / 10);
  140.             szWork[1] = '0' + (char)(h % 10);
  141.             EmbossedTextOut(
  142.                             hDC,
  143.                             ganPosX[HOUR_INDEX],
  144.                             gnPosY,
  145.                             szWork,
  146.                             2,
  147.                             (COLORREF)-1,
  148.                             (COLORREF)-1,
  149.                             3,
  150.                             3);
  151.             oldh = h;
  152.         }
  153.  
  154.         fRepaintedMin = FALSE;
  155.         if (gbRepaint || m != oldm)
  156.         {
  157.             szWork[0] = gszFormatHMS[MIN_SEP_INDEX];
  158.             szWork[1] = '0' + (char)(m / 10);
  159.             szWork[2] = '0' + (char)(m % 10);
  160.             EmbossedTextOut(
  161.                             hDC,
  162.                             ganPosX[MIN_SEP_INDEX],
  163.                             gnPosY,
  164.                             szWork,
  165.                             3,
  166.                             (COLORREF)-1,
  167.                             (COLORREF)-1,
  168.                             3,
  169.                             3);
  170.             oldm = m;
  171.             fRepaintedMin = TRUE;
  172.         }
  173.  
  174.         fRepaintedSec = FALSE;
  175.         if (gbRepaint || s != olds)
  176.         {
  177.             szWork[0] = gszFormatHMS[SEC_SEP_INDEX];
  178.             szWork[1] = '0' + (char)(s / 10);
  179.             szWork[2] = '0' + (char)(s % 10);
  180.             EmbossedTextOut(
  181.                             hDC,
  182.                             ganPosX[SEC_SEP_INDEX],
  183.                             gnPosY,
  184.                             szWork,
  185.                             3,
  186.                             (COLORREF)-1,
  187.                             (COLORREF)-1,
  188.                             3,
  189.                             3);
  190.             olds = s;
  191.             fRepaintedSec = TRUE;
  192.         }
  193.  
  194.         /* If we're doing a full repaint, then update the separators
  195.          */
  196.         if (gbRepaint)
  197.             for (ii=0; ii < cb; ii++)
  198.                 if (!isdigit(gszFormatHMS[ii]))
  199.                 {
  200.                     if (SEC_SEP_INDEX == ii && fRepaintedSec)
  201.                         continue;
  202.  
  203.                     if (MIN_SEP_INDEX == ii && fRepaintedMin)
  204.                         continue;
  205.  
  206.                     EmbossedTextOut(
  207.                                     hDC,
  208.                                     ganPosX[ii],
  209.                                     gnPosY,
  210.                                     gszFormatHMS+ii,
  211.                                     1,
  212.                                     (COLORREF)-1,
  213.                                     (COLORREF)-1,
  214.                                     3,
  215.                                     3);
  216.                 }
  217.     }
  218.     
  219.     gbRepaint = FALSE;
  220.     SelectObject(hDC, hFont);
  221. }
  222.  
  223. /*****************************************************************************
  224. *
  225. * TWnd_OnCreate
  226. *
  227. * Handle WM_CREATE message to time window.
  228. *
  229. * HWND hWnd                 - Window handle
  230. * CREATESTRUCT FAR* lpCreateStruct
  231. *                           - Pointer to creation parameters for the window.
  232. *
  233. * Returns TRUE on success. Returning FALSE will cause the window to be
  234. * destroyed and the application will exit.
  235. *
  236. * Just return TRUE so the window will be created.
  237. *
  238. *****************************************************************************/
  239. BOOL NEAR PASCAL TWnd_OnCreate(
  240.     HWND                    hWnd,
  241.     CREATESTRUCT FAR*       lpCreateStruct)
  242. {
  243.     return TRUE;
  244. }
  245.  
  246. /*****************************************************************************
  247. *
  248. * TWnd_OnSize
  249. *
  250. * Handle WM_SIZE message to time window.
  251. *
  252. * HWND hWnd                 - Window handle
  253. * UINT state                - Some SIZE_xxx code indicating what type of
  254. *                             size operation this is.
  255. * int  cx, cy               - New x and y size of the window's client area.
  256. *
  257. * Get the new client rect into grcTWnd.
  258. * Destroy and recreate the font scaled to show the time at the correct size.
  259. * Force the time to fully repaint.
  260. *
  261. *****************************************************************************/
  262. VOID NEAR PASCAL TWnd_OnSize(
  263.     HWND                    hWnd,
  264.     UINT                    state,
  265.     int                     cx,
  266.     int                     cy)
  267. {
  268.     HDC                     hDC;
  269.     
  270.     GetClientRect(hWnd, &grcTWnd);
  271.  
  272.     if (ghFont != (HFONT)NULL)
  273.         DeleteObject(ghFont);
  274.  
  275.     hDC = GetDC(hWnd);
  276.     ghFont = CreateScaledFont(hDC,
  277.                               &grcTWnd,
  278.                               (gnTimeFormat == IDS_TICKS) ? gszFormatTicks : gszFormatHMS,
  279.                               ganPosX,
  280.                               &gnPosY);
  281.     ReleaseDC(hWnd, hDC);
  282.  
  283.     gbRepaint = TRUE;
  284.     InvalidateRect(hWnd, NULL, TRUE);
  285. }
  286.  
  287.  
  288. /*****************************************************************************
  289. *
  290. * TWnd_OnPaint
  291. *
  292. * Handle WM_PAINT message to time window.
  293. *
  294. * HWND hWnd                 - Window handle
  295. *
  296. * Repaint the 3D inset borders around the edge of the client area.
  297. * Repaint the time.
  298. *
  299. *****************************************************************************/
  300. VOID NEAR PASCAL TWnd_OnPaint( HWND hWnd) { PAINTSTRUCT ps; HDC hDC;
  301. HBRUSH hBrOld; int nWidth; int nHeight;
  302.  
  303.     RECT                    rc;
  304.  
  305.     GetClientRect(hWnd, &rc);
  306.     nWidth  = rc.right;
  307.     nHeight = rc.bottom;
  308.     
  309.     hDC = BeginPaint(hWnd, &ps);
  310.  
  311.     hBrOld = (HBRUSH)SelectObject(hDC, GetStockObject(GRAY_BRUSH));
  312.     PatBlt(hDC, 0, 0, 1, nHeight-1, PATCOPY);
  313.     PatBlt(hDC, 1, 0, nWidth-2, 1, PATCOPY);
  314.  
  315.     SelectObject(hDC, GetStockObject(BLACK_BRUSH));
  316.     PatBlt(hDC, 1, 1, 1, nHeight-3, PATCOPY);
  317.     PatBlt(hDC, 2, 1, nWidth-4, 1, PATCOPY);
  318.  
  319.     SelectObject(hDC, GetStockObject(WHITE_BRUSH));
  320.     PatBlt(hDC, rc.right-1, 0, 1, nHeight-1, PATCOPY);
  321.     PatBlt(hDC, 0, rc.bottom-1, nWidth, 1, PATCOPY);
  322.  
  323.     SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  324.     PatBlt(hDC, rc.right-2, 1, 1, nHeight-2, PATCOPY);
  325.     PatBlt(hDC, 1, rc.bottom-2, nWidth-2, 1, PATCOPY);
  326.     
  327.     SelectObject(hDC, hBrOld);
  328.  
  329.     gbRepaint = TRUE;
  330.     PaintTime(hDC);
  331.  
  332.     EndPaint(hWnd, &ps);
  333. }
  334.  
  335. /*****************************************************************************
  336. *
  337. * TWnd_OnCommand
  338. *
  339. * Handle WM_COMMAND message to the time window.
  340. *
  341. * HWND hWnd                 - Window handle
  342. * int id                    - id of control or menu causing WM_COMMAND
  343. * HWND hwndCtl              - Window handle of child control, if any
  344. * UINT codeNotify           - Notification code if this message is from a
  345. *                             control.
  346. *
  347. * We will receive IDM_PLAY and IDM_STOP messages forwarded from the main
  348. * application window whenver playback starts or stops. Use these messages
  349. * to create or kill a timer which will be used to update the time.
  350. *****************************************************************************/
  351. VOID NEAR PASCAL TWnd_OnCommand(
  352.     HWND                    hWnd,
  353.     int                     id,
  354.     HWND                    hWndCtl,
  355.     UINT                    codeNotify)
  356. {
  357.     switch(id)
  358.     {
  359.         case IDM_PLAY:
  360.             if (0 == gnTimerOn)
  361.             {
  362.                 gnTimerOn++;
  363.                 SetTimer(hWnd, TIMER_ID, TIMER_INTERVAL, 0);
  364.             }
  365.  
  366.             UpdateWindow(hWnd);
  367.             break;
  368.  
  369.         case IDM_STOP:
  370.             if (0 == gnTimerOn)
  371.             {
  372.                 gnTimerOn--;
  373.                 KillTimer(hWnd, TIMER_ID);
  374.             }
  375.             
  376.             UpdateWindow(hWnd);
  377.             break;
  378.     }
  379. }
  380.  
  381. /*****************************************************************************
  382. *
  383. * TWnd_OnDestroy
  384. *
  385. * Handle WM_DESTROY message to the time window.
  386. *
  387. * HWND hWnd                 - Window handle
  388. *
  389. * If we're being destroyed and the timer is still running, stop it.
  390. *****************************************************************************/
  391. VOID NEAR PASCAL TWnd_OnDestroy(
  392.     HWND                    hWnd)
  393. {
  394.     if (gnTimerOn)
  395.     {
  396.         KillTimer(hWnd, TIMER_ID);
  397.     }
  398. }
  399.  
  400. /*****************************************************************************
  401. *
  402. * TWnd_OnTimer
  403. *
  404. * Handle WM_TIMER message to the time window.
  405. *
  406. * HWND hWnd                 - Window handle
  407. * UINT id                   - Timer ID
  408. *
  409. * Update the time.
  410. *****************************************************************************/
  411. PRIVATE VOID NEAR PASCAL TWnd_OnTimer(
  412.     HWND                    hWnd,
  413.     UINT                    id)
  414. {
  415.     HDC                     hDC;
  416.  
  417.     hDC = GetDC(hWnd);
  418.     PaintTime(hDC);
  419.     ReleaseDC(hWnd, hDC);
  420. }
  421.  
  422. /*****************************************************************************
  423. *
  424. * TWnd_WndProc
  425. *
  426. * Window procedure for main application window.
  427. *
  428. * HWND hWnd                 - Window handle
  429. * UINT msg                  - Message code
  430. * WPARAM wParam             - Message specific parameter
  431. * LPARAM lParam             - Message specific parameter
  432. *
  433. * Dispatch messages we care about to the appropriate handler, else just
  434. * call DefWindowProc.
  435. *
  436. * Note this use of message cracker macros from windowsx.h. Using these
  437. * macros will shield you from the differences between Win16 and Win32;
  438. * if your app is cross-compilable, you should use these and save yourself
  439. * some headaches!
  440. *
  441. *****************************************************************************/
  442. LRESULT CALLBACK TWnd_WndProc(
  443.     HWND                    hWnd,
  444.     UINT                    msg,
  445.     WPARAM                  wParam,
  446.     LPARAM                  lParam)
  447. {
  448.     switch( msg )
  449.     {
  450.         HANDLE_MSG(hWnd, WM_CREATE,         TWnd_OnCreate);
  451.         HANDLE_MSG(hWnd, WM_SIZE,           TWnd_OnSize);
  452.         HANDLE_MSG(hWnd, WM_PAINT,          TWnd_OnPaint);
  453.         HANDLE_MSG(hWnd, WM_COMMAND,        TWnd_OnCommand);
  454.         HANDLE_MSG(hWnd, WM_DESTROY,        TWnd_OnDestroy);
  455.         HANDLE_MSG(hWnd, WM_TIMER,          TWnd_OnTimer);
  456.  
  457.         default:
  458.             return DefWindowProc(hWnd, msg, wParam, lParam);
  459.     }
  460.  
  461.     return 0;
  462. }
  463.