File:  [OS/2 SDKs] / pmsdk / samples / petzold / chap08 / organ.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:22 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1989, HEAD
Microsoft OS/2 SDK PM 02-24-1989

/*--------------------------------------
   ORGAN.C --  Play Organ from Keyboard
  --------------------------------------*/

#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
#include "organ.h"

MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
VOID    EXPENTRY Speaker (USHORT usFreq) ;

SHORT  xOffset, yOffset, cxCaps, cyChar ;
USHORT usLastScan ;

int main (void)
     {
     static CHAR  szClientClass [] = "Organ" ;
     static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU |
                                 FCF_SIZEBORDER    | FCF_MINMAX  |
                                 FCF_SHELLPOSITION | FCF_TASKLIST ;
     HAB          hab ;
     HMQ          hmq ;
     HWND         hwndFrame, hwndClient ;
     QMSG         qmsg ;

     if (DosPortAccess (0, 0, 0x42, 0x61))   // Don't run if port access fails
          return 1 ;

     hab = WinInitialize (0) ;
     hmq = WinCreateMsgQueue (hab, 0) ;

     WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;

     hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
                                     &flFrameFlags, szClientClass, NULL,
				     0L, NULL, 0, &hwndClient) ;

     WinSendMsg (hwndFrame, WM_SETICON,
                 WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE),
                 NULL) ;

     while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
          WinDispatchMsg (hab, &qmsg) ;

     WinDestroyWindow (hwndFrame) ;
     WinDestroyMsgQueue (hmq) ;
     WinTerminate (hab) ;
     DosPortAccess (0, 1, 0x42, 0x61) ;
     return 0 ;
     }

VOID DrawKey (HPS hps, USHORT usScanCode, BOOL fInvert)
     {
     RECTL rcl ;

     rcl.xLeft   = 3 * cxCaps * key[usScanCode].xPos / 2 + xOffset ;
     rcl.yBottom = 3 * cyChar * key[usScanCode].yPos / 2 + yOffset ;
     rcl.xRight  = rcl.xLeft   + 3 * cxCaps ;
     rcl.yTop    = rcl.yBottom + 3 * cyChar / 2 ;

     WinDrawText (hps, -1, key[usScanCode].szKey, &rcl,
                  CLR_NEUTRAL, CLR_BACKGROUND,
                  DT_CENTER | DT_VCENTER | DT_ERASERECT) ;
     if (fInvert)
          WinInvertRect (hps, &rcl) ;

     WinDrawBorder (hps, &rcl, 1, 1, CLR_NEUTRAL, CLR_BACKGROUND,
                    DB_STANDARD) ;
     }

VOID ProcessKey (HPS hps, USHORT usScanCode, USHORT fsFlags)
     {
     static USHORT ausOctFreq [] = { 262, 277, 294, 311, 330, 349,
                                     370, 392, 415, 440, 466, 494 } ;
     USHORT        usOct, usFreq ;

     if (usScanCode >= NUMSCANS)                       // No scan codes over 53
          return ;
     if ((usOct = key[usScanCode].sOctave) == -1)      // Non-music key
          return ;

     if (fsFlags & KC_KEYUP)                           // For key up
          {
          if (usLastScan == usScanCode)                // If that's the note
               {
               Speaker (0) ;                           // turn off speaker
               DrawKey (hps, usScanCode, FALSE) ;      // and redraw key
               usLastScan = 0 ;
               }
          return ;
          }
     if (fsFlags & KC_PREVDOWN)                        // Ignore typematics
          return ;

     usFreq = ausOctFreq [key[usScanCode].sNote] ;     // Get frequency

     if (fsFlags & KC_SHIFT)
          usOct += fsFlags & KC_ALT ? 2 : 1 ;          // Higher octave
     else if (fsFlags & KC_CTRL)
          usOct -= fsFlags & KC_ALT ? 2 : 1 ;          // Lower octave

     if (usOct > 4)                                    // Shift frequency
          usFreq <<= (usOct - 4) ;                     //   for octave
     else if (usOct < 4)
          usFreq >>= (4 - usOct) ;

     Speaker (usFreq) ;                                // Turn on speaker
     DrawKey (hps, usScanCode, TRUE) ;                 // Draw the inverted key

     if (usLastScan != 0)
          DrawKey (hps, usLastScan, FALSE) ;           // Redraw previous key
     usLastScan = usScanCode ;                         // Save scan code
     }

MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
     {
     FONTMETRICS fm ;
     HPS         hps ;
     SHORT       cxClient, cyClient ;
     USHORT      usScanCode ;

     switch (msg)
          {
          case WM_CREATE:
               hps = WinGetPS (hwnd) ;
               GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;
               cxCaps = (SHORT) fm.lEmInc ;
               cyChar = (SHORT) fm.lMaxBaselineExt ;
               WinReleasePS (hps) ;
               return 0 ;

          case WM_SIZE:
               cxClient = SHORT1FROMMP (mp2) ;
               cyClient = SHORT2FROMMP (mp2) ;

               xOffset = (cxClient - 25 * 3 * cxCaps / 2) / 2 ;
               yOffset = (cyClient - 6 * cyChar) / 2 ;
               return 0 ;

          case WM_CHAR:
               if (!(CHARMSG(&msg)->fs & KC_SCANCODE))
                    break ;

               hps = WinGetPS (hwnd) ;
               ProcessKey (hps, CHARMSG(&msg)->scancode, CHARMSG(&msg)->fs) ;
               WinReleasePS (hps) ;
               return 0 ;

          case WM_PAINT:
               hps = WinBeginPaint (hwnd, NULL, NULL) ;
               GpiErase (hps) ;

               for (usScanCode = 0 ; usScanCode < NUMSCANS ; usScanCode++)
                    if (key[usScanCode].xPos != -1)
                         DrawKey (hps, usScanCode, usScanCode == usLastScan) ;

               WinEndPaint (hps) ;
               return 0 ;
          }
     return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
     }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.