home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / prog_pm / chap08 / organ.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-09  |  5.5 KB  |  164 lines

  1. /*--------------------------------------
  2.    ORGAN.C --  Play Organ from Keyboard
  3.   --------------------------------------*/
  4.  
  5. #define INCL_DOS
  6. #define INCL_WIN
  7. #define INCL_GPI
  8. #include <os2.h>
  9. #include "organ.h"
  10.  
  11. MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
  12. VOID    EXPENTRY Speaker (USHORT usFreq) ;
  13.  
  14. SHORT  xOffset, yOffset, cxCaps, cyChar ;
  15. USHORT usLastScan ;
  16.  
  17. int main (void)
  18.      {
  19.      static CHAR  szClientClass [] = "Organ" ;
  20.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU |
  21.                                  FCF_SIZEBORDER    | FCF_MINMAX  |
  22.                                  FCF_SHELLPOSITION | FCF_TASKLIST ;
  23.      HAB          hab ;
  24.      HMQ          hmq ;
  25.      HWND         hwndFrame, hwndClient ;
  26.      QMSG         qmsg ;
  27.  
  28.      if (DosPortAccess (0, 0, 0x42, 0x61))   // Don't run if port access fails
  29.           return 1 ;
  30.  
  31.      hab = WinInitialize (0) ;
  32.      hmq = WinCreateMsgQueue (hab, 0) ;
  33.  
  34.      WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
  35.  
  36.      hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
  37.                                      &flFrameFlags, szClientClass, NULL,
  38.                      0L, NULL, 0, &hwndClient) ;
  39.  
  40.      WinSendMsg (hwndFrame, WM_SETICON,
  41.                  WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE),
  42.                  NULL) ;
  43.  
  44.      while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  45.           WinDispatchMsg (hab, &qmsg) ;
  46.  
  47.      WinDestroyWindow (hwndFrame) ;
  48.      WinDestroyMsgQueue (hmq) ;
  49.      WinTerminate (hab) ;
  50.      DosPortAccess (0, 1, 0x42, 0x61) ;
  51.      return 0 ;
  52.      }
  53.  
  54. VOID DrawKey (HPS hps, USHORT usScanCode, BOOL fInvert)
  55.      {
  56.      RECTL rcl ;
  57.  
  58.      rcl.xLeft   = 3 * cxCaps * key[usScanCode].xPos / 2 + xOffset ;
  59.      rcl.yBottom = 3 * cyChar * key[usScanCode].yPos / 2 + yOffset ;
  60.      rcl.xRight  = rcl.xLeft   + 3 * cxCaps ;
  61.      rcl.yTop    = rcl.yBottom + 3 * cyChar / 2 ;
  62.  
  63.      WinDrawText (hps, -1, key[usScanCode].szKey, &rcl,
  64.                   CLR_NEUTRAL, CLR_BACKGROUND,
  65.                   DT_CENTER | DT_VCENTER | DT_ERASERECT) ;
  66.      if (fInvert)
  67.           WinInvertRect (hps, &rcl) ;
  68.  
  69.      WinDrawBorder (hps, &rcl, 1, 1, CLR_NEUTRAL, CLR_BACKGROUND,
  70.                     DB_STANDARD) ;
  71.      }
  72.  
  73. VOID ProcessKey (HPS hps, USHORT usScanCode, USHORT fsFlags)
  74.      {
  75.      static USHORT ausOctFreq [] = { 262, 277, 294, 311, 330, 349,
  76.                                      370, 392, 415, 440, 466, 494 } ;
  77.      USHORT        usOct, usFreq ;
  78.  
  79.      if (usScanCode >= NUMSCANS)                       // No scan codes over 53
  80.           return ;
  81.      if ((usOct = key[usScanCode].sOctave) == -1)      // Non-music key
  82.           return ;
  83.  
  84.      if (fsFlags & KC_KEYUP)                           // For key up
  85.           {
  86.           if (usLastScan == usScanCode)                // If that's the note
  87.                {
  88.                Speaker (0) ;                           // turn off speaker
  89.                DrawKey (hps, usScanCode, FALSE) ;      // and redraw key
  90.                usLastScan = 0 ;
  91.                }
  92.           return ;
  93.           }
  94.      if (fsFlags & KC_PREVDOWN)                        // Ignore typematics
  95.           return ;
  96.  
  97.      usFreq = ausOctFreq [key[usScanCode].sNote] ;     // Get frequency
  98.  
  99.      if (fsFlags & KC_SHIFT)
  100.           usOct += fsFlags & KC_ALT ? 2 : 1 ;          // Higher octave
  101.      else if (fsFlags & KC_CTRL)
  102.           usOct -= fsFlags & KC_ALT ? 2 : 1 ;          // Lower octave
  103.  
  104.      if (usOct > 4)                                    // Shift frequency
  105.           usFreq <<= (usOct - 4) ;                     //   for octave
  106.      else if (usOct < 4)
  107.           usFreq >>= (4 - usOct) ;
  108.  
  109.      Speaker (usFreq) ;                                // Turn on speaker
  110.      DrawKey (hps, usScanCode, TRUE) ;                 // Draw the inverted key
  111.  
  112.      if (usLastScan != 0)
  113.           DrawKey (hps, usLastScan, FALSE) ;           // Redraw previous key
  114.      usLastScan = usScanCode ;                         // Save scan code
  115.      }
  116.  
  117. MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  118.      {
  119.      FONTMETRICS fm ;
  120.      HPS         hps ;
  121.      SHORT       cxClient, cyClient ;
  122.      USHORT      usScanCode ;
  123.  
  124.      switch (msg)
  125.           {
  126.           case WM_CREATE:
  127.                hps = WinGetPS (hwnd) ;
  128.                GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;
  129.                cxCaps = (SHORT) fm.lEmInc ;
  130.                cyChar = (SHORT) fm.lMaxBaselineExt ;
  131.                WinReleasePS (hps) ;
  132.                return 0 ;
  133.  
  134.           case WM_SIZE:
  135.                cxClient = SHORT1FROMMP (mp2) ;
  136.                cyClient = SHORT2FROMMP (mp2) ;
  137.  
  138.                xOffset = (cxClient - 25 * 3 * cxCaps / 2) / 2 ;
  139.                yOffset = (cyClient - 6 * cyChar) / 2 ;
  140.                return 0 ;
  141.  
  142.           case WM_CHAR:
  143.                if (!(CHARMSG(&msg)->fs & KC_SCANCODE))
  144.                     break ;
  145.  
  146.                hps = WinGetPS (hwnd) ;
  147.                ProcessKey (hps, CHARMSG(&msg)->scancode, CHARMSG(&msg)->fs) ;
  148.                WinReleasePS (hps) ;
  149.                return 0 ;
  150.  
  151.           case WM_PAINT:
  152.                hps = WinBeginPaint (hwnd, NULL, NULL) ;
  153.                GpiErase (hps) ;
  154.  
  155.                for (usScanCode = 0 ; usScanCode < NUMSCANS ; usScanCode++)
  156.                     if (key[usScanCode].xPos != -1)
  157.                          DrawKey (hps, usScanCode, usScanCode == usLastScan) ;
  158.  
  159.                WinEndPaint (hps) ;
  160.                return 0 ;
  161.           }
  162.      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
  163.      }
  164.