Implementando uma barra de busca
[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]
Esta seção descreve como implementar uma barra de busca para um aplicativo media-player. A barra de busca é implementada como um controle de barra de controle. Para obter uma visão geral da busca no DirectShow, consulte Procurando o grafo de filtro.
Quando o aplicativo for iniciado, inicialize a barra de controle:
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));
}
A barra de controle é desabilitada até que o usuário abra um arquivo de mídia. O intervalo da barra de controle é definido de 0 a 100. Durante a reprodução do arquivo, o aplicativo calculará a posição de reprodução como uma porcentagem da duração do arquivo e atualizará a barra de controle adequadamente. Por exemplo, a posição da barra de controle "50" sempre corresponde ao meio do arquivo.
Quando o usuário abrir um arquivo, crie um grafo de reprodução de arquivo usando RenderFile. O código para isso é mostrado em Como reproduzir um arquivo. Em seguida, consulte o Gerenciador de Grafo de Filtro para a interface IMediaSeeking e armazene o ponteiro da interface:
IMediaSeeking *g_pSeek = 0;
hr = pGraph->QueryInterface(IID_IMediaSeeking, (void**)&g_pSeek);
Para determinar se o arquivo é pesquisável, chame o método IMediaSeeking::CheckCapabilities ou o método IMediaSeeking::GetCapabilities . Esses métodos fazem quase a mesma coisa, mas sua semântica é um pouco diferente. O exemplo a seguir usa 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);
}
O sinalizador AM_SEEKING_CanSeekAbsolute verifica se o arquivo de origem é buscado e o sinalizador AM_SEEKING_CanGetDuration verifica se a duração do arquivo pode ser determinada com antecedência. Se houver suporte para ambos os recursos, o aplicativo habilitará a barra de controle e recuperará a duração do arquivo.
Se o grafo for buscado, o aplicativo usará um temporizador para atualizar a posição da barra de controle durante a reprodução. Ao executar o grafo de filtro para reproduzir o arquivo, inicie o evento de temporizador chamando uma das funções do temporizador do Windows, como SetTimer. Para obter mais informações sobre temporizadores, consulte o tópico "Temporizadores" no SDK da Plataforma.
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;
}
}
Use o evento de temporizador para atualizar a posição da barra de controle. Chame IMediaSeeking::GetCurrentPosition para recuperar a posição de reprodução de groselha e calcule a posição como uma porcentagem da duração do arquivo:
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;
O usuário também pode mover a barra de controle para procurar o arquivo. Quando o usuário arrasta ou clica no controle trackbar, o aplicativo recebe um evento WM_HSCROLL. A palavra baixa do parâmetro wParam é a mensagem de notificação de barra de controle. Por exemplo, TB_ENDTRACK é enviado no final da ação de barra de controle e TB_THUMBTRACK é enviado continuamente enquanto o usuário arrasta a barra de controle. O código a seguir mostra uma maneira de lidar com a mensagem 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;
}
}
}
Se o usuário arrastar a barra de controle, o aplicativo emitirá uma série de comandos seek, um para cada TB_THUMBTRACK mensagem recebida. Para tornar as operações de busca o mais suaves possível, o aplicativo pausa o grafo. Pausar o grafo interrompe a reprodução, mas garante que a janela de vídeo seja atualizada. Quando o aplicativo recebe a mensagem TB_ENDTRACK, ele restaura o grafo para seu estado original.