home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1992
/
20
/
cdplayer
/
cdplayer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-21
|
20KB
|
663 lines
/********************************************************************
CDPlayer 1.0 Copyright (c) 1992 Jeff Prosise
First published in PC Magazine, U.S. Edition, November 24, 1992
CDPlayer uses Windows 3.1's Media Control Interface (MCI) to
control track selections on audio CDs played in CD-ROM drives.
********************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <stdlib.h>
#include "cdplayer.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
BOOL FAR PASCAL AboutDlgProc (HWND, WORD, WORD, LONG);
void BeginPlay (BYTE, HWND);
void ResumePlay (DWORD, HWND);
void UpdateTrackButtons (HWND);
char *IntToMinSec (int, char *);
char *TMSFtoMinSec (DWORD, char *);
MCI_STATUS_PARMS MCIStatus; // MCI_STATUS structure
MCI_OPEN_PARMS MCIOpen; // MCI_OPEN structure
MCI_PLAY_PARMS MCIPlay; // MCI_PLAY structure
MCI_SET_PARMS MCISet; // MCI_SET structure
BOOL bMediaPresent = FALSE; // Media status flag
BOOL bScrolling = FALSE; // Scroll flag
BOOL bPaused = FALSE; // Pause flag
WORD wNumberOfTracks; // Number of tracks
WORD wCurrentTrack = 0; // Current track number
WORD awTrackLength[99]; // Track lengths in seconds
DWORD dwPosition; // Pause position
WORD wPageNumber = 0; // Page number
WORD wPageCount = 1; // Page count
WORD wTimerID; // Timer ID value
HWND hwndTrack, hwndLength; // Window handles
HWND hwndTime, hwndScrollBar;
/********************************************************************
WinMain starts the program.
********************************************************************/
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szOpenError[] = "Unable to open the CD Audio device";
static char szTimerError[] = "Unable to allocate a timer";
static char szAppName[] = "CDPlayer";
WNDCLASS wndclass;
HWND hwnd;
MSG msg;
// Register the window class
if (!hPrevInstance) {
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC) WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = DLGWINDOWEXTRA;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (hInstance, szAppName);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = COLOR_WINDOW + 1;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
RegisterClass (&wndclass);
}
// Create a window based on the registered class
hwnd = CreateDialog (hInstance, szAppName, 0 , NULL);
// Open the CD Audio device and set the time format to TMSF
MCISet.dwTimeFormat = MCI_FORMAT_TMSF;
MCIOpen.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
if (!mciSendCommand (NULL, MCI_OPEN, MCI_OPEN_TYPE |
MCI_OPEN_TYPE_ID, (DWORD) (LPSTR) &MCIOpen))
mciSendCommand (MCIOpen.wDeviceID, MCI_SET,
MCI_SET_TIME_FORMAT, (DWORD) (LPSTR) &MCISet);
else if (!mciSendCommand (NULL, MCI_OPEN, MCI_OPEN_TYPE |
MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, (DWORD) (LPSTR) &MCIOpen))
mciSendCommand (MCIOpen.wDeviceID, MCI_SET,
MCI_SET_TIME_FORMAT, (DWORD) (LPSTR) &MCISet);
else {
MessageBeep (MB_ICONEXCLAMATION);
MessageBox (hwnd, szOpenError, "Error", MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
// Get window handles and font handle
hwndTrack = GetDlgItem (hwnd, IDD_TRACK);
hwndLength = GetDlgItem (hwnd, IDD_LENGTH);
hwndTime = GetDlgItem (hwnd, IDD_TIME);
hwndScrollBar = GetDlgItem (hwnd, IDD_SCROLLBAR);
// Allocate a timer that calls WndProc once per second
if ((wTimerID = SetTimer (hwnd, 1, 1000, NULL)) == NULL) {
MessageBeep (MB_ICONEXCLAMATION);
MessageBox (hwnd, szTimerError, "Error", MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
// Display the window
ShowWindow (hwnd, nCmdShow);
UpdateWindow (hwnd);
// Enter the message loop
while (GetMessage (&msg, NULL, 0, 0))
if ((hwnd == 0) || (!IsDialogMessage (hwnd, &msg)))
DispatchMessage (&msg);
// Terminate the program
return msg.wParam;
}
/********************************************************************
WndProc processes messages to the main window.
********************************************************************/
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static char szSection[] = "Options";
static char szEntry[] = "MinimizeTimeSlice";
static char szIniFile[] = "CDPLAYER.INI";
char szBuffer[8];
static HBRUSH hBrush;
static HMENU hSysMenu;
static HANDLE hInstance;
static FARPROC lpfnAboutDlgProc;
static int iThumbPos;
POINT point;
RECT rect;
WORD i;
switch (message) {
case WM_CREATE:
// Create a background brush for WM_CTLCOLOR messages
hBrush = CreateSolidBrush (GetSysColor (COLOR_WINDOW));
// Obtain a far pointer to the About dialog box function
hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance);
// Center the window on the screen
GetWindowRect (hwnd, &rect);
SetWindowPos (hwnd, 0,
(GetSystemMetrics (SM_CXSCREEN) - (rect.right - rect.left)) / 2,
(GetSystemMetrics (SM_CYSCREEN) - (rect.bottom - rect.top)) / 2,
0, 0, SWP_NOSIZE | SWP_NOZORDER);
// Add new options to the system menu
hSysMenu = GetSystemMenu (hwnd, FALSE);
AppendMenu (hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu (hSysMenu, MF_STRING, IDM_TOGGLEMTS,
"Minimize &Time Slice");
AppendMenu (hSysMenu, MF_STRING, IDM_ABOUT,
"&About CDPlayer...");
// Read option information from the INI file
if (GetPrivateProfileInt (szSection, szEntry, 0, szIniFile) == 1)
CheckMenuItem (hSysMenu, IDM_TOGGLEMTS, MF_CHECKED);
return 0;
case WM_COMMAND:
// Begin play if a track button was pressed
if ((wParam >= 101) && (wParam <= 120)) {
BeginPlay ((BYTE) (wParam + (wPageNumber * 20) - 100), hwnd);
return 0;
}
switch (wParam) {
case IDD_PLAY:
// Begin play at track 1
if (bMediaPresent)
BeginPlay (1, hwnd);
return 0;
case IDD_STOP:
// Stop play
if (bMediaPresent) {
bPaused = FALSE;
wCurrentTrack = 0;
mciSendCommand (MCIOpen.wDeviceID, MCI_STOP, NULL, NULL);
}
return 0;
case IDD_PAUSE:
if (!bMediaPresent)
return 0;
// Resume play
if (bPaused)
ResumePlay (dwPosition, hwnd);
// Pause play
else {
MCIStatus.dwItem = MCI_STATUS_MODE;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
if (MCIStatus.dwReturn == MCI_MODE_PLAY) {
bPaused = TRUE;
MCIStatus.dwItem = MCI_STATUS_POSITION;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM | MCI_WAIT,
(DWORD) (LPSTR) &MCIStatus);
dwPosition = MCIStatus.dwReturn;
mciSendCommand (MCIOpen.wDeviceID, MCI_STOP, NULL, NULL);
}
}
return 0;
case IDD_EJECT:
// Eject the disk
if (bMediaPresent)
mciSendCommand (MCIOpen.wDeviceID, MCI_SET,
MCI_SET_DOOR_OPEN, NULL);
return 0;
case IDD_PREVTRACK:
// Go to the previous track
if (bMediaPresent)
BeginPlay ((BYTE) ((wCurrentTrack <= 1) ?
wNumberOfTracks : wCurrentTrack - 1), hwnd);
return 0;
case IDD_NEXTTRACK:
// Go to the next track
if (bMediaPresent)
BeginPlay ((BYTE) ((wCurrentTrack == wNumberOfTracks) ?
1 : wCurrentTrack + 1), hwnd);
return 0;
case IDD_20PLUS:
if (wNumberOfTracks > 20) {
wPageNumber++;
if (wPageNumber == wPageCount)
wPageNumber = 0;
UpdateTrackButtons (hwnd);
}
return 0;
case IDCANCEL:
// Terminate the program
DestroyWindow (hwnd);
return 0;
}
case WM_TIMER:
// Ignore this message if the window is minimized and
// Minimize Time Slice is checked in the system menu
if ((IsIconic (hwnd)) && (GetMenuState (hSysMenu,
IDM_TOGGLEMTS, MF_BYCOMMAND) & MF_CHECKED))
return 0;
// Find out if there is a CD in the drive
MCIStatus.dwItem = MCI_STATUS_MEDIA_PRESENT;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM |
MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
// Initialize the program if a CD was inserted
if ((!bMediaPresent) && (MCIStatus.dwReturn == TRUE)) {
bMediaPresent = TRUE;
bScrolling = FALSE;
bPaused = FALSE;
wCurrentTrack = 0;
wPageNumber = 0;
// Get the number of tracks
MCIStatus.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM |
MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
wNumberOfTracks = (WORD) MCIStatus.dwReturn;
if (wNumberOfTracks > 99)
wNumberOfTracks = 99;
wPageCount = ((wNumberOfTracks - 1) / 20) + 1;
// Enable the track button display
if (wNumberOfTracks <= 20)
for (i=1; i<=wNumberOfTracks; i++)
EnableWindow (GetDlgItem (hwnd, i+100), TRUE);
else {
for (i=1; i<=20; i++)
EnableWindow (GetDlgItem (hwnd, i+100), TRUE);
EnableWindow (GetDlgItem (hwnd, IDD_20PLUS), TRUE);
}
// Get the length of each track
for (i=1; i<=wNumberOfTracks; i++) {
MCIStatus.dwItem = MCI_STATUS_LENGTH;
MCIStatus.dwTrack = (DWORD) i;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_TRACK | MCI_STATUS_ITEM | MCI_WAIT,
(DWORD) (LPSTR) &MCIStatus);
awTrackLength[i-1] =
((WORD) MCI_MSF_MINUTE (MCIStatus.dwReturn) * 60) +
(WORD) MCI_MSF_SECOND (MCIStatus.dwReturn);
}
}
// Reset the status indicators if a CD was removed
else if ((bMediaPresent) && (MCIStatus.dwReturn == FALSE)) {
bMediaPresent = FALSE;
for (i=1; i<=20; i++)
EnableWindow (GetDlgItem (hwnd, i+100), FALSE);
EnableWindow (GetDlgItem (hwnd, IDD_20PLUS), FALSE);
if (wPageNumber != 0)
for (i=1; i<=20; i++)
SetDlgItemText (hwnd, i+100, _itoa (i, szBuffer, 10));
SetWindowText (hwndTrack, "");
SetWindowText (hwndLength, "");
SetWindowText (hwndTime, "");
SetScrollPos (hwndScrollBar, SB_CTL, 0, TRUE);
InvalidateRect (hwndScrollBar, NULL, TRUE);
return 0;
}
// Find out if a CD is playing
if (bMediaPresent) {
MCIStatus.dwItem = MCI_STATUS_MODE;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM |
MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
// Update the status indicators if a CD is playing
if (MCIStatus.dwReturn == MCI_MODE_PLAY) {
MCIStatus.dwItem = MCI_STATUS_POSITION;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM | MCI_WAIT,
(DWORD) (LPSTR) &MCIStatus);
// Update track and length indicators if this is a new track
if (wCurrentTrack !=
(WORD) MCI_TMSF_TRACK (MCIStatus.dwReturn)) {
wCurrentTrack =
(WORD) MCI_TMSF_TRACK (MCIStatus.dwReturn);
SetWindowText (hwndTrack,
_itoa ((int) wCurrentTrack, szBuffer, 10));
SetWindowText (hwndLength,
IntToMinSec ((int) awTrackLength[wCurrentTrack-1],
szBuffer));
SetScrollRange (hwndScrollBar, SB_CTL, 0,
(int) awTrackLength[wCurrentTrack-1], FALSE);
}
// Update the time indicator and the scroll bar
if (!bScrolling) {
SetWindowText (hwndTime,
TMSFtoMinSec (MCIStatus.dwReturn, szBuffer));
SetScrollPos (hwndScrollBar, SB_CTL,
(((int) MCI_TMSF_MINUTE
(MCIStatus.dwReturn)) * 60) +
(int) MCI_TMSF_SECOND
(MCIStatus.dwReturn), TRUE);
}
}
// Reset the status indicators if there is no CD playing
else if (!bPaused) {
GetWindowText (hwndTrack, szBuffer, sizeof (szBuffer));
if (szBuffer[0] != 0x00) {
SetWindowText (hwndTrack, "");
SetWindowText (hwndLength, "");
SetWindowText (hwndTime, "");
SetScrollPos (hwndScrollBar, SB_CTL, 0, TRUE);
InvalidateRect (hwndScrollBar, NULL, TRUE);
wCurrentTrack = 0;
}
}
}
return 0;
case WM_HSCROLL:
// Ignore the scroll bar if there is not a CD playing
MCIStatus.dwItem = MCI_STATUS_MODE;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
if (MCIStatus.dwReturn != MCI_MODE_PLAY)
break;
switch (wParam) {
case SB_LINEUP:
case SB_PAGEUP:
case SB_LINEDOWN:
case SB_PAGEDOWN:
// Move the scroll bar thumb
if (!bScrolling) {
bScrolling = TRUE;
MCIStatus.dwItem = MCI_STATUS_POSITION;
mciSendCommand (MCIOpen.wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPSTR) &MCIStatus);
iThumbPos = (int) ((MCI_TMSF_MINUTE (MCIStatus.dwReturn) * 60)
+ MCI_TMSF_SECOND (MCIStatus.dwReturn));
}
if (wParam == SB_LINEUP)
iThumbPos--;
else if (wParam == SB_PAGEUP)
iThumbPos -= 8;
else if (wParam == SB_LINEDOWN)
iThumbPos++;
else // wParam == SB_PAGEDOWN
iThumbPos += 8;
if (iThumbPos < 0)
iThumbPos = 0;
else if (iThumbPos > (int) awTrackLength[wCurrentTrack-1])
iThumbPos = (int) awTrackLength[wCurrentTrack-1];
else {
IntToMinSec (iThumbPos, szBuffer);
SetWindowText (hwndTime, szBuffer);
SetScrollPos (hwndScrollBar, SB_CTL, iThumbPos, TRUE);
}
return 0;
case SB_ENDSCROLL:
// Go to a new location in the current track
if (bScrolling) {
bScrolling = FALSE;
MCIPlay.dwFrom = MCI_MAKE_TMSF ((BYTE) wCurrentTrack,
(BYTE) (iThumbPos / 60),
(BYTE) (iThumbPos - ((iThumbPos / 60) * 60)), 30);
mciSendCommand (MCIOpen.wDeviceID, MCI_PLAY,
MCI_FROM | MCI_NOTIFY, (DWORD) (LPSTR) &MCIPlay);
return 0;
}
else
break;
case SB_THUMBPOSITION:
// Go to the location specified by the scroll bar thumb
iThumbPos = (int) LOWORD (lParam);
SetWindowText (hwndTime, IntToMinSec (iThumbPos, szBuffer));
SetScrollPos (hwndScrollBar, SB_CTL, iThumbPos, TRUE);
InvalidateRect (hwndScrollBar, NULL, TRUE);
MCIPlay.dwFrom = MCI_MAKE_TMSF ((BYTE) wCurrentTrack,
(BYTE) (iThumbPos / 60),
(BYTE) (iThumbPos - ((iThumbPos / 60) * 60)), 30);
mciSendCommand (MCIOpen.wDeviceID, MCI_PLAY,
MCI_FROM | MCI_NOTIFY, (DWORD) (LPSTR) &MCIPlay);
return 0;
}
break;
case MM_MCINOTIFY:
// Restart the CD if "Continuous Play" is checked
if (wParam == MCI_NOTIFY_SUCCESSFUL) {
if (IsDlgButtonChecked (hwnd, IDD_CHECKBOX) == 1)
BeginPlay ((BYTE) 1, hwnd);
else
wCurrentTrack = 0;
return 0;
}
break;
case WM_CTLCOLOR:
// Paint status indicators red
if ((LOWORD (lParam) == hwndTrack) ||
(LOWORD (lParam) == hwndLength) ||
(LOWORD (lParam) == hwndTime)) {
SetBkColor (wParam, GetSysColor (COLOR_WINDOW));
SetTextColor (wParam, RGB (255, 0, 0));
UnrealizeObject (hBrush);
point.x = point.y = 0;
ClientToScreen (hwnd, &point);
SetBrushOrg (wParam, point.x, point.y);
return ((DWORD) hBrush);
}
break;
case WM_SYSCOLORCHANGE:
// Change the background brush when a system color changes
DeleteObject (hBrush);
hBrush = CreateSolidBrush (GetSysColor (COLOR_WINDOW));
return 0;
case WM_SYSCOMMAND:
// Execute commands in system menu
if (wParam == IDM_ABOUT) {
DialogBox (hInstance, "AboutBox", hwnd, lpfnAboutDlgProc);
return 0;
}
else if (wParam == IDM_TOGGLEMTS) {
if (GetMenuState (hSysMenu, IDM_TOGGLEMTS, MF_BYCOMMAND) &
MF_CHECKED) {
CheckMenuItem (hSysMenu, IDM_TOGGLEMTS, MF_UNCHECKED);
WritePrivateProfileString (szSection, szEntry, "0",
szIniFile);
}
else {
CheckMenuItem (hSysMenu, IDM_TOGGLEMTS, MF_CHECKED);
WritePrivateProfileString (szSection, szEntry, "1",
szIniFile);
}
return 0;
}
else
break;
case WM_DESTROY:
// Close devices, deallocate resources, and terminate
mciSendCommand (MCIOpen.wDeviceID, MCI_CLOSE, NULL, NULL);
KillTimer (hwnd, wTimerID);
DeleteObject (hBrush);
PostQuitMessage (0);
return 0;
}
return DefDlgProc (hwnd, message, wParam, lParam);
}
/********************************************************************
AboutDlgProc processes messages to the About dialog box.
********************************************************************/
BOOL FAR PASCAL AboutDlgProc (HWND hwnd, WORD message,
WORD wParam, LONG lParam)
{
PAINTSTRUCT ps;
HPEN hPen;
HDC hdc;
switch (message) {
case WM_INITDIALOG:
return TRUE;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
hPen = CreatePen (PS_SOLID, 16, RGB (255, 0, 255));
SelectObject (hdc, hPen);
MoveTo (hdc, 32, 0);
LineTo (hdc, 0, 32);
LineTo (hdc, 64, 0);
LineTo (hdc, 0, 64);
LineTo (hdc, 80, 0);
LineTo (hdc, 16, 80);
LineTo (hdc, 52, 56);
DeleteObject (hPen);
EndPaint (hwnd, &ps);
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDOK:
case IDCANCEL:
EndDialog (hwnd, 0);
return TRUE;
}
break;
}
return FALSE;
}
/********************************************************************
BeginPlay starts play at the beginning of the specified track.
********************************************************************/
void BeginPlay (BYTE byTrackNumber, HWND hwnd)
{
char *szBuffer[8];
bPaused = FALSE;
wCurrentTrack = (WORD) byTrackNumber;
// Update the track, length, and time indicators
SetWindowText (hwndTrack, _itoa ((int) byTrackNumber,
(char *) szBuffer, 10));
SetWindowText (hwndLength,
IntToMinSec ((int) awTrackLength[byTrackNumber-1],
(char *) szBuffer));
SetWindowText (hwndTime, "0:00");
// Initialize the scroll bar for this track
SetScrollRange (hwndScrollBar, SB_CTL, 0,
(int) awTrackLength[byTrackNumber-1], FALSE);
SetScrollPos (hwndScrollBar, SB_CTL, 0, TRUE);
InvalidateRect (hwndScrollBar, NULL, TRUE);
// Send an MCI_PLAY command to the CD audio driver
MCIPlay.dwCallback = (DWORD) hwnd;
MCIPlay.dwFrom = MCI_MAKE_TMSF (byTrackNumber, 0, 0, 1);
mciSendCommand (MCIOpen.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY,
(DWORD) (LPSTR) &MCIPlay);
}
/********************************************************************
ResumePlay resumes play after the Pause button is pressed.
********************************************************************/
void ResumePlay (DWORD dwPosition, HWND hwnd)
{
bPaused = FALSE;
MCIPlay.dwCallback = (DWORD) hwnd;
MCIPlay.dwFrom = dwPosition;
mciSendCommand (MCIOpen.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY,
(DWORD) (LPSTR) &MCIPlay);
}
/********************************************************************
UpdateTrackButtons changes the numbers on the track button display.
********************************************************************/
void UpdateTrackButtons (HWND hwnd)
{
int i, j;
char szBuffer[3];
j = (int) wPageNumber * 20;
for (i=1; i<=20; i++)
SetDlgItemText (hwnd, i+100, _itoa (i+j, szBuffer, 10));
if (wPageNumber == (wPageCount-1)) {
j = (int) (wNumberOfTracks % 20) + 1;
for (i=j; i<=20; i++)
EnableWindow (GetDlgItem (hwnd, i+100), FALSE);
}
else
for (i=1; i<=20; i++)
EnableWindow (GetDlgItem (hwnd, i+100), TRUE);
}
/********************************************************************
IntToMinSec converts a time value in seconds to a string in
minutes:seconds format.
********************************************************************/
char *IntToMinSec (int iTime, char *szResult)
{
int iSeconds;
char szBuffer[3];
_itoa (iTime / 60, szResult, 10);
strcat (szResult, ":");
if ((iSeconds = (iTime - ((iTime / 60) * 60))) < 10)
strcat (szResult, "0");
strcat (szResult, _itoa (iSeconds, szBuffer, 10));
return szResult;
}
/********************************************************************
TMSFtoMinSec converts a time value in TMSF format to a string
in minutes:seconds format.
********************************************************************/
char *TMSFtoMinSec (DWORD dwTime, char *szResult)
{
int iSeconds;
char szBuffer[3];
_itoa ((int) MCI_TMSF_MINUTE (dwTime), szResult, 10);
strcat (szResult, ":");
if ((iSeconds = (int) MCI_TMSF_SECOND (dwTime)) < 10)
strcat (szResult, "0");
strcat (szResult, _itoa (iSeconds, szBuffer, 10));
return szResult;
}