Операционная система Windows 95 для программиста© Александр Фролов, Григорий ФроловТом 22, М.: Диалог-МИФИ, 1993, 271 стр. 7.4. Приложение Compact Disk PlayerВ качестве примера практического использования органов управления Trackbar, Progressbar и Animation мы предлагаем вам приложение Compact Disk Player, предназначенное для проигрывания дорожек звукового компакт-диска. Попутно мы продемонстрируем использование MCI-интерфейса в операционной системе Microsoft Windows 95. Напомним, что MCI-интерфейс используется для работы с устройствами мультимедиа. Более подробно вы можете об этом узнать из 15 тома "Библиотеки системного программиста". Вы также узнаете, как создать приложение Win32, не имеющее главное окно, а представляющее из себя обычную диалоговую панель. Внешний вид приложения Compact Disk Player показан на рис. 7.6.
Рис. 7.6. Приложение Compact Disk Player В верхней части окна слева находятся органы управления Trackbar и Progressbar. Первый из них используется для перемещения по дорожкам звукового компакт-диска, второй показывает текущую дорожку. По мере проигрывания дорожек полоса Progressbar и движок Trackbar сдвигаются вправо. Вы можете переключаться на произвольную дорожку компакт-диска, просто передвигая движок органа Trackbar в нужное место или делая щелчки мышью слева или справа от него в окне Trackbar. Для перехода к следующей дорожке можно использовать клавишу <PgUp>, клавиши перемещения курсора вверх и вправо, а для перехода к предыдущей - клавишу <PgDn> и клавиши перемещения курсора вниз и влево. Если нажать на клавишу <Home>, приложение начнет проигрывание с первой дорожки, а если <End> - с последней. Справа вверху в окне нашего приложения расположен орган управления Animation. Когда проигрывание остановлено, в окне этого органа управления изображается неподвижный компакт-диск. Когда же начинается проигрывание, этот диск начинает вращаться. В нижней части окна находятся кнопки, с помощью
которых можно управлять процессом проигрывания:
При смене компакт-диска количество рисок в окне органа управления Trackbar автоматически устанавливается равным количеству звуковых дорожек. Еще одно замечание. Когда вы вставляете музыкальный компакт-диск, операционная система Microsoft Windows 95 автоматически запускает приложение и начинает проигрывание вставленного диска. Для работы с нашим приложением просто остановите проигрывание и завершите приложение CD Player. Исходные тексты приложения Compact Disk PlayerПриложение Compact Disk Player сделано на базе приложения MCICDPL, которое было описано в 15 томе "Библиотеки системного программиста". Функции приложения Compact Disk Player определены в файлах cdplay.c (листинг 7.1) и cdproc.c (листинг 7.2). Листинг 7.1. Файл cdplay\cdplay.c #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include "resource.h" #include "afxres.h" #include "cdplay.h" HINSTANCE hInst; char szAppName[] = "CdPlayApp"; char szAppTitle[] = "CD Player"; UINT nTimerID; UINT nCurTrack = 0; UINT nTrackCnt = 0; HWND hwndCurTrack; HWND hProgressBar; HWND hTrackBar; // ----------------------------------------------------- // Функция WinMain // ----------------------------------------------------- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; hInst = hInstance; // Преверяем, не было ли это приложение запущено ранее hWnd = FindWindow(szAppName, NULL); if(hWnd) { if(IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE); SetForegroundWindow(hWnd); return FALSE; } // Инициализируем библиотеку стандартных органов управления InitCommonControls(); // Отображаем диалоговую панель, которая служит // главным окном приложения DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); return FALSE; } // ----------------------------------------------------- // Функция DlgProc // ----------------------------------------------------- BOOL APIENTRY DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { HANDLE_MSG(hdlg, WM_INITDIALOG, DlgProc_OnInitDialog); HANDLE_MSG(hdlg, WM_COMMAND, DlgProc_OnCommand); HANDLE_MSG(hdlg, WM_HSCROLL, DlgProc_OnHScroll); HANDLE_MSG(hdlg, WM_TIMER, DlgProc_OnTimer); default: break; } return FALSE; } // ----------------------------------------------------- // Функция DlgProc_OnInitDialog // ----------------------------------------------------- BOOL DlgProc_OnInitDialog(HWND hdlg, HWND hwndFocus, LPARAM lParam) { // Определяем идентификатор поля, которое используется // для отображения номера текущей дорожки hwndCurTrack = GetDlgItem(hdlg, IDT_CURTRACK); // Получаем идентификатор органа Progressbar hProgressBar = GetDlgItem(hdlg, IDC_PROGRESSBAR); // Устанавливаем диапазон изменения значений // и шаг для органа Progressbar SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, nTrackCnt)); SendMessage(hProgressBar, PBM_SETSTEP, 1, 0); // Получаем идентификатор органа Trackbar hTrackBar = GetDlgItem(hdlg, IDC_TRACKBAR); // Устанавливаем диапазон изменения значений // для органа Trackbar SendMessage(hTrackBar, TBM_SETRANGE, TRUE, MAKELPARAM(1, nTrackCnt)); // Устанавливаем шаг изменений SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 1); SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 1); // Инициализируем устройство проигрывания // звуковых компакт-дисков CdInit(); // Создаем таймер для периодического определения // состояния устройства проигрывания nTimerID = SetTimer(hdlg, 1, 1000, NULL); // Открываем AVI-файл с видеоклипом (вращающийся // компакт-диск) Animate_Open(GetDlgItem(hdlg, IDC_ANIMATE), "CD.AVI"); return TRUE; } // ----------------------------------------------------- // Функция DlgProc_OnCommand // ----------------------------------------------------- #pragma warning(disable: 4098) void DlgProc_OnCommand(HWND hdlg, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case IDCANCEL: case IDB_EXIT: { KillTimer(hdlg, nTimerID); // удаляем таймер CdClose(); // закрываем устройство чтения компакт-диска EndDialog(hdlg, TRUE); // завершаем работу приложения break; } // Выполнение команд проигрывания, останова, // паузы, возобновления проигрывания после паузы и т. д. case IDB_PLAY: CdPlay(hdlg, 1); break; case IDB_STOP: CdStop(); break; case IDB_PAUSE: CdPause(); break; case IDB_RESUME: CdResume(hdlg); break; case IDB_NEXT: CdPlayNext(hdlg); break; case IDB_PREV: CdPlayPrev(hdlg); break; case IDB_EJECT: CdEject(); break; default: return FALSE; } return TRUE; } // ----------------------------------------------------- // Функция DlgProc_OnTimer // ----------------------------------------------------- void DlgProc_OnTimer(HWND hwnd, UINT id) { BYTE szBuf[20]; // Если окно свернуто в пиктограмму, ничего не делаем, // чтобы не снижать производительность системы if(IsIconic(hwnd)) return; // Если состояние устройства проигрывания изменилось, // отображаем изменения в диалоговой панели if(CdUpdateState(hwnd)) { // Отображаем номер текущей дорожки if(nCurTrack != 0) { itoa(nCurTrack, szBuf, 10); SetWindowText(hwndCurTrack, szBuf); } else SetWindowText(hwndCurTrack, ""); // Изменяем положение движка Trackbar SendMessage(hTrackBar, TBM_SETPOS, TRUE, nCurTrack); // Изменяем диапазон значений и положение // полосы Progressbar SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, nTrackCnt)); SendMessage(hProgressBar, PBM_SETPOS, nCurTrack, 0); } } // ----------------------------------------------------- // Функция DlgProc_OnHScroll // ----------------------------------------------------- void DlgProc_OnHScroll(HWND hdlg, HWND hwndCtl, UINT code, int pos) { switch(code) { // Отрабатываем команды, поступающие от органа // управления Trackbar case TB_LINEDOWN: case TB_PAGEDOWN: CdPlayNext(hdlg); break; case TB_LINEUP: case TB_PAGEUP: CdPlayPrev(hdlg); break; case TB_BOTTOM: CdPlay(hdlg, nTrackCnt); break; case TB_TOP: CdPlay(hdlg, 1); break; case TB_THUMBPOSITION: CdPlay(hdlg, pos); break; default: break; } } В файле cdproc.c (листинг 7.2) собраны функции управления устройством чтения компакт-диска. Листинг 7.2. Файл cdplay\cdproc.c #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include "resource.h" #include "afxres.h" #include "cdplay.h" #include <mmsystem.h> DWORD dwrc; MCI_OPEN_PARMS MCIOpen; MCI_SET_PARMS MCISet; MCI_STATUS_PARMS MCIStatus; MCI_PLAY_PARMS MCIPlay; BOOL bMediaPresent = FALSE; BOOL bPaused = FALSE; UINT nMode = 0; HWND hwndCurTrack = NULL; extern UINT nCurTrack; extern UINT nTrackCnt; extern HWND hTrackBar; // ----------------------------------------------------- // Функция CdInit // ----------------------------------------------------- BOOL CdInit(void) { // Открываем устройство чтения компакт-дисков MCIOpen.lpstrDeviceType = (LPSTR)MCI_DEVTYPE_CD_AUDIO; dwrc = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID, (DWORD)&MCIOpen); if(dwrc) { mciwioError(dwrc); return FALSE; } // Устанавливаем формат времени MCISet.dwTimeFormat = MCI_FORMAT_TMSF; dwrc = mciSendCommand(MCIOpen.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)&MCISet); if(dwrc) { mciwioError(dwrc); return FALSE; } return TRUE; } // ----------------------------------------------------- // Функция CdClose // ----------------------------------------------------- void CdClose(void) { // Закрываем устройство чтения компакт-дисков dwrc = mciSendCommand(MCIOpen.wDeviceID, MCI_CLOSE, 0, 0); if(dwrc) mciwioError(dwrc); } //----------------------------------------------------- // mciwioError // Обработка ошибок //----------------------------------------------------- void mciwioError(DWORD dwrc) { BYTE szBuf[MAXERRORLENGTH]; if(mciGetErrorString(dwrc, (LPSTR)szBuf, MAXERRORLENGTH)) MessageBox(NULL, szBuf, "MCIWAVE Error", MB_ICONEXCLAMATION); else MessageBox(NULL, "Неизвестная ошибка", "MCIWAVE Error", MB_ICONEXCLAMATION); } // ----------------------------------------------------- // Функция CdUpdateState // ----------------------------------------------------- BOOL CdUpdateState(HWND hdlg) { BOOL fNeedUpdate = FALSE; UINT nCurMode; // Определяем текущее состояние проигрывателя CD MCIStatus.dwItem = MCI_STATUS_MODE; mciSendCommand(MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)&MCIStatus); // Проверяем, готово ли устройство чтения к работе if((MCIStatus.dwReturn == MCI_MODE_NOT_READY) || (MCIStatus.dwReturn == MCI_MODE_OPEN)) { // Устройство не готово nCurMode = CD_EMPTY; } else if((MCIStatus.dwReturn == MCI_MODE_STOP) && bPaused) { // Устройство остановлено nCurMode = CD_PAUSED; } else if(MCIStatus.dwReturn == MCI_MODE_PLAY) { // Устройство находится в режиме проигрывания nCurMode = CD_PLAYING; } else { // Устройство готово nCurMode = CD_READY; } // Если с момента последней проверки произошло // изменение режима, записываем код нового режима if(nMode != nCurMode) { fNeedUpdate = TRUE; nMode = nCurMode; // Если устройство находится в режиме проигрывания, // запускаем видеоклип. В противном случае // останавливаем видеоклип в его текущей позиции if(nCurMode == CD_PLAYING) Animate_Play(GetDlgItem(hdlg, IDC_ANIMATE), 0, -1, -1); else Animate_Stop(GetDlgItem(hdlg, IDC_ANIMATE)); } // Проверяем, вставлен ли компакт-диск MCIStatus.dwItem = MCI_STATUS_MEDIA_PRESENT; mciSendCommand(MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)&MCIStatus); // Если компакт-диск вставлен, определяем // количество звуковых дорожек if((!bMediaPresent) && MCIStatus.dwReturn) { bMediaPresent = TRUE; bPaused = FALSE; nCurTrack = 0; MCIStatus.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; mciSendCommand(MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)&MCIStatus); nTrackCnt = MCIStatus.dwReturn; // Устанавливаем диапазон изменения значений // для органа управления Trackbar SendMessage(hTrackBar, TBM_SETRANGE, TRUE, MAKELPARAM(1, nTrackCnt)); } // Если компакт-диск не вставлен, сбрасываем // номер текущей дорожки в поле диалоговой панели else if((bMediaPresent) && !MCIStatus.dwReturn) { bMediaPresent = FALSE; bPaused = FALSE; } // Если приложение находится в режиме проигрывания, // определяем номер текущей дорожки if(nCurMode == CD_PLAYING) { // Определяем текущую позицию MCIStatus.dwItem = MCI_STATUS_POSITION; mciSendCommand(MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)&MCIStatus); // Если номер дорожки изменился, отображаем новое // значение в соответствующем поле диалоговой панели if(nCurTrack != (UINT)MCI_TMSF_TRACK(MCIStatus.dwReturn)) { nCurTrack = (UINT)MCI_TMSF_TRACK(MCIStatus.dwReturn); fNeedUpdate = TRUE; } } return fNeedUpdate; } //----------------------------------------------------- // CdPlay // Запуск проигрывания дорожки //----------------------------------------------------- void CdPlay(HWND hwnd, UINT nTrack) { if(bMediaPresent) { bPaused = FALSE; MCIPlay.dwCallback = (DWORD)hwnd; MCIPlay.dwFrom = MCI_MAKE_TMSF(nTrack, 0, 0, 0); dwrc = mciSendCommand(MCIOpen.wDeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD)&MCIPlay); if(dwrc) mciwioError(dwrc); } } //----------------------------------------------------- // CdStop // Останов проигрывания дорожки //----------------------------------------------------- void CdStop(void) { if(bMediaPresent) { bPaused = FALSE; nCurTrack = 0; mciSendCommand(MCIOpen.wDeviceID, MCI_STOP, 0, 0); } } //----------------------------------------------------- // CdPause // Временный останов проигрывания дорожки //----------------------------------------------------- void CdPause(void) { if(bMediaPresent) { if(!bPaused) { bPaused = TRUE; mciSendCommand(MCIOpen.wDeviceID, MCI_PAUSE, 0, 0); } } } //----------------------------------------------------- // CdResume // Возобновление проигрывания после временного останова //----------------------------------------------------- void CdResume(HWND hwnd) { if(bMediaPresent) { if(bPaused) { bPaused = FALSE; MCIPlay.dwCallback = (DWORD)hwnd; mciSendCommand(MCIOpen.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)&MCIPlay); } } } //----------------------------------------------------- // CdPlayNext // Проигрывание следующей дорожки //----------------------------------------------------- void CdPlayNext(HWND hwnd) { UINT nNewTrack; if(bMediaPresent) { // Если текущая дорожка - последняя, // начинаем проигрывание с первой дорожки. // Если нет - проигрываем следующую дорожку if(nCurTrack == nTrackCnt) nNewTrack = 1; else nNewTrack = nCurTrack + 1; CdPlay(hwnd, nNewTrack); } } //----------------------------------------------------- // CdPlayPrev // Проигрывание предыдущей дорожки //----------------------------------------------------- void CdPlayPrev(HWND hwnd) { UINT nNewTrack; if(bMediaPresent) { // Если текущая дорожка - первая, // проигрываем последнюю дорожку if(nCurTrack <= 1) nNewTrack = nTrackCnt; else nNewTrack = nCurTrack - 1; CdPlay(hwnd, nNewTrack); } } //----------------------------------------------------- // CdEject // Выталкивание компакт-диска //----------------------------------------------------- void CdEject(void) { mciSendCommand(MCIOpen.wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0); } В файле cdplay.h (листинг 7.3) находятся описания функций, определенных в приложении Compact Disk Player. Листинг 7.3. Файл cdplay\cdplay.h BOOL APIENTRY DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam); BOOL DlgProc_OnInitDialog(HWND hdlg, HWND hwndFocus, LPARAM lParam); void DlgProc_OnCommand(HWND hdlg, int id, HWND hwndCtl, UINT codeNotify); void DlgProc_OnTimer(HWND hwnd, UINT id); void DlgProc_OnHScroll(HWND hwnd,HWND hwndCtl,UINT code, int pos); void UpdateDlgControls(void); BOOL CdInit(void); void CdClose(void); void mciwioError(DWORD dwrc); BOOL CdUpdateState(HWND hdlg); void CdPlay(HWND hwnd, UINT nTrack); void CdStop(void); void CdPause(void); void CdResume(HWND hwnd); void CdPlayNext(HWND hwnd); void CdPlayPrev(HWND hwnd); void CdEject(void); #define CD_EMPTY 0 #define CD_READY 1 #define CD_PLAYING 2 #define CD_PAUSED 3 В файле resource.h (создается автоматически системой Microsoft Visual C++) находятся определения констант для работы с ресурсами приложения Compact Disk Player. Этот файл представлен в листинге 7.4. Листинг 7.4. Файл cdplay\resource.h //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by cdplay.rc // #define IDD_DIALOG1 101 #define IDB_NEXT 1000 #define IDB_PREV 1001 #define IDB_PLAY 1002 #define IDB_STOP 1003 #define IDB_PAUSE 1004 #define IDB_RESUME 1005 #define IDB_EJECT 1006 #define IDT_CURTRACK 1008 #define IDB_EXIT 1009 #define IDC_PROGRESSBAR 1012 #define IDC_TRACKBAR 1014 #define IDC_ANIMATE 1015 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1016 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif Файл cdplay.rc (листинг 7.5) содержит определение ресурсов приложения Compact Disk Player. Листинг 7.5. Файл cdplay\cdplay.rc //Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ////////////////////////////////////////////////////////////// // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ////////////////////////////////////////////////////////////// // Dialog // IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 278, 138 STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Compact disk player, (C) A. Frolov, 1995" FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON ">>",IDB_NEXT,22,89,50,14 PUSHBUTTON "<<",IDB_PREV,76,89,50,14 PUSHBUTTON "Play",IDB_PLAY,129,89,50,14 PUSHBUTTON "Stop",IDB_STOP,22,106,50,14 PUSHBUTTON "Pause",IDB_PAUSE,76,106,50,14 PUSHBUTTON "Resume",IDB_RESUME,129,106,50,14 PUSHBUTTON "Eject",IDB_EJECT,203,89,50,14 PUSHBUTTON "Exit",IDB_EXIT,203,106,50,14 LTEXT "",IDT_CURTRACK,79,20,92,10 GROUPBOX "",IDC_STATIC,11,6,256,75 CONTROL "Generic1",IDC_PROGRESSBAR, "msctls_progress32", 0x3,25,39,184,9 CONTROL "Generic3",IDC_TRACKBAR, "msctls_trackbar32", WS_TABSTOP | 0x21,19,50,195,25 LTEXT "Track number:",IDC_STATIC,25,20,47,8 GROUPBOX "",IDC_STATIC,11,76,181,53 CONTROL "Animate",IDC_ANIMATE,"SysAnimate32", WS_BORDER | WS_TABSTOP | 0x1,219,34,33,33 GROUPBOX "",IDC_STATIC,191,76,76,53 END #ifdef APSTUDIO_INVOKED ////////////////////////////////////////////////////////////// // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END ////////////////////////////////////////////////////////////// #endif // APSTUDIO_INVOKED #ifndef APSTUDIO_INVOKED ////////////////////////////////////////////////////////////// // Generated from the TEXTINCLUDE 3 resource. ////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED Описание функцийКратко опишем функции приложения Compact Disk Player, имеющие отношение к органам управления Trackbar, Progressbar и Animation. Особенности использования интерфейса MCI были описаны в 15 томе "Библиотеки системного программиста". WinMainПосле сохранения идентификатора приложения и проверки на повторный запуск функция WinMain вызывает функцию InitCommonControls, выполняющую инициализацию библиотеки стандартных органов управления. Далее вызывается функция DialogBox, создающая диалоговую панель. Функция этой диалоговой панели DlgProc выполняет всю полезную работу. DlgProcФункция DlgProc обрабатывает сообщения WM_INITDIALOG, WM_COMMAND, WM_HSCROLL и WM_TIMER, вызывая для них, соответственно, функции DlgProc_OnInitDialog, DlgProc_OnCommand, DlgProc_OnHScroll и DlgProc_OnTimer. DlgProc1_OnInitDialogФункция DlgProc_OnInitDialog определяет идентификаторы органов управления, расположенных в диалоговой панели, и сохраняет их для дальнейшего использования. После этого она устанавливает диапазон изменения значений и шаг для органа Progressbar, посылая ему сообщения PBM_SETRANGE и PBM_SETSTEP. В качестве максимального используется значение из переменной nTrackCnt. Как только в устройство чтения компакт-дисков будет вставлен звуковой компакт-диск, обработчик сообщения WM_TIMER запишет в эту переменную количество дорожек. Шаг изменения значений для органа управления Progressbar устанавливается равным единице. Затем выполняется инициализация органа управления Trackbar. Максимальное значение устанавливается равным содержимому переменной nTrackCnt (как и для органа Progressbar), а шаг изменения - равным единице. Благодаря этому пользователь сможет перемещаться по всем дорожкам компакт-диска. После этого обработчик сообщения открывает и инициализирует устройство чтения компакт-дисков, вызывая функцию CdInit, и затем запускает таймер с интервалом, равным примерно одной секунде. Таймер нужен для периодического определения состояния компакт-диска и, в частности, для периодического определения номера текущей дорожки. На последнем шаге инициализации открывается файл с видеоклипом CD.AVI, который должен находится в текущем каталоге. Этот файл открывается макрокомандой Animate_Open. DlgProc_OnCommandФункция DlgProc1_OnCommand обрабатывает сообщение WM_COMMAND, поступающее от органов управления диалоговой панели. Когда пользователь нажимает кнопку Exit или клавишу <Esc> обработчик уничтожает таймер, закрывает устройство чтения компакт-диска при помощи функции CdClose и затем закрывает диалоговую панель, вызывая функцию EndDialog. В результате приложение завершает свою работу. Обработка остальных кнопок выполняется соответствующими функциями, определенными в файле cdproc.c (листинг 7.2). Действия, которые выполняют эти функции, были описаны нами в 15 томе "Библиотеки системного программиста", поэтому для экономии места мы не будем рассказывать о них еще раз. DlgProc_OnTimerФункция DlgProc_OnTimer обрабатывает сообщение WM_TIMER , поступающее примерно один раз в секунду. Если диалоговая панель находится в минимизированном состоянии (что определяется с помощью функции IsIconic), обработчик сразу возвращает управление. В противном случае вызывается функция CdUpdateState, определяющая текущее состояние устройства чтения компакт-дисков и выполняющая некоторые другие действия, связанные с обновлением состояния органов управления диалоговой панели. Если в результате вызова этой функции выяснилось, что состояние изменилось, функция DlgProc_OnTimer отображает номер текущей дорожки в статическом органе управления с идентификатором hwndCurTrack. После этого она изменяет положение движка Trackbar, чтобы он указывал на текущую дорожку, а также устанавливает диапазон значений и новое положение полосы Progressbar. DlgProc_OnHScrollФункция DlgProc_OnHScroll обрабатывает сообщение WM_HSCROLL , которое вырабатывает орган управления Trackbar. В ответ на извещения TB_LINEDOWN и TB_PAGEDOWN обработчик вызывает функцию CdPlayNext, которая проигрывает следующую дорожку. При обработке извещений TB_LINEUP и TB_PAGEUP вызывается функция CdPlayPrev, которая проигрывает предыдущую дорожку. Когда пользователь нажимает клавиши <Home> или <End>, обработчики извещений TB_TOP и TB_BOTTOM запускают проигрывание, соответственно, первой и последней дорожки звукового компакт-диска. Если пользователь перемещает движок органа управления Trackbar в новое положение, обработчик извещения TB_THUMBPOSITION запускает проигрывание той дорожки, которая была выбрана и номер которой был передан вместе с этим извещением. |