Реализация панели поиска
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи аудио и видеозахват в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine, и захват аудио и видео в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
В этом разделе описывается, как реализовать панель поиска для приложения проигрывателя мультимедиа. Панель поиска реализуется как элемент управления "Дорожка". Общие сведения о поиске в DirectShow см. в статье Поискграфа фильтров.
При запуске приложения инициализируйте панель отслеживания:
void InitSlider(HWND hwnd)
{
// Initialize the trackbar range, but disable the
// control until the user opens a file.
hScroll = GetDlgItem(hwnd, IDC_SLIDER1);
EnableWindow(hScroll, FALSE);
SendMessage(hScroll, TBM_SETRANGE, TRUE, MAKELONG(0, 100));
}
Панель отслеживания отключена, пока пользователь не откроет файл мультимедиа. Диапазон ползунка устанавливается от 0 до 100. Во время воспроизведения файлов приложение вычисляет позицию воспроизведения в процентах от длительности файла и соответствующим образом обновляет панель отслеживания. Например, позиция трекбара "50" всегда соответствует середине файла.
Когда пользователь открывает файл, создайте граф воспроизведения файлов с помощью RenderFile. Код для этого показан в как воспроизвести файл. Затем запросите у Диспетчера графов фильтрации интерфейс IMediaSeeking и сохраните указатель интерфейса.
IMediaSeeking *g_pSeek = 0;
hr = pGraph->QueryInterface(IID_IMediaSeeking, (void**)&g_pSeek);
Чтобы определить, является ли файл доступным для поиска, вызовите метод IMediaSeeking::CheckCapabilities или метод IMediaSeeking::GetCapabilities. Эти методы делают почти то же самое, но их семантика немного отличается. В следующем примере используется CheckCapabilites:
// Determine if the source is seekable.
BOOL bCanSeek = FALSE;
DWORD caps = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanGetDuration;
bCanSeek = (S_OK == pSeek->CheckCapabilities(&caps));
if (bCanSeek)
{
// Enable the trackbar.
EnableWindow(hScroll, TRUE);
// Find the file duration.
pSeek->GetDuration(&g_rtTotalTime);
}
Флаг AM_SEEKING_CanSeekAbsolute проверяет, можно ли искать исходный файл, а флаг AM_SEEKING_CanGetDuration проверяет, можно ли заранее определить длительность файла. Если поддерживаются обе возможности, приложение включает ползунковую панель и извлекает продолжительность файла.
Если граф доступен для поиска, приложение будет использовать таймер для обновления позиции панели отслеживания во время воспроизведения. При запуске графа фильтров для воспроизведения файла запустите событие таймера, вызвав одну из функций таймера Windows, например SetTimer. Дополнительные сведения о таймерах см. в разделе "Таймеры" в пакете SDK для платформы.
void StartPlayback(HWND hwnd)
{
pControl->Run();
if (bCanSeek)
{
StopTimer(); // Make sure an old timer is not still active.
nTimerID = SetTimer(hwnd, IDT_TIMER1, TICK_FREQ, (TIMERPROC)NULL);
if (nTimerID == 0)
{
/* Handle Error */
}
}
}
void StopTimer()
{
if (wTimerID != 0)
{
KillTimer(g_hwnd, wTimerID);
wTimerID = 0;
}
}
Используйте событие таймера для обновления позиции ползунка. Вызовите IMediaSeeking::GetCurrentPosition, чтобы получить текущую позицию воспроизведения, затем вычислите позицию в процентах от длительности файла.
case WM_TIMER:
if (wParam == IDT_TIMER1)
{
// Timer should not be running unless we really can seek.
ASSERT(bCanSeek == TRUE);
REFERENCE_TIME timeNow;
if (SUCCEEDED(pSeek->GetCurrentPosition(&timeNow)))
{
long sliderTick = (long)((timeNow * 100) / g_rtTotalTime);
SendMessage( hScroll, TBM_SETPOS, TRUE, sliderTick );
}
}
break;
Пользователь также может переместить панель отслеживания для поиска файла. Когда пользователь перетаскивает или щелкает элемент управления trackbar, приложение получает событие WM_HSCROLL. Низкое слово параметра wParam — это сообщение уведомления о панели отслеживания. Например, TB_ENDTRACK отправляется в конце действия панели отслеживания и TB_THUMBTRACK отправляется непрерывно, пока пользователь перетаскивает панель отслеживания. В следующем коде показан один из способов обработки сообщения WM_HSCROLL:
static OAFilterState state;
static BOOL bStartOfScroll = TRUE;
case WM_HSCROLL:
short int userReq = LOWORD(wParam);
if (userReq == TB_ENDTRACK || userReq == TB_THUMBTRACK)
{
DWORD dwPosition = SendMessage(hTrackbar, TBM_GETPOS, 0, 0);
// Pause when the scroll action begins.
if (bStartOfScroll)
{
pControl->GetState(10, &state);
bStartOfScroll = FALSE;
pControl->Pause();
}
// Update the position continuously.
REFERENCE_TIME newTime = (g_rtTotalTime/100) * dwPosition;
pSeek->SetPositions(&newTime, AM_SEEKING_AbsolutePositioning,
NULL, AM_SEEKING_NoPositioning);
// Restore the state at the end.
if (userReq == TB_ENDTRACK)
{
if (state == State_Stopped)
pControl->Stop();
else if (state == State_Running)
pControl->Run();
bStartOfScroll = TRUE;
}
}
}
Если пользователь перетаскивает панель отслеживания, приложение выдает ряд команд поиска, по одному для каждого сообщения TB_THUMBTRACK, которое он получает. Чтобы сделать операции поиска максимально гладкими, приложение приостанавливает график. Приостановка воспроизведения графа останавливает воспроизведение, но гарантирует, что окно видео обновлено. Когда приложение получает сообщение TB_ENDTRACK, оно восстанавливает граф в исходном состоянии.