Partilhar via


Implementando uma barra de busca

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize 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 de media player. A barra de busca é implementada como um controle de trackbar. Para obter uma visão geral da busca no DirectShow, consulte Buscando o gráfico de filtro.

Quando o aplicativo for iniciado, inicialize a barra deslizante.

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 controlo deslizante está desativada até que o utilizador abra um arquivo de mídia. O intervalo da barra de deslize é definido de 0 a 100. Durante a reprodução de ficheiros, a aplicação calculará a posição de reprodução como uma percentagem da duração do ficheiro e atualizará a barra de faixas em conformidade. Por exemplo, a posição da barra de deslocamento "50" corresponde sempre ao meio do ficheiro.

Quando o usuário abre um arquivo, crie um gráfico de reprodução de arquivo usando RenderFile. O código para isso é mostrado em Como reproduzir um arquivo. Em seguida, consulte o Filter Graph Manager 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étodoIMediaSeeking::CheckCapabilitiesou o métodoIMediaSeeking::GetCapabilities. Estes métodos fazem quase a mesma coisa, mas a sua semântica é ligeiramente 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 é pesquisável e o sinalizador AM_SEEKING_CanGetDuration verifica se a duração do arquivo pode ser determinada com antecedência. Se ambos os recursos forem suportados, o aplicativo habilita a barra de controle e recupera a duração do arquivo.

Se o gráfico for pesquisável, a aplicação usará um temporizador para atualizar a posição da barra de progresso durante a reprodução. Quando você executa o gráfico de filtro para reproduzir o arquivo, inicie o evento de temporizador chamando uma das funções de temporizador do Windows, como SetTimer. Para obter mais informações sobre temporizadores, consulte o tópico "Timers" no Platform 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;
    }
}

Utilize o evento de temporizador para atualizar a posição do controlador deslizante. Chame IMediaSeeking::GetCurrentPosition para recuperar a posição de reprodução atual e, em seguida, 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 trilha para procurar o arquivo. Quando o utilizador arrasta ou clica no controlo de barra deslizante, a aplicação recebe uma mensagem WM_HSCROLL. A menor palavra do parâmetro wParam é a mensagem de notificação do deslizador. Por exemplo, TB_ENDTRACK é enviado no final da ação da barra de controle deslizante, e TB_THUMBTRACK é enviado continuamente enquanto o utilizador arrasta a barra de controle deslizante. O código a seguir mostra uma maneira de manipular 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 utilizador arrastar o controlo deslizante, a aplicação emite uma série de comandos de busca, um para cada mensagem TB_THUMBTRACK que recebe. Para tornar as operações de busca o mais suaves possível, o aplicativo pausa o gráfico. Pausar o gráfico 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 gráfico ao seu estado original.