mirror of https://github.com/tongzx/nt5src
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.
1968 lines
52 KiB
1968 lines
52 KiB
//==========================================================================;
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (c) 1992 - 1994 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// acmapp.c
|
|
//
|
|
// Description:
|
|
// This is a sample application that demonstrates how to use the
|
|
// Audio Compression Manager API's in Windows. This application is
|
|
// also useful as an ACM driver test.
|
|
//
|
|
//==========================================================================;
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <mmsystem.h>
|
|
#include <commdlg.h>
|
|
#include <shellapi.h>
|
|
#include <stdarg.h>
|
|
#include <memory.h>
|
|
#include <mmreg.h>
|
|
#include <msacm.h>
|
|
|
|
#include "appport.h"
|
|
#include "acmapp.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
//
|
|
// globals, no less
|
|
//
|
|
HINSTANCE ghinst;
|
|
BOOL gfAcmAvailable;
|
|
UINT gfuAppOptions = APP_OPTIONSF_AUTOOPEN;
|
|
HFONT ghfontApp;
|
|
HACMDRIVERID ghadidNotify;
|
|
|
|
UINT guWaveInId = (UINT)WAVE_MAPPER;
|
|
UINT guWaveOutId = (UINT)WAVE_MAPPER;
|
|
|
|
TCHAR gszNull[] = TEXT("");
|
|
TCHAR gszAppProfile[] = TEXT("acmapp.ini");
|
|
TCHAR gszYes[] = TEXT("Yes");
|
|
TCHAR gszNo[] = TEXT("No");
|
|
|
|
TCHAR gszAppName[APP_MAX_APP_NAME_CHARS];
|
|
TCHAR gszFileUntitled[APP_MAX_FILE_TITLE_CHARS];
|
|
|
|
TCHAR gszInitialDirOpen[APP_MAX_FILE_PATH_CHARS];
|
|
TCHAR gszInitialDirSave[APP_MAX_FILE_PATH_CHARS];
|
|
|
|
TCHAR gszLastSaveFile[APP_MAX_FILE_PATH_CHARS];
|
|
|
|
ACMAPPFILEDESC gaafd;
|
|
|
|
|
|
//==========================================================================;
|
|
//
|
|
// Application helper functions
|
|
//
|
|
//
|
|
//==========================================================================;
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int AppMsgBox
|
|
//
|
|
// Description:
|
|
// This function displays a message for the application in a standard
|
|
// message box.
|
|
//
|
|
// Note that this function takes any valid argument list that can
|
|
// be passed to wsprintf. Because of this, the application must
|
|
// remember to cast near string pointers to FAR when built for Win 16.
|
|
// You will get a nice GP fault if you do not cast them correctly.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to parent window for message box holding the
|
|
// message.
|
|
//
|
|
// UINT fuStyle: Style flags for MessageBox().
|
|
//
|
|
// PTSTR pszFormat: Format string used for wvsprintf().
|
|
//
|
|
// Return (int):
|
|
// The return value is the result of MessageBox() function.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int FNCGLOBAL AppMsgBox
|
|
(
|
|
HWND hwnd,
|
|
UINT fuStyle,
|
|
PTSTR pszFormat,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
TCHAR ach[1024];
|
|
int n;
|
|
|
|
//
|
|
// format and display the message..
|
|
//
|
|
va_start(va, pszFormat);
|
|
#ifdef WIN32
|
|
wvsprintf(ach, pszFormat, va);
|
|
#else
|
|
wvsprintf(ach, pszFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
n = MessageBox(hwnd, ach, gszAppName, fuStyle);
|
|
|
|
return (n);
|
|
} // AppMsgBox()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int AppMsgBoxId
|
|
//
|
|
// Description:
|
|
// This function displays a message for the application. The message
|
|
// text is retrieved from the string resource table using LoadString.
|
|
//
|
|
// Note that this function takes any valid argument list that can
|
|
// be passed to wsprintf. Because of this, the application must
|
|
// remember to cast near string pointers to FAR when built for Win 16.
|
|
// You will get a nice GP fault if you do not cast them correctly.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to parent window for message box holding the
|
|
// message.
|
|
//
|
|
// UINT fuStyle: Style flags for MessageBox().
|
|
//
|
|
// UINT uIdsFormat: String resource id to be loaded with LoadString()
|
|
// and used a the format string for wvsprintf().
|
|
//
|
|
// Return (int):
|
|
// The return value is the result of MessageBox() if the string
|
|
// resource specified by uIdsFormat is valid. The return value is zero
|
|
// if the string resource failed to load.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int FNCGLOBAL AppMsgBoxId
|
|
(
|
|
HWND hwnd,
|
|
UINT fuStyle,
|
|
UINT uIdsFormat,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
TCHAR szFormat[APP_MAX_STRING_RC_CHARS];
|
|
TCHAR ach[APP_MAX_STRING_ERROR_CHARS];
|
|
int n;
|
|
|
|
n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
|
|
if (0 != n)
|
|
{
|
|
//
|
|
// format and display the message..
|
|
//
|
|
va_start(va, uIdsFormat);
|
|
#ifdef WIN32
|
|
wvsprintf(ach, szFormat, va);
|
|
#else
|
|
wvsprintf(ach, szFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
n = MessageBox(hwnd, ach, gszAppName, fuStyle);
|
|
}
|
|
|
|
return (n);
|
|
} // AppMsgBoxId()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// void AppHourGlass
|
|
//
|
|
// Description:
|
|
// This function changes the cursor to that of the hour glass or
|
|
// back to the previous cursor.
|
|
//
|
|
// This function can be called recursively.
|
|
//
|
|
// Arguments:
|
|
// BOOL fHourGlass: TRUE if we need the hour glass. FALSE if we need
|
|
// the arrow back.
|
|
//
|
|
// Return (void):
|
|
// On return, the cursor will be what was requested.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
void FNGLOBAL AppHourGlass
|
|
(
|
|
BOOL fHourGlass
|
|
)
|
|
{
|
|
static HCURSOR hcur;
|
|
static UINT uWaiting = 0;
|
|
|
|
if (fHourGlass)
|
|
{
|
|
if (!uWaiting)
|
|
{
|
|
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
ShowCursor(TRUE);
|
|
}
|
|
|
|
uWaiting++;
|
|
}
|
|
else
|
|
{
|
|
--uWaiting;
|
|
|
|
if (!uWaiting)
|
|
{
|
|
ShowCursor(FALSE);
|
|
SetCursor(hcur);
|
|
}
|
|
}
|
|
} // AppHourGlass()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppYield
|
|
//
|
|
// Description:
|
|
// This function yields by dispatching all messages stacked up in the
|
|
// application queue.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to main window of application if not yielding
|
|
// for a dialog. Handle to dialog box if yielding for a dialog box.
|
|
//
|
|
// BOOL fIsDialog: TRUE if being called to yield for a dialog box.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is always TRUE.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppYield
|
|
(
|
|
HWND hwnd,
|
|
BOOL fIsDialog
|
|
)
|
|
{
|
|
MSG msg;
|
|
|
|
if (fIsDialog)
|
|
{
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if ((NULL == hwnd) || !IsDialogMessage(hwnd, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
} // AppYield()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int AppSetWindowText
|
|
//
|
|
// Description:
|
|
// This function formats a string and sets the specified window text
|
|
// to the result.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window to receive the new text.
|
|
//
|
|
// PTSTR pszFormat: Pointer to any valid format for wsprintf.
|
|
//
|
|
// Return (int):
|
|
// The return value is the number of bytes that the resulting window
|
|
// text was.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int FNCGLOBAL AppSetWindowText
|
|
(
|
|
HWND hwnd,
|
|
PTSTR pszFormat,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
TCHAR ach[APP_MAX_STRING_ERROR_CHARS];
|
|
int n;
|
|
|
|
//
|
|
// format and display the string in the window...
|
|
//
|
|
va_start(va, pszFormat);
|
|
#ifdef WIN32
|
|
n = wvsprintf(ach, pszFormat, va);
|
|
#else
|
|
n = wvsprintf(ach, pszFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
SetWindowText(hwnd, ach);
|
|
|
|
return (n);
|
|
} // AppSetWindowText()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int AppSetWindowTextId
|
|
//
|
|
// Description:
|
|
// This function formats a string and sets the specified window text
|
|
// to the result. The format string is extracted from the string
|
|
// table using LoadString() on the uIdsFormat argument.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window to receive the new text.
|
|
//
|
|
// UINT uIdsFormat: String resource id to be loaded with LoadString()
|
|
// and used a the format string for wvsprintf().
|
|
//
|
|
// Return (int):
|
|
// The return value is the number of bytes that the resulting window
|
|
// text was. This value is zero if the LoadString() function fails
|
|
// for the uIdsFormat argument.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int FNCGLOBAL AppSetWindowTextId
|
|
(
|
|
HWND hwnd,
|
|
UINT uIdsFormat,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
TCHAR szFormat[APP_MAX_STRING_RC_CHARS];
|
|
TCHAR ach[APP_MAX_STRING_ERROR_CHARS];
|
|
int n;
|
|
|
|
n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
|
|
if (0 != n)
|
|
{
|
|
//
|
|
// format and display the string in the window...
|
|
//
|
|
va_start(va, uIdsFormat);
|
|
#ifdef WIN32
|
|
n = wvsprintf(ach, szFormat, va);
|
|
#else
|
|
n = wvsprintf(ach, szFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
SetWindowText(hwnd, ach);
|
|
}
|
|
|
|
return (n);
|
|
} // AppSetWindowTextId()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppFormatBigNumber
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
// LPTSTR pszNumber:
|
|
//
|
|
// DWORD dw:
|
|
//
|
|
// Return (BOOL):
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppFormatBigNumber
|
|
(
|
|
LPTSTR pszNumber,
|
|
DWORD dw
|
|
)
|
|
{
|
|
//
|
|
// this is ugly...
|
|
//
|
|
//
|
|
if (dw >= 1000000000L)
|
|
{
|
|
wsprintf(pszNumber, TEXT("%u,%03u,%03u,%03u"),
|
|
(WORD)(dw / 1000000000L),
|
|
(WORD)((dw % 1000000000L) / 1000000L),
|
|
(WORD)((dw % 1000000L) / 1000),
|
|
(WORD)(dw % 1000));
|
|
}
|
|
else if (dw >= 1000000L)
|
|
{
|
|
wsprintf(pszNumber, TEXT("%u,%03u,%03u"),
|
|
(WORD)(dw / 1000000L),
|
|
(WORD)((dw % 1000000L) / 1000),
|
|
(WORD)(dw % 1000));
|
|
}
|
|
else if (dw >= 1000)
|
|
{
|
|
wsprintf(pszNumber, TEXT("%u,%03u"),
|
|
(WORD)(dw / 1000),
|
|
(WORD)(dw % 1000));
|
|
}
|
|
else
|
|
{
|
|
wsprintf(pszNumber, TEXT("%lu"), dw);
|
|
}
|
|
|
|
|
|
return (TRUE);
|
|
} // AppFormatBigNumber()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppFormatDosDateTime
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
// LPTSTR pszDateTime:
|
|
//
|
|
// UINT uDosDate:
|
|
//
|
|
// UINT uDosTime:
|
|
//
|
|
// Return (BOOL):
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppFormatDosDateTime
|
|
(
|
|
LPTSTR pszDateTime,
|
|
UINT uDosDate,
|
|
UINT uDosTime
|
|
)
|
|
{
|
|
static TCHAR szFormatDateTime[] = TEXT("%.02u/%.02u/%.02u %.02u:%.02u:%.02u");
|
|
|
|
UINT uDateMonth;
|
|
UINT uDateDay;
|
|
UINT uDateYear;
|
|
UINT uTimeHour;
|
|
UINT uTimeMinute;
|
|
UINT uTimeSecond;
|
|
|
|
//
|
|
//
|
|
//
|
|
uTimeHour = uDosTime >> 11;
|
|
uTimeMinute = (uDosTime & 0x07E0) >> 5;
|
|
uTimeSecond = (uDosTime & 0x001F) << 1;
|
|
|
|
uDateMonth = (uDosDate & 0x01E0) >> 5;
|
|
uDateDay = (uDosDate & 0x001F);
|
|
uDateYear = (uDosDate >> 9) + 80;
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
wsprintf(pszDateTime, szFormatDateTime,
|
|
uDateMonth,
|
|
uDateDay,
|
|
uDateYear,
|
|
uTimeHour,
|
|
uTimeMinute,
|
|
uTimeSecond);
|
|
|
|
return (TRUE);
|
|
} // AppFormatDosDateTime()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// void AcmAppDebugLog
|
|
//
|
|
// Description:
|
|
// This function logs information to the debugger if the Debug Log
|
|
// option is set. You can then run DBWin (or something similar)
|
|
// to redirect the output whereever you want. Very useful for debugging
|
|
// ACM drivers.
|
|
//
|
|
// Arguments:
|
|
// PTSTR pszFormat: Pointer to any valid format for wsprintf.
|
|
//
|
|
// Return (void):
|
|
// None.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
void FNCGLOBAL AcmAppDebugLog
|
|
(
|
|
PTSTR pszFormat,
|
|
...
|
|
)
|
|
{
|
|
static TCHAR szDebugLogSeparator[] = TEXT("=============================================================================\r\n");
|
|
|
|
va_list va;
|
|
TCHAR ach[APP_MAX_STRING_ERROR_CHARS];
|
|
|
|
|
|
//
|
|
// !!! UNICODE !!!
|
|
//
|
|
//
|
|
if (0 != (APP_OPTIONSF_DEBUGLOG & gfuAppOptions))
|
|
{
|
|
if (NULL == pszFormat)
|
|
{
|
|
OutputDebugString(szDebugLogSeparator);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// format and display the string in a message box...
|
|
//
|
|
va_start(va, pszFormat);
|
|
#ifdef WIN32
|
|
wvsprintf(ach, pszFormat, va);
|
|
#else
|
|
wvsprintf(ach, pszFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
OutputDebugString(ach);
|
|
}
|
|
} // AcmAppDebugLog()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int MEditPrintF
|
|
//
|
|
// Description:
|
|
// This function is used to print formatted text into a Multiline
|
|
// Edit Control as if it were a standard console display. This is
|
|
// a very easy way to display small amounts of text information
|
|
// that can be scrolled and copied to the clip-board.
|
|
//
|
|
// Arguments:
|
|
// HWND hedit: Handle to a Multiline Edit control.
|
|
//
|
|
// PTSTR pszFormat: Pointer to any valid format for wsprintf. If
|
|
// this argument is NULL, then the Multiline Edit Control is cleared
|
|
// of all text.
|
|
//
|
|
//
|
|
// Return (int):
|
|
// Returns the number of characters written into the edit control.
|
|
//
|
|
// Notes:
|
|
// The pszFormat string can contain combinations of escapes that
|
|
// modify the default behaviour of this function. Escapes are single
|
|
// character codes placed at the _beginning_ of the format string.
|
|
//
|
|
// Current escapes defined are:
|
|
//
|
|
// ~ : Suppresses the default CR/LF added to the end of the
|
|
// printed line. Since the most common use of this function
|
|
// is to output a whole line of text with a CR/LF, that is
|
|
// the default.
|
|
//
|
|
// ` : Suppresses logging to the debug terminal (regardless of
|
|
// the global debug log options flag).
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int FNCGLOBAL MEditPrintF
|
|
(
|
|
HWND hedit,
|
|
PTSTR pszFormat,
|
|
...
|
|
)
|
|
{
|
|
static TCHAR szCRLF[] = TEXT("\r\n");
|
|
|
|
va_list va;
|
|
TCHAR ach[APP_MAX_STRING_RC_CHARS];
|
|
int n;
|
|
BOOL fCRLF;
|
|
BOOL fDebugLog;
|
|
|
|
//
|
|
// default the escapes
|
|
//
|
|
fCRLF = TRUE;
|
|
fDebugLog = TRUE;
|
|
|
|
|
|
//
|
|
// if the pszFormat argument is NULL, then just clear all text in
|
|
// the edit control..
|
|
//
|
|
if (NULL == pszFormat)
|
|
{
|
|
SetWindowText(hedit, gszNull);
|
|
|
|
AcmAppDebugLog(NULL);
|
|
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// format and display the string in the window... first search for
|
|
// escapes to modify default behaviour.
|
|
//
|
|
for (;;)
|
|
{
|
|
switch (*pszFormat)
|
|
{
|
|
case '~':
|
|
fCRLF = FALSE;
|
|
pszFormat++;
|
|
continue;
|
|
|
|
case '`':
|
|
fDebugLog = FALSE;
|
|
pszFormat++;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
va_start(va, pszFormat);
|
|
#ifdef WIN32
|
|
n = wvsprintf(ach, pszFormat, va);
|
|
#else
|
|
n = wvsprintf(ach, pszFormat, (LPSTR)va);
|
|
#endif
|
|
va_end(va);
|
|
|
|
Edit_SetSel(hedit, (WPARAM)-1, (LPARAM)-1);
|
|
Edit_ReplaceSel(hedit, ach);
|
|
|
|
if (fDebugLog)
|
|
{
|
|
AcmAppDebugLog(ach);
|
|
}
|
|
|
|
if (fCRLF)
|
|
{
|
|
Edit_SetSel(hedit, (WPARAM)-1, (LPARAM)-1);
|
|
Edit_ReplaceSel(hedit, szCRLF);
|
|
|
|
if (fDebugLog)
|
|
{
|
|
AcmAppDebugLog(szCRLF);
|
|
}
|
|
}
|
|
|
|
return (n);
|
|
} // MEditPrintF()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppGetFileTitle
|
|
//
|
|
// Description:
|
|
// This function extracts the file title from a file path and returns
|
|
// it in the caller's specified buffer.
|
|
//
|
|
// Arguments:
|
|
// PTSTR pszFilePath: Pointer to null terminated file path.
|
|
//
|
|
// PTSTR pszFileTitle: Pointer to buffer to receive the file title.
|
|
//
|
|
// Return (BOOL):
|
|
// Always returns TRUE. But should return FALSE if this function
|
|
// checked for bogus values, etc.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppGetFileTitle
|
|
(
|
|
PTSTR pszFilePath,
|
|
PTSTR pszFileTitle
|
|
)
|
|
{
|
|
#define IS_SLASH(c) ('/' == (c) || '\\' == (c))
|
|
|
|
PTSTR pch;
|
|
|
|
//
|
|
// scan to the end of the file path string..
|
|
//
|
|
for (pch = pszFilePath; '\0' != *pch; pch++)
|
|
;
|
|
|
|
//
|
|
// now scan back toward the beginning of the string until a slash (\),
|
|
// colon, or start of the string is encountered.
|
|
//
|
|
while ((pch >= pszFilePath) && !IS_SLASH(*pch) && (':' != *pch))
|
|
{
|
|
pch--;
|
|
}
|
|
|
|
//
|
|
// finally, copy the 'title' into the destination buffer.. skip ahead
|
|
// one char since the above loop steps back one too many chars...
|
|
//
|
|
lstrcpy(pszFileTitle, ++pch);
|
|
|
|
return (TRUE);
|
|
} // AppGetFileTitle()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppGetFileName
|
|
//
|
|
// Description:
|
|
// This function is a wrapper for the Get[Open/Save]FileName commdlg
|
|
// chooser dialogs. Based on the fuFlags argument, this function will
|
|
// display the appropriate chooser dialog and return the result.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to parent window for chooser dialog.
|
|
//
|
|
// PTSTR pszFilePath: Pointer to buffer to receive the file path.
|
|
//
|
|
// PTSTR pszFileTitle: Pointer to buffer to receive the file title.
|
|
// This argument may be NULL, in which case no title will be returned.
|
|
//
|
|
// UINT fuFlags:
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is TRUE if a file was chosen. It is FALSE if the
|
|
// user canceled the operation.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppGetFileName
|
|
(
|
|
HWND hwnd,
|
|
PTSTR pszFilePath,
|
|
PTSTR pszFileTitle,
|
|
UINT fuFlags
|
|
)
|
|
{
|
|
#define APP_OFN_FLAGS_SAVE (OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT)
|
|
#define APP_OFN_FLAGS_OPEN (OFN_HIDEREADONLY | OFN_FILEMUSTEXIST)
|
|
|
|
TCHAR szExtDefault[APP_MAX_EXT_DEFAULT_CHARS];
|
|
TCHAR szExtFilter[APP_MAX_EXT_FILTER_CHARS];
|
|
OPENFILENAME ofn;
|
|
BOOL f;
|
|
PTCHAR pch;
|
|
|
|
|
|
//
|
|
// get the extension filter and default extension for this application
|
|
//
|
|
LoadString(ghinst, IDS_OFN_EXT_DEF, szExtDefault, SIZEOF(szExtDefault));
|
|
LoadString(ghinst, IDS_OFN_EXT_FILTER, szExtFilter, SIZEOF(szExtFilter));
|
|
|
|
|
|
//
|
|
// NOTE! building the filter string for the OPENFILENAME structure
|
|
// is a bit more difficult when dealing with Unicode and C8's new
|
|
// optimizer. it joyfully removes literal '\0' characters from
|
|
// strings that are concatted together. if you try making each
|
|
// string separate (array of pointers to strings), the compiler
|
|
// will dword align them... etc, etc.
|
|
//
|
|
// if you can think of a better way to build the filter string
|
|
// for common dialogs and still work in Win 16 and Win 32 [Unicode]
|
|
// i'd sure like to hear about it...
|
|
//
|
|
for (pch = &szExtFilter[0]; '\0' != *pch; pch++)
|
|
{
|
|
if ('!' == *pch)
|
|
*pch = '\0';
|
|
}
|
|
|
|
//
|
|
// initialize the OPENFILENAME members
|
|
//
|
|
memset(&ofn, 0, sizeof(OPENFILENAME));
|
|
|
|
pszFilePath[0] = '\0';
|
|
if (pszFileTitle)
|
|
pszFileTitle[0] = '\0';
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.lpstrFilter = szExtFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0L;
|
|
ofn.nFilterIndex = 1L;
|
|
ofn.lpstrFile = pszFilePath;
|
|
ofn.nMaxFile = APP_MAX_FILE_PATH_CHARS;
|
|
ofn.lpstrFileTitle = pszFileTitle;
|
|
ofn.nMaxFileTitle = pszFileTitle ? APP_MAX_FILE_TITLE_CHARS : 0;
|
|
if (fuFlags & APP_GETFILENAMEF_SAVE)
|
|
{
|
|
ofn.lpstrInitialDir = gszInitialDirSave;
|
|
}
|
|
else
|
|
{
|
|
ofn.lpstrInitialDir = gszInitialDirOpen;
|
|
}
|
|
ofn.nFileOffset = 0;
|
|
ofn.nFileExtension = 0;
|
|
ofn.lpstrDefExt = szExtDefault;
|
|
|
|
//
|
|
// if the fuFlags.APP_GETFILENAMEF_SAVE bit is set, then call
|
|
// GetSaveFileName() otherwise call GetOpenFileName(). why commdlg was
|
|
// designed with two separate functions for save and open only clark
|
|
// knows.
|
|
//
|
|
if (fuFlags & APP_GETFILENAMEF_SAVE)
|
|
{
|
|
ofn.Flags = APP_OFN_FLAGS_SAVE;
|
|
f = GetSaveFileName(&ofn);
|
|
if (f)
|
|
{
|
|
if (NULL != pszFilePath)
|
|
{
|
|
lstrcpy(gszInitialDirSave, pszFilePath);
|
|
|
|
pch = &gszInitialDirSave[lstrlen(gszInitialDirSave) - 1];
|
|
for ( ; gszInitialDirSave != pch; pch--)
|
|
{
|
|
if ('\\' == *pch)
|
|
{
|
|
*pch = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ofn.Flags = APP_OFN_FLAGS_OPEN;
|
|
f = GetOpenFileName(&ofn);
|
|
if (f)
|
|
{
|
|
if (NULL != pszFilePath)
|
|
{
|
|
lstrcpy(gszInitialDirOpen, pszFilePath);
|
|
|
|
pch = &gszInitialDirOpen[lstrlen(gszInitialDirOpen) - 1];
|
|
for ( ; gszInitialDirOpen != pch; pch--)
|
|
{
|
|
if ('\\' == *pch)
|
|
{
|
|
*pch = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (f);
|
|
} // AppGetFileName()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppTitle
|
|
//
|
|
// Description:
|
|
// This function formats and sets the title text of the application's
|
|
// window.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to application window to set title text for.
|
|
//
|
|
// PTSTR pszFileTitle: Pointer to file title to display.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is always TRUE.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppTitle
|
|
(
|
|
HWND hwnd,
|
|
PTSTR pszFileTitle
|
|
)
|
|
{
|
|
static TCHAR szFormatTitle[] = TEXT("%s - %s");
|
|
|
|
TCHAR ach[APP_MAX_FILE_PATH_CHARS];
|
|
|
|
//
|
|
// format the title text as 'AppName - FileTitle'
|
|
//
|
|
wsprintf(ach, szFormatTitle, (LPSTR)gszAppName, (LPSTR)pszFileTitle);
|
|
SetWindowText(hwnd, ach);
|
|
|
|
return (TRUE);
|
|
} // AppTitle()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppFileNew
|
|
//
|
|
// Description:
|
|
// This function is called to handle the IDM_FILE_NEW message. It is
|
|
// responsible for clearing the working area for a new unnamed file.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to application window.
|
|
//
|
|
// PACMAPPFILEDESC paafd: Pointer to current file descriptor.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is TRUE if the working area was cleared and is
|
|
// ready for new stuff. The return value is FALSE if the user canceled
|
|
// the operation.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppFileNew
|
|
(
|
|
HWND hwnd,
|
|
PACMAPPFILEDESC paafd,
|
|
BOOL fCreate
|
|
)
|
|
{
|
|
BOOL f;
|
|
|
|
if (fCreate)
|
|
{
|
|
f = AcmAppFileNew(hwnd, paafd);
|
|
if (!f)
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if there is currently a file path, then we have to do some real
|
|
// work...
|
|
//
|
|
if ('\0' != paafd->szFilePath[0])
|
|
{
|
|
f = AcmAppFileNew(hwnd, paafd);
|
|
if (!f)
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// blow away the old file path and title; set the window title
|
|
// and return success
|
|
//
|
|
lstrcpy(paafd->szFilePath, gszFileUntitled);
|
|
lstrcpy(paafd->szFileTitle, gszFileUntitled);
|
|
}
|
|
|
|
AppTitle(hwnd, paafd->szFileTitle);
|
|
|
|
AcmAppDisplayFileProperties(hwnd, paafd);
|
|
|
|
return (TRUE);
|
|
} // AppFileNew()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppFileOpen
|
|
//
|
|
// Description:
|
|
// This function handles the IDM_FILE_OPEN message. It is responsible
|
|
// for getting a new file name from the user and opening that file
|
|
// if possible.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to application window.
|
|
//
|
|
// PACMAPPFILEDESC paafd: Pointer to current file descriptor.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is TRUE if a new file was selected and opened.
|
|
// It is FALSE if the user canceled the operation.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNLOCAL AppFileOpen
|
|
(
|
|
HWND hwnd,
|
|
PACMAPPFILEDESC paafd
|
|
)
|
|
{
|
|
TCHAR szFilePath[APP_MAX_FILE_PATH_CHARS];
|
|
TCHAR szFileTitle[APP_MAX_FILE_TITLE_CHARS];
|
|
BOOL f;
|
|
|
|
//
|
|
// first test for a modified file that has not been saved. if the
|
|
// return value is FALSE we should cancel the File.Open operation.
|
|
//
|
|
f = AcmAppFileSaveModified(hwnd, paafd);
|
|
if (!f)
|
|
return (FALSE);
|
|
|
|
|
|
//
|
|
// get the file name of the new file into temporary buffers (so
|
|
// if we fail to open it we can back out cleanly).
|
|
//
|
|
f = AppGetFileName(hwnd, szFilePath, szFileTitle, APP_GETFILENAMEF_OPEN);
|
|
if (!f)
|
|
return (FALSE);
|
|
|
|
|
|
//!!!
|
|
// read the new file...
|
|
//
|
|
lstrcpy(paafd->szFilePath, szFilePath);
|
|
lstrcpy(paafd->szFileTitle, szFileTitle);
|
|
|
|
f = AcmAppFileOpen(hwnd, paafd);
|
|
if (f)
|
|
{
|
|
//
|
|
// set the window title text...
|
|
//
|
|
AppTitle(hwnd, szFileTitle);
|
|
AcmAppDisplayFileProperties(hwnd, paafd);
|
|
}
|
|
|
|
return (f);
|
|
} // AppFileOpen()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AppFileSave
|
|
//
|
|
// Description:
|
|
// This function handles the IDM_FILE_SAVE[AS] messages. It is
|
|
// responsible for saving the current file. If a file name needs
|
|
// to be specified then the save file dialog is displayed.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to application window.
|
|
//
|
|
// PACMAPPFILEDESC paafd: Pointer to current file descriptor.
|
|
//
|
|
// BOOL fSaveAs: TRUE if the save file chooser should be displayed
|
|
// before saving the file. FALSE if should operate like File.Save.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is TRUE if the file was saved. It is FALSE if the
|
|
// user canceled the operation or the file does not need saved.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNGLOBAL AppFileSave
|
|
(
|
|
HWND hwnd,
|
|
PACMAPPFILEDESC paafd,
|
|
BOOL fSaveAs
|
|
)
|
|
{
|
|
TCHAR szFilePath[APP_MAX_FILE_PATH_CHARS];
|
|
TCHAR szFileTitle[APP_MAX_FILE_TITLE_CHARS];
|
|
BOOL f;
|
|
|
|
//
|
|
//
|
|
//
|
|
lstrcpy(szFilePath, paafd->szFilePath);
|
|
lstrcpy(szFileTitle, paafd->szFileTitle);
|
|
|
|
|
|
//
|
|
// check if we should bring up the save file chooser dialog...
|
|
//
|
|
if (fSaveAs || (0 == lstrcmp(paafd->szFileTitle, gszFileUntitled)))
|
|
{
|
|
//
|
|
// get the file name for saving the data to into temporary
|
|
// buffers (so if we fail to save it we can back out cleanly).
|
|
//
|
|
f = AppGetFileName(hwnd, szFilePath, szFileTitle, APP_GETFILENAMEF_SAVE);
|
|
if (!f)
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// save the file...
|
|
//
|
|
f = AcmAppFileSave(hwnd, paafd, szFilePath, szFileTitle, 0);
|
|
if (f)
|
|
{
|
|
//
|
|
// changes have been saved, so clear the modified bit...
|
|
//
|
|
paafd->fdwState &= ~ACMAPPFILEDESC_STATEF_MODIFIED;
|
|
|
|
AppTitle(hwnd, paafd->szFileTitle);
|
|
|
|
AcmAppDisplayFileProperties(hwnd, paafd);
|
|
}
|
|
|
|
return (f);
|
|
} // AppFileSave()
|
|
|
|
|
|
//==========================================================================;
|
|
//
|
|
// Main application window handling code...
|
|
//
|
|
//
|
|
//==========================================================================;
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AppInitMenuPopup
|
|
//
|
|
// Description:
|
|
// This function handles the WM_INITMENUPOPUP message. This message
|
|
// is sent to the window owning the menu that is going to become
|
|
// active. This gives an application the ability to modify the menu
|
|
// before it is displayed (disable/add items, etc).
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
|
|
// message.
|
|
//
|
|
// HMENU hmenu: Handle to the menu that is to become active.
|
|
//
|
|
// int nItem: Specifies the zero-based relative position of the menu
|
|
// item that invoked the popup menu.
|
|
//
|
|
// BOOL fSysMenu: Specifies whether the popup menu is a System menu
|
|
// (TRUE) or it is not a System menu (FALSE).
|
|
//
|
|
// Return (LRESULT):
|
|
// Returns zero if the message is processed.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNLOCAL AppInitMenuPopup
|
|
(
|
|
HWND hwnd,
|
|
HMENU hmenu,
|
|
int nItem,
|
|
BOOL fSysMenu
|
|
)
|
|
{
|
|
BOOL f;
|
|
int nSelStart;
|
|
int nSelEnd;
|
|
HWND hedit;
|
|
|
|
DPF(4, "AppInitMenuPopup(hwnd=%Xh, hmenu=%Xh, nItem=%d, fSysMenu=%d)",
|
|
hwnd, hmenu, nItem, fSysMenu);
|
|
|
|
//
|
|
// if the system menu is what got hit, succeed immediately... this
|
|
// application has no stuff in the system menu.
|
|
//
|
|
if (fSysMenu)
|
|
return (0L);
|
|
|
|
//
|
|
// initialize the menu that is being 'popped up'
|
|
//
|
|
switch (nItem)
|
|
{
|
|
case APP_MENU_ITEM_FILE:
|
|
EnableMenuItem(hmenu, IDM_FILE_NEW,
|
|
(UINT)(gfAcmAvailable ? MF_ENABLED : MF_GRAYED));
|
|
|
|
f = (NULL != gaafd.pwfx);
|
|
EnableMenuItem(hmenu, IDM_FILE_SNDPLAYSOUND_PLAY,
|
|
(UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
EnableMenuItem(hmenu, IDM_FILE_SNDPLAYSOUND_STOP,
|
|
(UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
|
|
f = (NULL != gaafd.pwfx) && gfAcmAvailable;
|
|
EnableMenuItem(hmenu, IDM_FILE_CONVERT,
|
|
(UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
|
|
|
|
//
|
|
// if the file has been modified, then enable the File.Save
|
|
// menu
|
|
//
|
|
f = (0 != (gaafd.fdwState & ACMAPPFILEDESC_STATEF_MODIFIED));
|
|
EnableMenuItem(hmenu, IDM_FILE_SAVE,
|
|
(UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
|
|
// f = (NULL != gaafd.pwfx);
|
|
EnableMenuItem(hmenu, IDM_FILE_SAVEAS,
|
|
(UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
break;
|
|
|
|
case APP_MENU_ITEM_EDIT:
|
|
//
|
|
// check to see if something is selected in the display
|
|
// window and enable/disable Edit menu options appropriately
|
|
//
|
|
hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
|
|
Edit_GetSelEx(hedit, &nSelStart, &nSelEnd);
|
|
|
|
f = (nSelStart != nSelEnd);
|
|
EnableMenuItem(hmenu, WM_COPY, (UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
break;
|
|
|
|
case APP_MENU_ITEM_VIEW:
|
|
EnableMenuItem(hmenu, IDM_VIEW_ACM_DRIVERS,
|
|
(UINT)(gfAcmAvailable ? MF_ENABLED : MF_GRAYED));
|
|
break;
|
|
|
|
|
|
case APP_MENU_ITEM_OPTIONS:
|
|
f = (0 != waveInGetNumDevs());
|
|
EnableMenuItem(hmenu, IDM_OPTIONS_WAVEINDEVICE, (UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
|
|
f = (0 != waveOutGetNumDevs());
|
|
EnableMenuItem(hmenu, IDM_OPTIONS_WAVEOUTDEVICE, (UINT)(f ? MF_ENABLED : MF_GRAYED));
|
|
|
|
//
|
|
// make sure the options that need a checkmark are checked..
|
|
//
|
|
f = (0 != (APP_OPTIONSF_AUTOOPEN & gfuAppOptions));
|
|
CheckMenuItem(hmenu, IDM_OPTIONS_AUTOOPEN,
|
|
(UINT)(f ? MF_CHECKED : MF_UNCHECKED));
|
|
|
|
f = (0 != (APP_OPTIONSF_DEBUGLOG & gfuAppOptions));
|
|
CheckMenuItem(hmenu, IDM_OPTIONS_DEBUGLOG,
|
|
(UINT)(f ? MF_CHECKED : MF_UNCHECKED));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// we processed the message--return 0...
|
|
//
|
|
return (0L);
|
|
} // AppInitMenuPopup()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AppCommand
|
|
//
|
|
// Description:
|
|
// This function handles the WM_COMMAND message.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window receiving the WM_COMMAND message.
|
|
//
|
|
// int nId: Control or menu item identifier.
|
|
//
|
|
// HWND hwndCtl: Handle of control if the message is from a control.
|
|
// This argument is NULL if the message was not generated by a control.
|
|
//
|
|
// UINT uCode: Notification code. This argument is 1 if the message
|
|
// was generated by an accelerator. If the message is from a menu,
|
|
// this argument is 0.
|
|
//
|
|
// Return (LRESULT):
|
|
// Returns zero if the message is processed.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNLOCAL AppCommand
|
|
(
|
|
HWND hwnd,
|
|
int nId,
|
|
HWND hwndCtl,
|
|
UINT uCode
|
|
)
|
|
{
|
|
BOOL f;
|
|
DWORD dw;
|
|
UINT uDevId;
|
|
|
|
switch (nId)
|
|
{
|
|
case IDM_FILE_NEW:
|
|
AppFileNew(hwnd, &gaafd, TRUE);
|
|
break;
|
|
|
|
case IDM_FILE_OPEN:
|
|
AppFileOpen(hwnd, &gaafd);
|
|
break;
|
|
|
|
case IDM_FILE_SAVE:
|
|
AppFileSave(hwnd, &gaafd, FALSE);
|
|
break;
|
|
|
|
case IDM_FILE_SAVEAS:
|
|
AppFileSave(hwnd, &gaafd, TRUE);
|
|
break;
|
|
|
|
|
|
case IDM_FILE_SNDPLAYSOUND_PLAY:
|
|
if (NULL == gaafd.pwfx)
|
|
{
|
|
MessageBeep((UINT)-1);
|
|
break;
|
|
}
|
|
|
|
AppHourGlass(TRUE);
|
|
dw = timeGetTime();
|
|
f = sndPlaySound(gaafd.szFilePath, SND_ASYNC | SND_NODEFAULT);
|
|
dw = timeGetTime() - dw;
|
|
AppHourGlass(FALSE);
|
|
|
|
if (0 != (APP_OPTIONSF_DEBUGLOG & gfuAppOptions))
|
|
{
|
|
AcmAppDebugLog(NULL);
|
|
AcmAppDebugLog(TEXT("sndPlaySound(%s) took %lu milliseconds to %s.\r\n"),
|
|
(LPTSTR)gaafd.szFilePath,
|
|
dw,
|
|
f ? (LPTSTR)TEXT("succeed") : (LPTSTR)TEXT("fail"));
|
|
}
|
|
|
|
if (!f)
|
|
{
|
|
AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
|
|
TEXT("The file '%s' cannot be played by sndPlaySound."),
|
|
(LPSTR)gaafd.szFilePath);
|
|
}
|
|
break;
|
|
|
|
case IDM_FILE_SNDPLAYSOUND_STOP:
|
|
sndPlaySound(NULL, 0L);
|
|
break;
|
|
|
|
case IDM_FILE_CONVERT:
|
|
AcmAppFileConvert(hwnd, &gaafd);
|
|
break;
|
|
|
|
|
|
case IDM_FILE_ABOUT:
|
|
DialogBox(ghinst, DLG_ABOUT, hwnd, AboutDlgProc);
|
|
break;
|
|
|
|
case IDM_FILE_EXIT:
|
|
FORWARD_WM_CLOSE(hwnd, SendMessage);
|
|
break;
|
|
|
|
|
|
case WM_COPY:
|
|
//
|
|
// pass on edit messages received to the display window
|
|
//
|
|
SendMessage(GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY), nId, 0, 0L);
|
|
break;
|
|
|
|
case IDM_EDIT_SELECTALL:
|
|
Edit_SetSel(GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY), 0, -1);
|
|
break;
|
|
|
|
|
|
case IDM_UPDATE:
|
|
AcmAppFileOpen(hwnd, &gaafd);
|
|
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
break;
|
|
|
|
case IDM_VIEW_SYSTEMINFO:
|
|
DialogBox(ghinst, DLG_AADETAILS, hwnd, AcmAppSystemInfoDlgProc);
|
|
break;
|
|
|
|
case IDM_VIEW_ACM_DRIVERS:
|
|
DialogBox(ghinst, DLG_AADRIVERS, hwnd, AcmAppDriversDlgProc);
|
|
break;
|
|
|
|
|
|
case IDM_OPTIONS_WAVEINDEVICE:
|
|
uDevId = DialogBoxParam(ghinst, DLG_AAWAVEDEVICE, hwnd,
|
|
AcmAppWaveDeviceDlgProc,
|
|
MAKELONG((WORD)guWaveInId, TRUE));
|
|
|
|
if (uDevId != guWaveInId)
|
|
{
|
|
guWaveInId = uDevId;
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
}
|
|
break;
|
|
|
|
case IDM_OPTIONS_WAVEOUTDEVICE:
|
|
uDevId = DialogBoxParam(ghinst, DLG_AAWAVEDEVICE, hwnd,
|
|
AcmAppWaveDeviceDlgProc,
|
|
MAKELONG((WORD)guWaveOutId, FALSE));
|
|
|
|
if (uDevId != guWaveOutId)
|
|
{
|
|
guWaveOutId = uDevId;
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_OPTIONS_AUTOOPEN:
|
|
gfuAppOptions ^= APP_OPTIONSF_AUTOOPEN;
|
|
break;
|
|
|
|
case IDM_OPTIONS_DEBUGLOG:
|
|
gfuAppOptions ^= APP_OPTIONSF_DEBUGLOG;
|
|
break;
|
|
|
|
case IDM_OPTIONS_FONT:
|
|
AcmAppChooseFont(hwnd);
|
|
break;
|
|
|
|
|
|
case IDM_PLAYRECORD:
|
|
if (NULL == gaafd.pwfx)
|
|
{
|
|
f = AppFileNew(hwnd, &gaafd, TRUE);
|
|
if (!f)
|
|
break;
|
|
|
|
if (NULL == gaafd.pwfx)
|
|
break;
|
|
}
|
|
|
|
f = DialogBoxParam(ghinst, DLG_AAPLAYRECORD, hwnd,
|
|
AcmAppPlayRecord, (LPARAM)(LPVOID)&gaafd);
|
|
if (f)
|
|
{
|
|
AcmAppFileOpen(hwnd, &gaafd);
|
|
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return (0L);
|
|
} // AppCommand()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// BOOL AcmAppDlgProcDragDropContinue
|
|
//
|
|
// Description:
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window.
|
|
//
|
|
// UINT uMsg: Message being sent to the window.
|
|
//
|
|
// WPARAM wParam: Specific argument to message.
|
|
//
|
|
// LPARAM lParam: Specific argument to message.
|
|
//
|
|
// Return (BOOL):
|
|
// The return value is specific to the message that was received. For
|
|
// the most part, it is FALSE if this dialog procedure does not handle
|
|
// a message.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
BOOL FNEXPORT AcmAppDlgProcDragDropContinue
|
|
(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
UINT uId;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
AppSetWindowText(hwnd, TEXT("File %u of %u"), LOWORD(lParam), HIWORD(lParam));
|
|
return (TRUE);
|
|
|
|
case WM_COMMAND:
|
|
uId = GET_WM_COMMAND_ID(wParam, lParam);
|
|
if ((IDOK == uId) || (IDCANCEL == uId))
|
|
{
|
|
EndDialog(hwnd, uId);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return (FALSE);
|
|
} // AcmAppDlgProcDragDropContinue()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AppDropFiles
|
|
//
|
|
// Description:
|
|
// This function handles the WM_DROPFILES message. This message is
|
|
// sent when files are 'dropped' on the window from file manager
|
|
// (or other drag/drop servers made by ISV's that figured out the
|
|
// undocumented internal workings of the SHELL).
|
|
//
|
|
// A window must be registered to receive these messages either by
|
|
// called DragAcceptFiles() or using CreateWindowEx() with the
|
|
// WS_EX_ACCEPTFILES style bit.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window receiving the message.
|
|
//
|
|
// HDROP hdrop: Handle to drop structure.
|
|
//
|
|
// Return (LRESULT):
|
|
// Returns 0 if the message is processed.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNLOCAL AppDropFiles
|
|
(
|
|
HWND hwnd,
|
|
HDROP hdrop
|
|
)
|
|
{
|
|
TCHAR szFilePath[APP_MAX_FILE_PATH_CHARS];
|
|
UINT cFiles;
|
|
UINT u;
|
|
BOOL f;
|
|
int n;
|
|
|
|
//
|
|
// first test for a file that has not been saved. if the return
|
|
// value is FALSE we should cancel the drop operation.
|
|
//
|
|
f = AcmAppFileSaveModified(hwnd, &gaafd);
|
|
if (!f)
|
|
{
|
|
goto App_Drop_Files_Exit;
|
|
}
|
|
|
|
//
|
|
// get number of files dropped on our window
|
|
//
|
|
cFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
|
|
|
|
DPF(4, "AppDropFiles(hwnd=%Xh, hdrop=%Xh)--cFiles=%u", hwnd, hdrop, cFiles);
|
|
|
|
//
|
|
// step through each file and stop on the one the user wants or
|
|
// the last file (whichever comes first).
|
|
//
|
|
for (u = 0; u < cFiles; u++)
|
|
{
|
|
//
|
|
// get the next file name and try to open it--if not a valid
|
|
// file, then skip to the next one (if there is one).
|
|
//
|
|
DragQueryFile(hdrop, u, szFilePath, SIZEOF(szFilePath));
|
|
|
|
|
|
//
|
|
// !!! destructive !!!
|
|
//
|
|
// attempt to open the file
|
|
//
|
|
lstrcpy(gaafd.szFilePath, szFilePath);
|
|
lstrcpy(gaafd.szFileTitle, gszNull);
|
|
|
|
f = AcmAppFileOpen(hwnd, &gaafd);
|
|
if (!f)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
AppTitle(hwnd, gaafd.szFileTitle);
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
|
|
//
|
|
// if this is NOT the last file in the list of files that are
|
|
// being dropped on us, then bring up a box asking if we should
|
|
// continue or stop where we are..
|
|
//
|
|
if ((cFiles - 1) != u)
|
|
{
|
|
n = DialogBoxParam(ghinst,
|
|
DLG_AADRAGDROP,
|
|
hwnd,
|
|
AcmAppDlgProcDragDropContinue,
|
|
MAKELPARAM((WORD)(u + 1), (WORD)cFiles));
|
|
if (IDCANCEL == n)
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// tell the shell to release the memory it allocated for beaming
|
|
// the file name(s) over to us... return 0 to show we processed
|
|
// the message.
|
|
//
|
|
App_Drop_Files_Exit:
|
|
|
|
DragFinish(hdrop);
|
|
return (0L);
|
|
} // AppDropFiles()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AppSize
|
|
//
|
|
// Description:
|
|
// This function handles the WM_SIZE message for the application's
|
|
// window. This message is sent to the application window after the
|
|
// size has changed (but before it is painted).
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window that generated the WM_SIZE message.
|
|
//
|
|
// UINT fuSizeType: Specifies the type of resizing requested. This
|
|
// argument is one of the following: SIZE_MAXIMIZED, SIZE_MINIMIZED,
|
|
// SIZE_RESTORED, SIZE_MAXHIDE, or SIZE_MAXSHOW.
|
|
//
|
|
// int nWidth: Width of the new client area for the window.
|
|
//
|
|
// int nHeight: Height of the new client area for the window.
|
|
//
|
|
// Return (LRESULT):
|
|
// Returns zero if the application processes the message.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNLOCAL AppSize
|
|
(
|
|
HWND hwnd,
|
|
UINT fuSizeType,
|
|
int nWidth,
|
|
int nHeight
|
|
)
|
|
{
|
|
HWND hedit;
|
|
RECT rc;
|
|
|
|
DPF(4, "AppSize(hwnd=%Xh, fuSizeType=%u, nWidth=%d, nHeight=%d)",
|
|
hwnd, fuSizeType, nWidth, nHeight);
|
|
|
|
//
|
|
// unless this application is the one being resized then don't waste
|
|
// time computing stuff that doesn't matter. this applies to being
|
|
// minimized also because this application does not have a custom
|
|
// minimized state.
|
|
//
|
|
if ((SIZE_RESTORED != fuSizeType) && (SIZE_MAXIMIZED != fuSizeType))
|
|
return (0L);
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
GetClientRect(hwnd, &rc);
|
|
InflateRect(&rc, 1, 1);
|
|
|
|
hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
|
|
SetWindowPos(hedit,
|
|
NULL,
|
|
rc.left,
|
|
rc.top,
|
|
rc.right - rc.left,
|
|
rc.bottom - rc.top,
|
|
SWP_NOZORDER);
|
|
|
|
|
|
//
|
|
// we processed the message..
|
|
//
|
|
return (0L);
|
|
} // AppSize()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AcmAppNotify
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return (LRESULT):
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNLOCAL AcmAppNotify
|
|
(
|
|
HWND hwnd,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
HWND hwndNext;
|
|
|
|
DPF(1, "AcmAppNotify: hwnd=%.04Xh, wParam=%.04Xh, lParam2=%.08lXh",
|
|
hwnd, wParam, lParam);
|
|
|
|
//
|
|
//
|
|
//
|
|
hwndNext = GetWindow(hwnd, GW_HWNDFIRST);
|
|
while (NULL != hwndNext)
|
|
{
|
|
if (GetParent(hwndNext) == hwnd)
|
|
{
|
|
SendMessage(hwndNext, WM_ACMAPP_ACM_NOTIFY, wParam, lParam);
|
|
}
|
|
|
|
hwndNext = GetWindow(hwndNext, GW_HWNDNEXT);
|
|
}
|
|
|
|
|
|
//
|
|
// now force an update to our display in case driver [dis/en]able
|
|
// changed what is playable/recordable.
|
|
//
|
|
AcmAppDisplayFileProperties(hwnd, &gaafd);
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
return (1L);
|
|
} // AcmAppNotify()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// LRESULT AppWndProc
|
|
//
|
|
// Description:
|
|
// This is the main application window procedure.
|
|
//
|
|
// Arguments:
|
|
// HWND hwnd: Handle to window.
|
|
//
|
|
// UINT uMsg: Message being sent to the window.
|
|
//
|
|
// WPARAM wParam: Specific argument to message.
|
|
//
|
|
// LPARAM lParam: Specific argument to message.
|
|
//
|
|
// Return (LRESULT):
|
|
// The return value depends on the message that is being processed.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
LRESULT FNEXPORT AppWndProc
|
|
(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
LRESULT lr;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
lr = HANDLE_WM_CREATE(hwnd, wParam, lParam, AppCreate);
|
|
return (lr);
|
|
|
|
case WM_WININICHANGE:
|
|
HANDLE_WM_WININICHANGE(hwnd, wParam, lParam, AppWinIniChange);
|
|
return (0L);
|
|
|
|
case WM_INITMENUPOPUP:
|
|
HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, AppInitMenuPopup);
|
|
return (0L);
|
|
|
|
case WM_COMMAND:
|
|
lr = HANDLE_WM_COMMAND(hwnd, wParam, lParam, AppCommand);
|
|
return (lr);
|
|
|
|
case WM_DROPFILES:
|
|
//
|
|
// some windowsx.h files have a messed up message cracker for
|
|
// WM_DROPFILES. because this is a sample app, i don't want
|
|
// people having trouble with bogus windowsx.h files, so crack
|
|
// the message manually... you should use the message cracker
|
|
// if you know your windowsx.h file is good.
|
|
//
|
|
// lr = HANDLE_WM_DROPFILES(hwnd, wParam, lParam, AppDropFiles);
|
|
//
|
|
lr = AppDropFiles(hwnd, (HDROP)wParam);
|
|
return (lr);
|
|
|
|
case WM_SIZE:
|
|
//
|
|
// handle what we want for sizing, and then always call the
|
|
// default handler...
|
|
//
|
|
HANDLE_WM_SIZE(hwnd, wParam, lParam, AppSize);
|
|
break;
|
|
|
|
case WM_QUERYENDSESSION:
|
|
lr = HANDLE_WM_QUERYENDSESSION(hwnd, wParam, lParam, AppQueryEndSession);
|
|
return (lr);
|
|
|
|
case WM_ENDSESSION:
|
|
HANDLE_WM_ENDSESSION(hwnd, wParam, lParam, AppEndSession);
|
|
return (0L);
|
|
|
|
case WM_CLOSE:
|
|
HANDLE_WM_CLOSE(hwnd, wParam, lParam, AppClose);
|
|
return (0L);
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
return (0L);
|
|
|
|
case WM_ACMAPP_ACM_NOTIFY:
|
|
AcmAppNotify(hwnd, wParam, lParam);
|
|
return (0L);
|
|
}
|
|
|
|
return (DefWindowProc(hwnd, uMsg, wParam, lParam));
|
|
} // AppWndProc()
|
|
|
|
|
|
//==========================================================================;
|
|
//
|
|
// Main entry and message dispatching code
|
|
//
|
|
//
|
|
//==========================================================================;
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// int WinMain
|
|
//
|
|
// Description:
|
|
// This function is called by the system as the initial entry point
|
|
// for a Windows application.
|
|
//
|
|
// Arguments:
|
|
// HINSTANCE hinst: Identifies the current instance of the
|
|
// application.
|
|
//
|
|
// HINSTANCE hinstPrev: Identifies the previous instance of the
|
|
// application (NULL if first instance). For Win 32, this argument
|
|
// is _always_ NULL.
|
|
//
|
|
// LPSTR pszCmdLine: Points to null-terminated unparsed command line.
|
|
// This string is strictly ANSI regardless of whether the application
|
|
// is built for Unicode. To get the Unicode equivalent call the
|
|
// GetCommandLine() function (Win 32 only).
|
|
//
|
|
// int nCmdShow: How the main window for the application is to be
|
|
// shown by default.
|
|
//
|
|
// Return (int):
|
|
// Returns result from WM_QUIT message (in wParam of MSG structure) if
|
|
// the application is able to enter its message loop. Returns 0 if
|
|
// the application is not able to enter its message loop.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
int PASCAL WinMain
|
|
(
|
|
HINSTANCE hinst,
|
|
HINSTANCE hinstPrev,
|
|
LPSTR pszCmdLine,
|
|
int nCmdShow
|
|
)
|
|
{
|
|
int nResult;
|
|
HWND hwnd;
|
|
MSG msg;
|
|
HACCEL haccl;
|
|
|
|
DbgInitialize(TRUE);
|
|
|
|
//
|
|
// our documentation states that WinMain is supposed to return 0 if
|
|
// we do not enter our message loop--so assume the worst...
|
|
//
|
|
nResult = 0;
|
|
|
|
//
|
|
// make our instance handle global for convenience..
|
|
//
|
|
ghinst = hinst;
|
|
|
|
//
|
|
// init some stuff, create window, etc.. note the explicit cast of
|
|
// pszCmdLine--this is to mute a warning (and an ugly ifdef) when
|
|
// compiling for Unicode. see AppInit() for more details.
|
|
//
|
|
hwnd = AppInit(hinst, hinstPrev, (LPTSTR)pszCmdLine, nCmdShow);
|
|
if (hwnd)
|
|
{
|
|
haccl = LoadAccelerators(hinst, ACCEL_APP);
|
|
|
|
//
|
|
// dispatch messages
|
|
//
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
//
|
|
// do all the special stuff required for this application
|
|
// when dispatching messages..
|
|
//
|
|
if (!TranslateAccelerator(hwnd, haccl, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
//
|
|
// return result of WM_QUIT message.
|
|
//
|
|
nResult = (int)msg.wParam;
|
|
}
|
|
|
|
//
|
|
// shut things down, clean up, etc.
|
|
//
|
|
nResult = AppExit(hinst, nResult);
|
|
|
|
return (nResult);
|
|
} // WinMain()
|