Thread: Piano window questions

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    57

    Piano window questions

    This code works well on my Windows XP with sound card.
    (it is a piano window)

    1. Will someone please verify it works on their XP system also?

    2. How do I compile and link with gcc? (I don't know how to use the sound lib with gcc)

    Thank you.


    Code:
    // I'm using vc 7.0, command line, but gcc works too
    // compile and link with this:
    //cl %1.c /c
    //link %1.obj user32.lib gdi32.lib winmm.lib
    //---------------------------------------------------------------------------
    #include <windows.h>
    #include <stdio.h>
    #include <mmsystem.h>
    
    //--- constants ------------------------------------------------------------
    #define IDC_BTN1            101
    #define IDC_BTN2            102
    
    //--- local -----------------------------------------------------------------
    HWND  hwndMain;
    HWND  hwndPiano;
    HWND  hwndWhiteKey;
    HWND  hwndBlackKey;
    HBRUSH  MW_Color;
    HBRUSH  PW_Color;
    HBRUSH  WK_Color_off;
    HBRUSH  WK_Color_on;
    HBRUSH  BK_Color_off;
    HBRUSH  BK_Color_on;
    HWND hBtn1;
    HWND hBtn2;
    
    //first white key start 5
    //white key width 15
    //space between white keys 1
    //white key length 80
    //black key width 10
    //black key length 50
    //black key start: prev key start + 10
    
    struct KEY{
       char bw;
       int  note;
       int  startx;
       BOOL  on;
       HWND hwndKey;
    };
    struct KEY key[49] = {
       'W',36,5,FALSE,0,
       'B',37,15,FALSE,0,
       'W',38,21,FALSE,0,
       'B',39,31,FALSE,0,
       'W',40,37,FALSE,0,
       'W',41,53,FALSE,0,
       'B',42,63,FALSE,0,
       'W',43,69,FALSE,0,
       'B',44,79,FALSE,0,
       'W',45,85,FALSE,0,
       'B',46,95,FALSE,0,
       'W',47,101,FALSE,0,
       'W',48,117,FALSE,0,
       'B',49,127,FALSE,0,
       'W',50,133,FALSE,0,
       'B',51,143,FALSE,0,
       'W',52,149,FALSE,0,
       'W',53,165,FALSE,0,
       'B',54,175,FALSE,0,
       'W',55,181,FALSE,0,
       'B',56,191,FALSE,0,
       'W',57,197,FALSE,0,
       'B',58,207,FALSE,0,
       'W',59,213,FALSE,0,
       'W',60,229,FALSE,0,
       'B',61,239,FALSE,0,
       'W',62,245,FALSE,0,
       'B',63,255,FALSE,0,
       'W',64,261,FALSE,0,
       'W',65,277,FALSE,0,
       'B',66,287,FALSE,0,
       'W',67,293,FALSE,0,
       'B',68,303,FALSE,0,
       'W',69,309,FALSE,0,
       'B',70,319,FALSE,0,
       'W',71,325,FALSE,0,
       'W',72,341,FALSE,0,
       'B',73,351,FALSE,0,
       'W',74,357,FALSE,0,
       'B',75,367,FALSE,0,
       'W',76,373,FALSE,0,
       'W',77,389,FALSE,0,
       'B',78,399,FALSE,0,
       'W',79,405,FALSE,0,
       'B',80,415,FALSE,0,
       'W',81,421,FALSE,0,
       'B',82,431,FALSE,0,
       'W',83,437,FALSE,0,
       'W',84,453,FALSE,0
    };
    // midi
    HMIDIOUT    mhandle;
    union {
       DWORD   dwData;
       UCHAR   bData[4];
    } u;
    
    
    //--- local prototypes ------------------------------------------------------------
    void initMainWindow(HINSTANCE, int);
    void initPianoWindow(HINSTANCE);
    void initBlackKeys(HINSTANCE);
    void initWhiteKeys(HINSTANCE);
    void initOtherControls(HINSTANCE);
    void initMidi();
    LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK PianoWndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK WhiteKeyWndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK BlackKeyWndProc(HWND, UINT, WPARAM, LPARAM);
    
    
    //---------------------------------------------------------------------------
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
       MSG msg; 
    
       initMainWindow(hInstance,nCmdShow);
       initPianoWindow(hInstance);
       initBlackKeys(hInstance);   // create black keys first, so they are on top
       initWhiteKeys(hInstance);
       initOtherControls(hInstance);
       UpdateWindow(hwndMain);
    
       initMidi();
    
       while(GetMessage(&msg, NULL, 0, 0) > 0) { 
          TranslateMessage(&msg); 
          DispatchMessage(&msg); 
       } 
       return msg.wParam; 
    }
    
    //---------------------------------------------------------------------------
    void initMainWindow(HINSTANCE hInstance, int nCmdShow) {
       WNDCLASSEX wc;
    
       //--- register ---------------------------------------------
       MW_Color = CreateSolidBrush(RGB(255, 0, 0));  // red
    
       wc.lpszClassName = "MainClass";
       wc.hInstance     = hInstance;
       wc.cbSize        = sizeof(WNDCLASSEX);
       wc.style         = 0;
       wc.cbClsExtra    = 0;
       wc.cbWndExtra    = 0;
       wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
       wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
       wc.hbrBackground = MW_Color;
       wc.lpszMenuName  = NULL;
       wc.lpfnWndProc   = MainWndProc;
    
       if(!RegisterClassEx(&wc)) {
          MessageBox(NULL, "Main Window Registration Failed!", "", MB_OK);
          exit(0);
       }
    
       //--- create -----------------------------------------------
       hwndMain = CreateWindowEx(
          0,
          "MainClass",
          "PianoNotes",
          WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, CW_USEDEFAULT,
          585, 300,
          NULL, NULL, hInstance, NULL);
    
       if(hwndMain == NULL) {
          MessageBox(NULL, "Main Window Creation Failed!", "", MB_OK);
          exit(0);
       }
    
       ShowWindow(hwndMain, nCmdShow);
    
       return;
    }
    
    //---------------------------------------------------------------------------
    void initPianoWindow(HINSTANCE hInstance) {
        WNDCLASSEX wc;
    
        //--- register ---------------------------------------------
        PW_Color = CreateSolidBrush(RGB(115,108,244));  // blue
    
        wc.lpszClassName = "PianoClass";
        wc.hInstance     = hInstance;
        wc.cbSize        = sizeof(WNDCLASSEX);
        wc.style         = 0;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = PW_Color;
        wc.lpszMenuName  = NULL;
        wc.lpfnWndProc   = PianoWndProc;
    
        if(!RegisterClassEx(&wc)) {
           MessageBox(NULL, "Piano Window Registration Failed!", "", MB_OK);
           exit(0);
        }
    
        //--- create -----------------------------------------------
        hwndPiano = CreateWindowEx(
           0,
           "PianoClass",
           "",
           WS_CHILD,
           45, 50,
           475, 100,
           hwndMain,
           NULL, hInstance, NULL);
    
        if(hwndPiano == NULL) {
           MessageBox(NULL, "Piano Window Creation Failed!", "", MB_OK);
           exit(0);
        }
    
        ShowWindow(hwndPiano, SW_SHOW);
    
        return;
    }
    
    //---------------------------------------------------------------------------
    void initBlackKeys(HINSTANCE hInstance) {
        int ii;
        WNDCLASSEX wc;
    
        //--- register ---------------------------------------------
        BK_Color_off = CreateSolidBrush(RGB(0,0,0));  // black
        BK_Color_on  = CreateSolidBrush(RGB(0,0,255));
    
        //Step 1: Registering the Window Class
        wc.lpszClassName = "BlackKeyClass";
        wc.hInstance     = hInstance;
        wc.cbSize        = sizeof(WNDCLASSEX);
        wc.style         = 0;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = BK_Color_off;
        wc.lpszMenuName  = NULL;
        wc.lpfnWndProc   = BlackKeyWndProc;
    
        if(!RegisterClassEx(&wc)) {
           MessageBox(NULL, "Black Key Registration Failed!", "", MB_OK);
           exit(0);
        }
    
        //--- create -----------------------------------------------
        for (ii=0;ii<49;ii++) {
           if (key[ii].bw == 'B') {
              hwndBlackKey = CreateWindowEx(
                 0,
                 "BlackKeyClass",
                 "",
                 WS_CHILD,
                 key[ii].startx, 13,
                 10, 50,
                 hwndPiano,
                 NULL, hInstance, NULL);
              
              if(hwndBlackKey == NULL) {
                 MessageBox(NULL, "Black Key Creation Failed!", "", MB_OK);
                 exit(0);
              }
              
              key[ii].hwndKey = hwndBlackKey;
              ShowWindow(hwndBlackKey, SW_SHOW);
              SetProp(hwndBlackKey,"note",(HANDLE)ii);
           }
        }
    
        return;
    }
    
    //---------------------------------------------------------------------------
    void initWhiteKeys(HINSTANCE hInstance) {
       int ii;
       WNDCLASSEX wc;
    
       //--- register ---------------------------------------------
       WK_Color_off = CreateSolidBrush(RGB(255,255,255));  // white
       WK_Color_on  = CreateSolidBrush(RGB(184,207,220));
    
       //Step 1: Registering the Window Class
       wc.lpszClassName = "WhiteKeyClass";
       wc.hInstance     = hInstance;
       wc.cbSize        = sizeof(WNDCLASSEX);
       wc.style         = 0;
       wc.cbClsExtra    = 0;
       wc.cbWndExtra    = 0;
       wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
       wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
       wc.hbrBackground = WK_Color_off;
       wc.lpszMenuName  = NULL;
       wc.lpfnWndProc   = WhiteKeyWndProc;
    
       if(!RegisterClassEx(&wc)) {
          MessageBox(NULL, "White Key Registration Failed!", "", MB_OK);
          exit(0);
       }
    
       //--- create -----------------------------------------------
       for (ii=0;ii<49;ii++) {
          if (key[ii].bw == 'W') {
             hwndWhiteKey = CreateWindowEx(
                0,
                "WhiteKeyClass",
                "",
                WS_CHILD | WS_CLIPSIBLINGS,
                key[ii].startx, 13,
                15, 80,
                hwndPiano,
                NULL, hInstance, NULL);
             
             if(hwndWhiteKey == NULL) {
                MessageBox(NULL, "White Key Creation Failed!", "", MB_OK);
                exit(0);
             }
             
             key[ii].hwndKey = hwndWhiteKey;
             ShowWindow(hwndWhiteKey, SW_SHOW);
             SetProp(hwndWhiteKey,"note",(HANDLE)ii);
          }
       }
    
       return;
    }
    
    //---------------------------------------------------------------------------
    void initOtherControls(HINSTANCE hInstance) {
    
       hBtn1 = CreateWindow("BUTTON", "All Off",
                            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                            400, 175, 66, 32,
                            hwndMain,
                            (HMENU)IDC_BTN1,
                            hInstance, NULL );
       hBtn2 = CreateWindow("BUTTON", "Sustain",
                            WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
                            300, 175, 73, 15,
                            hwndMain,
                            (HMENU)IDC_BTN2,
                            hInstance, NULL );
       return;
    }
    
    //---------------------------------------------------------------------------
    void initMidi()
    {
    	/* Open whichever MIDI Out device is specified in Control Panel's "Multimedia"*/ 
    	midiOutOpen(&mhandle, (UINT)-1, 0, 0, CALLBACK_NULL);
    
    	/* Set the voice */
    	u.bData[0] = 0xC0;
    	u.bData[1] = 60;	/* 60 = French Horm */
        midiOutShortMsg(mhandle, u.bData[0]);
        midiOutShortMsg(mhandle, u.bData[1]);
    
        return;
    }
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       PAINTSTRUCT ps; 
       HDC hdc;
       int ii;
       BOOL bHold;
    
       switch(msg)
       {
          case WM_PAINT: 
             hdc = BeginPaint(hwnd, &ps); 
             SetBkColor(hdc, RGB(255, 0, 0));
             SetTextColor(hdc, RGB(0, 0, 0));
             TextOut(hdc, 3, 10, "PianoNotes", 10); 
             EndPaint(hwnd, &ps); 
             break;
          case WM_COMMAND :
             switch( LOWORD( wParam ) )
             {
                case IDC_BTN1:
                   //MessageBox(hwnd,"button","", MB_OK);
                   for (ii=0;ii<49;ii++) {
                      if (key[ii].on) {
                         u.bData[0] = 0x80;	/* MIDI status byte */
                         u.bData[1] = key[ii].note;	/* first MIDI data byte - the note */
                         midiOutShortMsg(mhandle, u.dwData);
                         key[ii].on = FALSE;
                         InvalidateRect(key[ii].hwndKey, NULL, TRUE );
                      }
                   }
                   break;
             }
             break;
          case WM_LBUTTONDOWN:
             //MessageBox(hwnd,"Main WM_LBUTTONDOWN","", MB_OK);
             break;
          case WM_CLOSE:
             DestroyWindow(hwnd);
             break;
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
          default:
              return DefWindowProc(hwnd, msg, wParam, lParam);
       }
       return 0;
    }
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK PianoWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       switch(msg)
       {
          case WM_LBUTTONDOWN:
             //MessageBox(hwnd,"Piano WM_LBUTTONDOWN","", MB_OK);
             break;
          case WM_CLOSE:
             DestroyWindow(hwnd);
             break;
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
          default:
             return DefWindowProc(hwnd, msg, wParam, lParam);
       }
       return 0;
    }
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WhiteKeyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       int ii;
       PAINTSTRUCT ps; 
       HDC hdc;
       RECT rect;
    
       switch(msg)
       {
          case WM_PAINT:
             for (ii=0;ii<49;ii++) {
                if (key[ii].bw == 'W') {
                   hwndWhiteKey = key[ii].hwndKey;
                   hdc = BeginPaint(hwndWhiteKey, &ps); 
                   GetClientRect(hwndWhiteKey, &rect);
                   if (key[ii].on)
                       FillRect(ps.hdc, &rect, WK_Color_on);
                   else
                       FillRect(ps.hdc, &rect, WK_Color_off);
                   EndPaint(hwndWhiteKey, &ps);
                }
             }
             break;
          case WM_LBUTTONDOWN:
              //MessageBox(hwnd,"White Key WM_LBUTTONDOWN","", MB_OK);
              ii = (int) GetProp(hwnd,"note");
              if (key[ii].on) {
                 u.bData[0] = 0x80;	/* MIDI note off */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte */ /* 48 = C */
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = FALSE;
              }else{
                 u.bData[0] = 0x90;	/* MIDI note on */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                 u.bData[2] = 75;	/* second MIDI data byte */ /* volumn 0-127 */
                 u.bData[3] = 0;
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = TRUE;
              }
              InvalidateRect(key[ii].hwndKey, NULL, TRUE );
              break;
          case WM_LBUTTONUP:
              //MessageBox(hwnd,"White Key WM_LBUTTONUP","", MB_OK);
              if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
                 { break; }
              ii = (int) GetProp(hwnd,"note");
              if (key[ii].on) {
                 u.bData[0] = 0x80;	/* MIDI note off */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = FALSE;
                 InvalidateRect(key[ii].hwndKey, NULL, TRUE );
              }
              break;
          case WM_CLOSE:
             DestroyWindow(hwnd);
             break;
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
          default:
             return DefWindowProc(hwnd, msg, wParam, lParam);
       }
       return 0;
    }
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK BlackKeyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       int ii;
       PAINTSTRUCT ps; 
       HDC hdc;
       RECT rect;
    
       switch(msg)
       {
          case WM_PAINT:
             for (ii=0;ii<49;ii++) {
                if (key[ii].bw == 'B') {
                   hwndBlackKey = key[ii].hwndKey;
                   hdc = BeginPaint(hwndBlackKey, &ps); 
                   GetClientRect(hwndBlackKey, &rect);
                   if (key[ii].on)
                       FillRect(ps.hdc, &rect, BK_Color_on);
                   else
                       FillRect(ps.hdc, &rect, BK_Color_off);
                   EndPaint(hwndBlackKey, &ps);
                }
             }
             break;
          case WM_LBUTTONDOWN:
             //MessageBox(hwnd,"Black Key WM_LBUTTONDOWN","", MB_OK);
             ii = (int) GetProp(hwnd,"note");
             if (key[ii].on) {
                u.bData[0] = 0x80;	/* MIDI note off */
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = FALSE;
             }else{
                u.bData[0] = 0x90;	/* MIDI note on */
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note */
                u.bData[2] = 75;	/* second MIDI data byte */ /* volumn 0-127 */
                u.bData[3] = 0;
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = TRUE;
             }
             InvalidateRect(key[ii].hwndKey, NULL, TRUE );
             break;
          case WM_LBUTTONUP:
             //MessageBox(hwnd,"Black Key WM_LBUTTONUP","", MB_OK);
             if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
                 { break; }
             ii = (int) GetProp(hwnd,"note");
             if (key[ii].on) {
                u.bData[0] = 0x80;	/* MIDI note off*/
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note */
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = FALSE;
                InvalidateRect(key[ii].hwndKey, NULL, TRUE );
             }
             break;
          case WM_CLOSE:
             DestroyWindow(hwnd);
             break;
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
          default:
             return DefWindowProc(hwnd, msg, wParam, lParam);
       }
       return 0;
    }

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I tested this app on Winodws XP Pro, Version 2002 with SP2 installed. It does work. BUT there is a glitch in the code. If you repeatedly left click on some white keys in a really fast manner, that key will go into sustain mode even though sustain is NOT checked.

    Bob

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Tested on windows xp Home sp2. Works fine except for what BobS0327 mentioned. I beleive this problem is caused by LBUTTONUP being sent to a different window when the mouse has moved off of the key that was pressed.

  4. #4
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    Tested on Windows XP Pro, with SP2 installed. The program works just as what BobS0327 and Quantum1024 have described.

    If you don't want the weird sustain mode even though the sustain button isn't checked, I've managed to find a way to get rid of it.

    Modify the WM_LBUTTONDOWN/WM_LBUTTONUP messages in WhiteKeyWndProc and BlackKeyWndProc:

    WhiteKeyWndProc
    Code:
          case WM_LBUTTONDOWN:
              //MessageBox(hwnd,"White Key WM_LBUTTONDOWN","", MB_OK);
              ii = (int) GetProp(hwnd,"note");
              if (key[ii].on) {
                 u.bData[0] = 0x80;	/* MIDI note off */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte */ /* 48 = C */
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = FALSE;
              }else{
                 u.bData[0] = 0x90;	/* MIDI note on */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                 u.bData[2] = 75;	/* second MIDI data byte */ /* volumn 0-127 */
                 u.bData[3] = 0;
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = TRUE;
    
                // Dante's Change
                SetCapture( hwnd );
              }
              InvalidateRect(key[ii].hwndKey, NULL, TRUE );
              break;
          case WM_LBUTTONUP:
            
              // Dante's Change
              if ( GetCapture() == hwnd )
                SetCapture(0);             
            
              //MessageBox(hwnd,"White Key WM_LBUTTONUP","", MB_OK);
              if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
                 { break; }
              ii = (int) GetProp(hwnd,"note");
              if (key[ii].on) {
                 u.bData[0] = 0x80;	/* MIDI note off */
                 u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                 midiOutShortMsg(mhandle, u.dwData);
                 key[ii].on = FALSE;
                 InvalidateRect(key[ii].hwndKey, NULL, TRUE );
              }
              break;
    BlackKeyWndProc
    Code:
          case WM_LBUTTONDOWN:
             //MessageBox(hwnd,"Black Key WM_LBUTTONDOWN","", MB_OK);
             ii = (int) GetProp(hwnd,"note");
             if (key[ii].on) {
                u.bData[0] = 0x80;	/* MIDI note off */
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note*/
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = FALSE;
             }else{
                u.bData[0] = 0x90;	/* MIDI note on */
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note */
                u.bData[2] = 75;	/* second MIDI data byte */ /* volumn 0-127 */
                u.bData[3] = 0;
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = TRUE;
                
                // Dante's Change
                SetCapture( hwnd );
             }
             InvalidateRect(key[ii].hwndKey, NULL, TRUE );
             break;
          case WM_LBUTTONUP:
            
             // Dante's Change
             if ( GetCapture() == hwnd )
               SetCapture(0);              
            
             //MessageBox(hwnd,"Black Key WM_LBUTTONUP","", MB_OK);
             if (IsDlgButtonChecked(hwndMain, IDC_BTN2))
                 { break; }
             ii = (int) GetProp(hwnd,"note");
             if (key[ii].on) {
                u.bData[0] = 0x80;	/* MIDI note off*/
                u.bData[1] = key[ii].note;	/* first MIDI data byte - the note */
                midiOutShortMsg(mhandle, u.dwData);
                key[ii].on = FALSE;
                InvalidateRect(key[ii].hwndKey, NULL, TRUE );
             }
             break;
    All I'm doing is setting the mouse capture to the window during WM_LBUTTONDOWN, and removing the mouse capture when it detects a WM_LBUTTONUP.

    2. How do I compile and link with gcc? (I don't know how to use the sound lib with gcc)
    I linked it with -lwinmm
    Last edited by Dante Shamest; 10-22-2005 at 03:17 PM.

  5. #5
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    Works with Borland. I did get a few warnings. Ran fine with Dantes changes.

    C:\borland\bcc55\bin>bcc32 -tW -Lwinmm.lib pianno2.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    pianno2.c:
    Warning W8065 pianno2.c 128: Call to function 'initMidi' with no prototype in
    function WinMain
    Warning W8057 pianno2.c 135: Parameter 'hPrevInstance' is never used in functi
    on WinMain
    Warning W8057 pianno2.c 135: Parameter 'lpCmdLine' is never used in function W
    inMain
    Warning W8004 pianno2.c 516: 'hdc' is assigned a value that is never used in f
    unction WhiteKeyWndProc
    Warning W8004 pianno2.c 593: 'hdc' is assigned a value that is never used in f
    unction BlackKeyWndProc
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

    C:\borland\bcc55\bin>

  6. #6
    Registered User
    Join Date
    Sep 2004
    Posts
    57
    Many Thanks to everyone!

    Bob, nice catch, thanks. For this app, I think it's ok to leave that in as is. For other apps I may need to be aware of a potential problem.

    To Quantum1024, nice catch too, thanks. I had noticed what you point out and had decided to leave it as a feature: I can sustain individual notes (the"sustain" checkbox sustains all notes).

    To Dante, thanks for the fix! Very instructive to me.
    I'm guessing another possible fix is to have a WM_LBUTTONUP in the other windows (PianoWndProc and MainWndProc) which just simply turns off every note if "sustain" checkbox is not set). Also, thanks for the gcc help.

    To kryptkat, thanks for the bcc55 solution! I'm baffled why bcc32 gives a warning "'initMidi' with no prototype in function WinMain", since the prototype is 20 lines up, as a global prototype.

    Again, thanks everyone! I'm trying to pay back your help by seeing if I can help others (but I give the experts a chance to respond first).

  7. #7
    Registered User Queatrix's Avatar
    Join Date
    Apr 2005
    Posts
    1,342
    Works fine on 2000 too.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Just starting Windows Programming, School me!
    By Shamino in forum Windows Programming
    Replies: 17
    Last Post: 02-22-2008, 08:14 AM
  2. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  3. Buttons + Edit Control
    By jay kay in forum Windows Programming
    Replies: 6
    Last Post: 03-09-2005, 05:36 PM
  4. opengl help
    By heat511 in forum Game Programming
    Replies: 4
    Last Post: 04-05-2004, 01:08 AM
  5. Invoking MSWord
    By Donn in forum C Programming
    Replies: 21
    Last Post: 09-08-2001, 04:08 PM