
Introduction:
Have you seen all the funny soundboards out there on the internet? Perhaps you have used one to do prank phone calls to your relatives for a funny joke. These kind of apps have risen in popularity with the dawn of mobile apps. With this tutorial we will revisit the popular soundboard with the use of simple buttons and playing sound events using the windows api. This tutorial is a follow up of “How to use wave files as resources in c++“. This time we will be using buttons instead of cin >> input;. Thus we will be leaving the shell commands and migrating into a little taste of windows gui.
NOTE: We must enter -lwinmm in the linker settings or PlaySound() will not work.
Resource Script:
We will need to use a resource script as mentioned in the previous tutorial. This will define our audio files as the names IDW_SOUND1, IDW_SOUND2, IDW_SOUND3, and IDW_SOUND4. WAVE defines the type of resource then the next portion of syntax is the file path of the resource. The .rc file tells the compiler where to get these resources and where to place them inside the executable at runtime. This should start to make a little more sense when you review the code below.
resource.rc
|
1 2 3 4 5 6 7 |
#include "resource.h"
//Define the files as IDW_SOUND! (resource name) and of type WAVE then filepath
IDW_SOUND1 WAVE "1.wav"
IDW_SOUND2 WAVE "2.wav"
IDW_SOUND3 WAVE "3.wav"
IDW_SOUND4 WAVE "4.wav" |
Resource Header:
The purpose of the header file is to teach the compiler how to access the resources we described in the resource script. To do this we define the names IDW_SOUND1, IDW_SOUND2, IDW_SOUND3, and IDW_SOUND4 as resources by associating them with unique IDs 1000, 1001, 1002, and 1003. These numbers are arbitrary thus you could use anything here just don’t duplicate them. Since we will be using the PlaySound() function we need to tell the compiler what to do when the name is called upon using #ifdef RC_INVOKED. This tells the compiler if the name is invoked then use the resources described. This will make sense when you review the code below.
resource.h
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//Defines
#define IDW_SOUND1 1000
#define IDW_SOUND2 1001
#define IDW_SOUND3 1002
#define IDW_SOUND4 1003
//If these are invoked as resources load them
#ifdef RC_INVOKED
IDW_SOUND1 WAVE "1.wav"
IDW_SOUND2 WAVE "2.wav"
IDW_SOUND3 WAVE "3.wav"
IDW_SOUND4 WAVE "4.wav"
#endif |
Main Program:
This is where all our gui related features come to life using the windows api. We must include the resource.h file to let the compiler know when we are invoking the audio resources. The GetSystemMetrics() function gets the width and height of the users computer screen. We will then take this and put it in the variable screenWidth and screenHeight respectively but applying some logic first screenWidth = (screenWidth / 2) – 115. This will account for the size of the initial window created because GetSystemMetrics(SM_CXSCREEN) and GetSystemMetrics(SM_CYSCREEN) only returns the size of the entire screen. Windows sets position based on the upper left hand corner thus applying this with variables is the best way to approach this issue. The buttons can be found in the function CreateWindow(TEXT(“button”), TEXT(“SFX1″), WS_VISIBLE | WS_CHILD , 20, 50, 80, 25, hwnd, (HMENU) 1, NULL, NULL) the first 20 is the x position the next is the y position and the width and height follow. (HMENU) 1 is the event number in which we will use to trigger the sound. Using if (LOWORD(wParam) == 1) will trigger the event to the PlaySound() function. PlaySound(MAKEINTRESOURCE(IDW_SOUND4), NULL, SND_RESOURCE | SND_ASYNC) will trigger the sound from the resource header. MAKEINTRESOURCE() function retrieves the file from the resources inside the executable so we don’t have to include our resources as separate files thus we have a portable standalone executable. This should make more sense once you review the code below.
main.cpp
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#include <iostream>
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT( "Buttons" );
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc ;
wc.hCursor = LoadCursor(0, IDC_ARROW);
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
screenWidth = (screenWidth / 2) - 115;
screenHeight = (screenHeight / 2) - 90;
RegisterClass(&wc);
CreateWindow( wc.lpszClassName, TEXT("SoundBoard Tutorial"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
screenWidth, screenHeight, 230, 180, 0, 0, hInstance, 0);
while( GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch(msg)
{
case WM_CREATE:
{
CreateWindow(TEXT("button"), TEXT("SFX1"),
WS_VISIBLE | WS_CHILD ,
20, 50, 80, 25,
hwnd, (HMENU) 1, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("SFX2"),
WS_VISIBLE | WS_CHILD ,
20, 80, 80, 25,
hwnd, (HMENU) 2, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("SFX3"),
WS_VISIBLE | WS_CHILD ,
120, 50, 80, 25,
hwnd, (HMENU) 3, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("SFX4"),
WS_VISIBLE | WS_CHILD ,
120, 80, 80, 25,
hwnd, (HMENU) 4, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("ABOUT"),
WS_VISIBLE | WS_CHILD ,
20, 110, 80, 25,
hwnd, (HMENU) 5, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("QUIT"),
WS_VISIBLE | WS_CHILD ,
120, 110, 80, 25,
hwnd, (HMENU) 6, NULL, NULL);
break;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == 1){
PlaySound(MAKEINTRESOURCE(IDW_SOUND1), NULL, SND_RESOURCE | SND_ASYNC);
}
if (LOWORD(wParam) == 2){
PlaySound(MAKEINTRESOURCE(IDW_SOUND2), NULL, SND_RESOURCE | SND_ASYNC);
}
if (LOWORD(wParam) == 3){
PlaySound(MAKEINTRESOURCE(IDW_SOUND3), NULL, SND_RESOURCE | SND_ASYNC);
}
if (LOWORD(wParam) == 4){
PlaySound(MAKEINTRESOURCE(IDW_SOUND4), NULL, SND_RESOURCE | SND_ASYNC);
}
if (LOWORD(wParam) == 5){
MessageBox(NULL, "This tutorial was created by www.lukechalaudio.com", "About", MB_OK);
}
if (LOWORD(wParam) == 6) {
PostQuitMessage(0);
}
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
} |
Final Remarks:
With a little basic knowledge it starts becomes easy to trigger audio events from code. Since you have read the post you can now have the source code and files.
Download Source
I hope this helps with your current projects.










