Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

881 lines
32 KiB

/*
** SND.C
**
** Sound applet for the NT Control Panel.
**
*/
/* Revision history:
* Laurie Griffiths 19/12/91 Ported the windows 3.1 code to NT
*/
/*=============================================================================
| The whole thing is kicked off by Init.c
| When the DLL is loaded DllInitialize in init.c is called (as a result of
| the DLLENTRY line in SOURCES). This just loads some static strings
| with values dug out of resources.
|
| The control panel then calls CPlApplet in init.c with a series of
| messages which are explained in control\h\cpl.h
|
| The CPL_INQUIRE message is different in 3.1 (CPL_NEWINQUIRE).
|
| The big one is CPL_DBLCLK which is the go signal.
| A dialog box is created in RunApplet in init.c with window procedure
| SoundDlg (end of this file).
|
| WM_INITDIALOG is the trigger to fill the list boxes with text which is
| taken from the INI file (InitDialog). If there is no wave device present
| then it just allows the user to set the message beep flag (displays
| original state and allows alteration). If there is a wave device then
| the Test button is enabled. Whether or not there is a device to play the
| files, you can still assign them to events. This could be useful
| to someone installing the system. There's no real reason why they should
| be forced to configure the sound board first.
|
| Currently it does a message box to say that there's no sound board.
| Is this too intrusive?
|
| The calling tree looks like:
|
| DllInitialize loads resources
|
| CPlApplet main entry point from control panel (in init.c)
| RunApplet brings up dialog box (in init.c)
| DialogBox
| SoundDlg dialog procedure
| InitDialog
| FindDescription find description in <name=file,descr> string
| ShowSound show filename associated with a sound
| NewSound update list box with new <name,file,descr>
| catPath concatenate path onto file
| DrawItem draw item in list box
| DrawItemText draw text of item
| GetSoundEntry interrogate list box
| ControlMessage process messages from controls in dialogs
| EnablePlay enable/disable the TEST button
| FillDirBox fill list box from files in current dir
| ShowSound show filename associated with a sound
| PlayTheSound play the i-th sound entry
| GetSoundEntry interrogate list box
| WriteSounds write out a new [sounds] section
| ChangeSound change the filename associated with a sound
| QualifyFileName get full path name of file
| NewSound update list box with new <name,file,descr>
| GetSoundEntry interrogate list box
|
| The following are called from several places in the above
|
| GetSoundEntry
| FindDescription find description in <name=file,descr> string
|
| EnablePlay enable/disable the TEST button
| GetSoundEntry interrogate list box
|
| ShowSound show filename associated with a sound
| GetSoundEntry interrogate list box
| QualifyFileName get full path name of file
| FileName extract file name from full path name
| StripPathName split path into path and file by inserting null
| FileName extract file name from full path name
| FillDirBox fill list box from files in current dir
| EnablePlay enable/disable the TEST button
============================================================================*/
#include <windows.h>
#include <mmsystem.h>
#include <port1632.h>
#include <cphelp.h>
#include <cpl.h>
#include <shellapi.h>
#include "snd.h"
#define SetWindowRedraw(hwnd, fRedraw) \
((VOID)SendMessage(hwnd, WM_SETREDRAW, (UINT)(BOOL)(fRedraw), 0L))
/*---------------------------------------------------------------------------*/
#define STRSIZ MAX_PATH // maximum size of a string or filename
#define MAXINI 4096 // max size of all ini keys in [sounds] section
#define SLASH(c) ((c) == '/' || (c) == '\\')
/*
** DLGOPEN private definitions
**/
#define ATTRFILELIST 0x0000 // include files only
#define ATTRDIRLIST 0xC010 // directories and drives ONLY
/*---------------------------------------------------------------------------*/
static SZCODE aszNull[] = "";
static SZCODE aszDirSeparator[] = "\\";
static SZCODE aszResourceDir[]= "resource";
static SZCODE aszSounds[] = "sounds";
static SZCODE aszNewSoundFindFormat[] = "%s=";
static SZCODE aszNewSoundFormat[] = "%s=%s,%s";
static SZCODE aszCurrentDir[] = ".";
static SZCODE aszFileFilter[] = "*.wav";
static char aszAllFiles[] = "*.*"; // this is written on by DlgDirList()
static BOOL fSndPlaySound; // sound board working
static BOOL fIniChanged;
static BOOL fEnabled= FALSE; // True iff [Sounds] Enabled=1 in Win.ini
#if PARANOIA
/*---------------------------------------------------------------------------
| put <title><str>"\n" out onto debug screen
----------------------------------------------------------------------------*/
void Trace(LPSTR lpstr, LPSTR lpstrTitle)
{ char msg[255];
if (!lpstr) lpstr = "";
if (!lpstrTitle) lpstrTitle = "SOUND: SND.C";
wsprintf(msg, "%s %s\n", lpstrTitle, lpstr);
OutputDebugString(msg);
} /* Trace */
#endif
/*---------------------------------------------------------------------------
| ?
----------------------------------------------------------------------------*/
static VOID PASCAL NEAR CPHelp( HWND hwnd, DWORD dContext)
{ WinHelp(hwnd, aszSoundHlp, HELP_CONTEXT, dContext);
} /* CPHelp */
/*---------------------------------------------------------------------------
| lszEntry points to a string from WIN.INI
| split it at the start of the description by inserting 0 and return
| pointer to the description
|
| CASE1 (nice -- delimiter present )
| input string : text<delim>text
| return ptr : ^
| output string: text0 text
| where <delim> ::= ","[{<tab>|<space>|","}...]
| 0 represents the end-of-string delimiter
|
| CASE2 (nasty -- no delimiter present )
| input string : text0
| return ptr : ^
| output string: text0
| (Since Fangled And Tangled file systems allow spaces in names, the delimiter
| rules were changed from DOS require the delimiter to start with comma).
----------------------------------------------------------------------------*/
static LPSTR FindDescription( LPSTR lszEntry)
{
/* skip to next end-of-string or comma (space or tab no longer count) */
for (
; *lszEntry && *lszEntry!=','
; lszEntry++
)
;
if (*lszEntry)
{ BOOL fComma;
fComma = (*lszEntry == ',');
*lszEntry = (char)0;
/* skip the inserted null and any following blanks and tabs */
for (lszEntry++; *lszEntry == ' ' || *lszEntry == '\t'; lszEntry++)
;
/* if now found a comma and hadn't before, skip tabs and spaces again */
if (!fComma && (*lszEntry == ','))
{ for (lszEntry++; *lszEntry == ' ' || *lszEntry == '\t'; lszEntry++)
;
}
}
return lszEntry;
} /* FindDescription */
/*---------------------------------------------------------------------------
| Get (Event, File, Description) from the iListEntry-th entry in the NAMES list box
| iListEntry==-1 means use the current selection
| Supplying NULL for any of these PLPSTRs is safe and means don't bother
| to return this item.
----------------------------------------------------------------------------*/
static VOID NEAR GetSoundEntry( HWND hwnd /* dialog box */
, int iListEntry /* number of event */
, LPSTR lszEvent /* event name returned */
, LPSTR lszFile /* file name returned */
, LPSTR lszDescription /* description returned */
)
{ char aszBuffer[STRSIZ];
LPSTR lszCur;
LPSTR lszStart;
/* aszBuffer = text of iListEntry-th entry in list box, -1 => use current */
hwnd = GetDlgItem(hwnd, LB_NAMES);
if (iListEntry == -1)
iListEntry = (int)(LONG)
SendMessage(hwnd, LB_GETCURSEL, (WPARAM)0, (LPARAM)0);
lstrcpy(aszBuffer, (PSTR)SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iListEntry, (LPARAM)0));
/* replace "=" in aszBuffer with NULL (there'd better be one there!) */
for (lszCur = aszBuffer; *lszCur != '='; lszCur++)
;
*lszCur = (char)0;
/* lszEvent = <Event> from list entry */
if (lszEvent)
{ lstrcpy(lszEvent, aszBuffer);
}
lszStart = ++lszCur;
lszCur = FindDescription(lszCur);
if (lszFile)
{ if (!lstrcmpi(lszStart, aszNoSound))
*lszFile = (char)0;
else
lstrcpy(lszFile, lszStart);
}
if (lszDescription)
{ if (!*lszCur)
lszCur = aszBuffer;
lstrcpy(lszDescription, lszCur);
}
}/* GetSoundEntry */
/*---------------------------------------------------------------------------
| get full path name of file. Return TRUE iff it worked.
| updates lszFile, assumes there is enough room.
----------------------------------------------------------------------------*/
static BOOL NEAR PASCAL QualifyFileName( LPSTR lszFile )
{ OFSTRUCT of;
UINT fErrMode;
BOOL fReturn;
fErrMode = SetErrorMode(SEM_FAILCRITICALERRORS); /* return errors to us */
if ( OpenFile( lszFile
, &of
, OF_EXIST | OF_SHARE_DENY_NONE | OF_READ
)
!= HFILE_ERROR
)
{ OemToAnsi(of.szPathName, lszFile);
fReturn = TRUE;
} else
fReturn = FALSE;
SetErrorMode(fErrMode);
return fReturn;
}/* QualifyFileName */
/*---------------------------------------------------------------------------
| update lszPath to point to file-name at end of path-and-file-name
----------------------------------------------------------------------------*/
static LPSTR NEAR PASCAL FileName( LPCSTR lszPath)
{ LPCSTR lszCur;
/* move forward to first null */
for (lszCur = lszPath; *lszCur; lszCur++)
;
/* move backwards until find SLASH or colon */
for (; lszCur >= lszPath && !SLASH(*lszCur) && *lszCur != ':'; lszCur--)
;
/* move forwards one char */
return (LPSTR)++lszCur;
}/* FileName */
/*---------------------------------------------------------------------------
| update lszPath to insert a null at end of path (possibly hitting the "\"
| possibly hitting the start of the file name)
----------------------------------------------------------------------------*/
static VOID NEAR PASCAL StripPathName( LPSTR lszPath)
{ LPSTR lszCur;
/* move on to first char of filename at end of path */
lszCur = FileName(lszPath);
/* if path at least two chars long and ends in \ and not in :\
| then move back one char
*/
if (lszCur > lszPath+1 && SLASH(lszCur[-1]) && lszCur[-2] != ':')
lszCur--;
/* insert null */
*lszCur = (char)0;
}/* StripPathName */
/*---------------------------------------------------------------------------
| show the filenames that can be associated with sounds
----------------------------------------------------------------------------*/
static VOID NEAR FillDirBox( HWND hwnd
, LPSTR lszDir // the path
)
{ char aszCWD[STRSIZ];
char aszNewCWD[STRSIZ];
int iDirLen;
UINT fErrMode;
// remove any trailing '/'
iDirLen = lstrlen(lszDir) - 1;
if (SLASH(lszDir[iDirLen]) && lszDir[iDirLen - 1] != ':')
lszDir[iDirLen] = (char)0;
GetCurrentDirectory(STRSIZ, aszCWD);
fErrMode = SetErrorMode(SEM_FAILCRITICALERRORS); /* return errors to us */
if ( !SetCurrentDirectory(lszDir) // set from string
|| !GetCurrentDirectory(STRSIZ, aszNewCWD) // get canonical form?
)
{ /* failed! back out and beep */
SetCurrentDirectory(aszCWD);
SetErrorMode(fErrMode);
MessageBeep(0);
} else
{ HWND hwndFiles;
SetErrorMode(fErrMode);
hwndFiles = GetDlgItem(hwnd, LB_FILES);
if ( !(int)(LONG)
SendMessage( hwndFiles, LB_GETCOUNT, (WPARAM)0, (LPARAM)0)
|| lstrcmpi(aszNewCWD, aszCWD)
)
{ /* Fill directory listbox from current directory */
SetWindowRedraw(hwndFiles, FALSE);
DlgDirList(hwnd, aszAllFiles, LB_FILES, ID_DIR, ATTRDIRLIST);
SendMessage( hwndFiles
, LB_DIR
, (WPARAM)ATTRFILELIST
, (LPARAM)(LPCSTR)aszFileFilter
);
SetWindowRedraw(hwndFiles, TRUE);
SendMessage( hwndFiles
, LB_ADDSTRING
, (WPARAM)0
, (LPARAM)(LPCSTR)aszNoSound
);
}
}
}/* FillDirBox */
/*---------------------------------------------------------------------------
| Enable or Disable the test button, file and sound displays
----------------------------------------------------------------------------*/
static VOID NEAR EnablePlay( HWND hwnd)
{ char aszFile[STRSIZ];
int iSelection;
BOOL fSelection;
HWND hwndFiles;
hwndFiles = GetDlgItem(hwnd, LB_FILES);
iSelection = (int)(LONG)
SendMessage(hwndFiles, LB_GETCURSEL, (WPARAM)0, (LPARAM)0);
fSelection = DlgDirSelectEx(hwnd, aszFile, STRSIZ, LB_FILES);
GetSoundEntry(hwnd, -1, NULL, aszFile, NULL);
EnableWindow( GetDlgItem(hwnd, ID_PLAY) // the TEST button
, fSndPlaySound
&& !fSelection
&& *aszFile
&& (iSelection != LB_ERR)
);
// enable disable the listboxes -- actually always enable (LKG)
EnableWindow(GetDlgItem(hwnd, LB_NAMES), TRUE || fSndPlaySound);
EnableWindow(hwndFiles, TRUE || fSndPlaySound);
}/* EnablePlay */
/*---------------------------------------------------------------------------
| Select the i-th element in the event NAMES list box
| Look up the file from the registry.
| Refill the FILES list box based on the dir containing the file
| Highlight (select) the file associated with it in the FILES list box
| if possible - the filename from the registry might be crap
| If there is no file, set the selection to no sound
----------------------------------------------------------------------------*/
static VOID NEAR ShowSound( HWND hwnd, int i)
{ char aszFile[STRSIZ];
char aszPath[STRSIZ];
if (i != -1)
SendDlgItemMessage(hwnd, LB_NAMES, LB_SETCURSEL, (WPARAM)i, (LPARAM)0);
GetSoundEntry(hwnd, i, NULL, aszFile, NULL);
lstrcpy(aszPath, aszFile);
if (QualifyFileName(aszPath))
{
LRESULT lRc;
StripPathName(aszPath); /* aszPath is now just the path */
FillDirBox(hwnd, aszPath);
lRc = SendDlgItemMessage( hwnd
, LB_FILES
, LB_SELECTSTRING
, (WPARAM)-1
, (LPARAM)FileName(aszFile)
);
if (lRc==-1) {
/* We couldn't find the file name in the list box.
** The most likely reason is that the file name contains a comma
** and we have stored the short file name in the registry.
** (storing file names with commas in the registry breaks the
** parsing scheme which is inherited from DOS. Some apps go
** looking there so we need to keep compatibility.
** FindFirstFile is how you get the long name back
*/
WIN32_FIND_DATA fd;
FindFirstFile(aszFile, &fd);
lRc = SendDlgItemMessage( hwnd
, LB_FILES
, LB_SELECTSTRING
, (WPARAM)-1
, (LPARAM)FileName(fd.cFileName)
);
if (lRc==-1) {
/* Can't even find the long name - maybe there' stuff in the registry
** or the file has been deleted.
*/
SendDlgItemMessage(hwnd, LB_FILES, LB_SETCURSEL, (WPARAM)(-1), (LPARAM)0);
}
}
} else
{
FillDirBox(hwnd, aszCurrentDir);
SendDlgItemMessage( hwnd
, LB_FILES
, LB_SELECTSTRING
, (WPARAM)-1
, (LPARAM)(LPCSTR)aszNoSound
);
}
EnablePlay(hwnd);
}/* ShowSound */
/*---------------------------------------------------------------------------
| play the filename associated with a sound
----------------------------------------------------------------------------*/
static VOID NEAR PlayTheSound( HWND hwnd, int i)
{ char aszFile[STRSIZ];
GetSoundEntry(hwnd, i, NULL, aszFile, NULL);
// play the sound if it is not associated with <none>
if (fSndPlaySound && *aszFile)
{ BOOL fPlayed;
HCURSOR hcur;
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
fPlayed = sndPlaySound(aszFile, SND_ASYNC | SND_FILENAME);
#if PARANOIA
Trace("Sound should have played", NULL);
#endif //DBG
SetCursor(hcur);
// The sound did not play, tell the user.
if (!fPlayed)
MessageBox(hwnd, aszErrorPlayMessage, aszErrorPlayTitle, MB_OK);
}
}/* PlayTheSound */
/*---------------------------------------------------------------------------
| update list box.
| add/repl any <lszEvent>=... entry with <lszEvent>=<lszFile>,<lszDescription>
----------------------------------------------------------------------------*/
static VOID NEAR NewSound( HWND hwnd /* dialog box window handle */
, LPCSTR lszEvent
, LPCSTR lszFile
, LPCSTR lszDescription
)
{
PSTR szEntry;
int iSound;
int iNewSound;
hwnd = GetDlgItem(hwnd, LB_NAMES);
/*
** The original Win 31 did not check the return value from LocalAlloc
** i'll just return if we could not allocate the storage.
*/
szEntry = (PSTR)LocalAlloc(LMEM_FIXED, lstrlen(lszEvent)
+ lstrlen(lszFile)
+ lstrlen(lszDescription) + 3);
if ( szEntry == NULL ) {
return;
}
iSound = (int)(LONG)SendMessage(hwnd, LB_FINDSTRING, (WPARAM)-1, (LPARAM)lszDescription);
if (iSound == LB_ERR)
iNewSound = (int)(DWORD)SendMessage(hwnd, LB_ADDSTRING,
(WPARAM)0, (LPARAM)lszDescription);
else {
LocalFree((HLOCAL)SendMessage(hwnd, LB_GETITEMDATA,
(WPARAM)iSound, (LPARAM)0));
iNewSound = iSound;
}
wsprintf(szEntry, aszNewSoundFormat, lszEvent, lszFile, lszDescription);
SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)iNewSound, (LPARAM)szEntry );
if (iSound == LB_ERR)
SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iNewSound, (LPARAM)0);
if (iSound != LB_ERR)
SetWindowRedraw(hwnd, TRUE);
}/* NewSound */
/*---------------------------------------------------------------------------
| change the file associated with a sound
----------------------------------------------------------------------------*/
static VOID NEAR ChangeSound(HWND hwnd,int iSound, LPSTR lszFile)
{ char aszName[STRSIZ];
char aszDescription[STRSIZ];
char aszShortName[STRSIZ];
if (!QualifyFileName(lszFile))
lszFile = aszNull;
GetSoundEntry(hwnd, iSound, aszName, NULL, aszDescription);
/* because long file names can contain commas which totally mess with the parsing
of the directory entries (basically <event>=<file>,<descr>), if there is
a comma in the long file name, we put the short one in instead.
If the short name also has a comma, then we're in trouble. Such file
names are not allowed! In this case we set the sound to <none>
*/
if (0 != strchr(lszFile,',')) {
GetShortPathName(lszFile, aszShortName, STRSIZ);
lszFile = aszShortName;
if (0 != strchr(lszFile,','))
strcpy(lszFile, "<none>");
}
NewSound(hwnd, aszName, lszFile, aszDescription);
}/* ChangeSound */
/*---------------------------------------------------------------------------
| write out a new [sounds] section
----------------------------------------------------------------------------*/
static VOID NEAR WriteSounds(HWND hwnd)
{ int iSound;
int iTotalSounds;
BOOL bAllOK = TRUE; /* all sounds written OK */
DWORD dwLastError = 0;
/* The idea is to capture the error code of the first error that we see,
to put up an error box in the event of any error (so that the user has
some idea of what has happened), but to continue to the end anyway
as it may be that it's still going to write all the data anyway
*/
hwnd = GetDlgItem(hwnd, LB_NAMES);
iTotalSounds = (int)(LONG)SendMessage( hwnd
, LB_GETCOUNT
, (WPARAM)0
, (LPARAM)0
);
// delete the whole section;
bAllOK = WriteProfileString(aszSounds, NULL, NULL);
if (!bAllOK)
{ dwLastError = GetLastError();
if (dwLastError==259) /* "No more items". This is normal */
{ bAllOK = TRUE;
dwLastError = 0;
}
}
//Write Enabled flag
if(fEnabled)
{ BOOL bOK = WriteProfileString(aszSounds, "Enable", "1");
if (bAllOK && !bOK)
{ dwLastError = GetLastError();
}
bAllOK = bAllOK && bOK;
}
else
{ BOOL bOK = WriteProfileString(aszSounds, "Enable", "0");
if (bAllOK && !bOK)
{ dwLastError = GetLastError();
}
bAllOK = bAllOK && bOK;
}
for (iSound = 0; iSound < iTotalSounds; iSound++)
{ char aszBuffer[STRSIZ];
LPSTR lszCur;
BOOL bOK;
lstrcpy(aszBuffer, (PSTR)SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iSound, (LPARAM)0));
for (lszCur = aszBuffer; *lszCur != '='; lszCur++)
;
*lszCur = (char)0;
bOK = WriteProfileString(aszSounds, aszBuffer, lszCur + 1);
if (bAllOK && !bOK)
{ dwLastError = GetLastError();
}
bAllOK = bAllOK && bOK;
}
if (!bAllOK)
{ char szErr[STRSIZ];
wsprintf(szErr, aszWriteErr, GetLastError());
MessageBox(hwnd, szErr, aszAppName, MB_OK);
}
SendMessage( (HWND)-1
, WM_WININICHANGE
, (WPARAM)0
, (LPARAM)(LPCSTR)aszSounds
);
} /* WriteSounds */
/*---------------------------------------------------------------------------
| Process control message from dialog box
----------------------------------------------------------------------------*/
static VOID PASCAL NEAR ControlMessage(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
switch ((WORD)wParam)
{ HWND hwndFocus;
case IDH_CHILD_SND:
CPHelp(hwnd, dwContext);
break;
case IDOK:
hwndFocus = GetFocus();
if (hwndFocus && (GetDlgCtrlID(hwndFocus) == LB_FILES))
#if defined(WIN16)
PostMessage( hwnd
, WM_COMMAND
, (WPARAM)LB_FILES
, MAKELPARAM(hwndFocus, LBN_DBLCLK)
);
#else
PostMessage( hwnd
, WM_COMMAND
, (WPARAM)MAKELONG(LB_FILES,LBN_DBLCLK)
, (LPARAM)hwndFocus
);
#endif //WIN16
else
{ HCURSOR hcur;
BOOL fBeep;
if (fIniChanged)
{ if ( MessageBox( hwnd
, aszWarningMessage
, aszWarningTitle
, MB_ICONEXCLAMATION | MB_OKCANCEL
)
== IDCANCEL
)
{ // PostMessage(hwnd, WM_INITDIALOG, 0, 0L);
//Bug #3298 -jyg-
break;
}
}
/* hourglass while we do things */
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
/* write any sounds away. */
if (fSndPlaySound)
sndPlaySound(NULL, 0); // flush any cached sounds
#if PARANOIA
Trace("Sound should have been flushed", NULL);
#endif //DBG
WriteSounds(hwnd);
/* Write the new beep setting */
SystemParametersInfo(SPI_GETBEEP, 0, &fBeep, 0);
if (fBeep != (BOOL)IsDlgButtonChecked(hwnd, ID_BEEP))
SystemParametersInfo( SPI_SETBEEP
, !fBeep
, NULL
, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE
);
/* restore pointer */
SetCursor(hcur);
EndDialog(hwnd, TRUE);
}
break;
case IDCANCEL:
if (fSndPlaySound)
sndPlaySound(NULL, 0); // Shut up when the dialog exits
// meaningful when we go async
#if PARANOIA
Trace("Sound should have been killed", NULL);
#endif // DBG
EndDialog(hwnd, FALSE);
break;
case ID_PLAY:
PlayTheSound(hwnd, -1);
break;
case ID_BEEP:
break;
case LB_NAMES:
switch(HIWORD(wParam)) /* NT change, was HIWORD(lParam) */
{ case LBN_SELCHANGE:
ShowSound(hwnd, -1);
break;
case LBN_DBLCLK:
PostMessage(hwnd, WM_COMMAND, (WPARAM)ID_PLAY, (LPARAM)0);
break;
}
break;
case LB_FILES:
switch(HIWORD(wParam))
{ char aszSelection[STRSIZ];
case LBN_SELCHANGE:
if (!DlgDirSelectEx(hwnd, aszSelection, STRSIZ, LB_FILES))
ChangeSound(hwnd, -1, aszSelection);
EnablePlay(hwnd);
break;
case LBN_DBLCLK:
if (DlgDirSelectEx(hwnd, aszSelection, STRSIZ, LB_FILES))
FillDirBox(hwnd, aszSelection);
else
PostMessage(hwnd, WM_COMMAND, (WPARAM)ID_PLAY, (LPARAM)0);
break;
}
break;
}
}/* ControlMessage */
/*---------------------------------------------------------------------------
| lszpath = lszpath [\] xlsz
| where xlsz is lsz with any leading drive: and .\ removed
----------------------------------------------------------------------------*/
static VOID NEAR PASCAL catpath( LPSTR lszpath, LPCSTR lsz)
{
// Remove any drive letters from the directory to append
if (lsz[1] == ':')
lsz += 2;
// Remove any current directories ".\" from directory to append
while (*lsz == '.' && SLASH(lsz[1]))
lsz += 2;
// Dont append a NULL string or a single "."
if (*lsz && !(*lsz == '.' && !lsz[1]))
{ /* add a "\" unless it already ends in "\" or ":" */
if ( (!SLASH(lszpath[lstrlen(lszpath)-1]))
&& ((lszpath[lstrlen(lszpath)-1]) != ':')
)
lstrcat(lszpath, aszDirSeparator);
lstrcat(lszpath, lsz);
}
}/* catpath */
/*---------------------------------------------------------------------------
| Initialse the dialog
| fIniChanged = FALSE
----------------------------------------------------------------------------*/
static BOOL PASCAL NEAR InitDialog( HWND hwnd /* dlg box window */
)
{ char aszBuffer[STRSIZ];
WAVEOUTCAPS woCaps;
LPSTR lszSection;
HANDLE hgSection;
BOOL fBeep;
BOOL fSoundsExist = TRUE;
fIniChanged = FALSE;
// Determine if there is a wave device;
fSndPlaySound = waveOutGetNumDevs()
&& !waveOutGetDevCaps(0, &woCaps, sizeof(woCaps))
&& woCaps.dwFormats != 0L;
/*********************************************
* fSndPlaySound
* = (IDYES==MessageBox(NULL,"Pretend sound device available?","???",MB_YESNO));
**********************************************/
if (!fSndPlaySound)
MessageBox(hwnd, aszNoDevice, aszErrorPlayTitle, MB_OK);
// Set the Windows Enabled flag
fEnabled = (1==GetProfileInt(aszSounds, "Enable", 0));
/* fill the list box with the [sounds] section of WIN.INI; */
if ((hgSection = GlobalAlloc(GMEM_MOVEABLE, (DWORD)MAXINI)) == NULL)
return FALSE;
lszSection = (LPVOID)GlobalLock(hgSection);
if (0<(int)GetProfileString(aszSounds, NULL, aszNull, lszSection, MAXINI))
{
for (; *lszSection; lszSection += lstrlen(lszSection) + 1)
{
LPSTR lszDescription;
if (0>=(int)GetProfileString( aszSounds
, lszSection
, aszNull
, aszBuffer
, sizeof(aszBuffer)
)
) break;
/* split string by inserting null and get pointer to second part */
lszDescription = FindDescription(aszBuffer);
if (!*lszDescription)
lszDescription = lszSection;
if (0!=lstrcmpi(lszSection,"Enable"))
{
NewSound(hwnd, lszSection, aszBuffer, lszDescription);
}
}
}
else fSoundsExist = FALSE;
GlobalUnlock(hgSection);
GlobalFree(hgSection);
// Try to change to the windows "resource" directory;
// if that fails hit up the windows "system" directory;
GetWindowsDirectory(aszBuffer, sizeof(aszBuffer));
catpath(aszBuffer, aszResourceDir);
if (!SetCurrentDirectory(aszBuffer))
{ GetSystemDirectory(aszBuffer, sizeof(aszBuffer));
SetCurrentDirectory(aszBuffer);
}
// select the first sound; There might not be any courtesy SteveWo.
if (fSoundsExist) ShowSound(hwnd, 0);
// Get the beep enabled flag from USER;
SystemParametersInfo(SPI_GETBEEP, 0, (&fBeep), 0);
CheckDlgButton(hwnd, ID_BEEP, fBeep);
}/* InitDialog */
/*---------------------------------------------------------------------------*/
static VOID PASCAL NEAR Destroy(
HWND hwnd)
{
int iEvents;
hwnd = GetDlgItem(hwnd, LB_NAMES);
iEvents = (int)(DWORD)SendMessage(hwnd, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
for (; iEvents--;)
LocalFree((HLOCAL)SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)iEvents, (LPARAM)0));
}
/*---------------------------------------------------------------------------
| Dialog procedure for the dialog box
----------------------------------------------------------------------------*/
INT_PTR SoundDlg( HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
{
switch (uMsg)
{
case WM_WININICHANGE:
// See if someone has modified the sounds section or can't tell;
if ( !lstrcmpi((LPCSTR)lParam, aszSounds)
|| !*((LPCSTR)lParam)
)
fIniChanged = TRUE;
break;
case WM_COMMAND:
ControlMessage(hwnd, wParam, lParam);
return TRUE;
case WM_INITDIALOG:
return InitDialog(hwnd);
case WM_DESTROY:
Destroy(hwnd);
break;
default:
if (uMsg == uHelpMessage)
{ CPHelp(hwnd, dwContext);
return TRUE;
}
break;
}
return FALSE;
}/* SoundDlg */