Condividi tramite


Implementazione di una barra di ricerca

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Questa sezione descrive come implementare una barra di ricerca per un'applicazione lettore multimediale. La barra di ricerca viene implementata come controllo trackbar. Per una panoramica della ricerca in DirectShow, vedere Ricerca del grafico dei filtri.

All'avvio dell'applicazione, inizializzare la barra di traccia:

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));
}

La barra di traccia viene disabilitata fino a quando l'utente apre un file multimediale. L'intervallo della barra di rilevamento è impostato da 0 a 100. Durante la riproduzione dei file, l'applicazione calcola la posizione di riproduzione come percentuale della durata del file e aggiorna di conseguenza la barra delle tracce. Ad esempio, la posizione della barra di traccia "50" corrisponde sempre al centro del file.

Quando l'utente apre un file, compilare un grafico di riproduzione file usando RenderFile. Il codice per questo è illustrato in Come riprodurre un file. Eseguire quindi una query su Filter Graph Manager per l'interfaccia IMediaSeeking e archiviare il puntatore dell'interfaccia:

IMediaSeeking *g_pSeek = 0;
hr = pGraph->QueryInterface(IID_IMediaSeeking, (void**)&g_pSeek);

Per determinare se il file è ricercabile, chiamare il metodo IMediaSeeking::CheckCapabilities o il metodo IMediaSeeking::GetCapabilities. Questi metodi fanno quasi la stessa cosa, ma la loro semantica è leggermente diversa. Nell'esempio seguente viene usato 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);
}

Il flag AM_SEEKING_CanSeekAbsolute verifica se il file di origine è ricercabile e il flag AM_SEEKING_CanGetDuration verifica se la durata del file può essere determinata in anticipo. Se entrambe le funzionalità sono supportate, l'applicazione abilita la barra delle tracce e recupera la durata del file.

Se il grafico è ricercabile, l'applicazione userà un timer per aggiornare la posizione della barra di traccia durante la riproduzione. Quando si esegue il grafico del filtro per riprodurre il file, avviare l'evento timer chiamando una delle funzioni timer di Windows, ad esempio SetTimer. Per altre informazioni sui timer, vedere l'argomento "Timer" in 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;
    }
}

Usare l'evento timer per aggiornare la posizione della barra di traccia. Chiamare IMediaSeeking::GetCurrentPosition per recuperare la posizione di riproduzione currante e quindi calcolare la posizione come percentuale della durata del file:

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;

L'utente può anche spostare la barra di traccia per cercare il file. Quando l'utente trascina o fa clic sul controllo trackbar, l'applicazione riceve un evento WM_HSCROLL. La parola bassa del parametro wParam è il messaggio di notifica della barra di traccia. Ad esempio, TB_ENDTRACK viene inviato alla fine dell'azione trackbar e TB_THUMBTRACK viene inviato continuamente mentre l'utente trascina la barra di traccia. Il codice seguente mostra un modo per gestire il messaggio di 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 l'utente trascina la barra delle tracce, l'applicazione genera una serie di comandi di ricerca, uno per ogni messaggio TB_THUMBTRACK ricevuto. Per rendere più fluide le operazioni di ricerca, l'applicazione sospende il grafico. La sospensione del grafico arresta la riproduzione, ma assicura che la finestra video venga aggiornata. Quando l'applicazione riceve il messaggio di TB_ENDTRACK, ripristina il grafico allo stato originale.