Implementieren einer Suchleiste

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde durch MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation ersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code nach Möglichkeit MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet. Microsoft schlägt vor, vorhandenen Code, der die Legacy-APIs verwendet, um nach Möglichkeit die neuen APIs zu verwenden.]

In diesem Abschnitt wird beschrieben, wie Sie eine Suchleiste für eine Media-Player-Anwendung implementieren. Die Suchleiste wird als Trackbar-Steuerelement implementiert. Eine Übersicht über die Suche in DirectShow finden Sie unter Suchen des Filterdiagramms.

Initialisieren Sie beim Starten der Anwendung die Trackbar:

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

Die Trackbar ist deaktiviert, bis der Benutzer eine Mediendatei öffnet. Der Trackbarbereich ist von 0 bis 100 festgelegt. Während der Dateiwiedergabe berechnet die Anwendung die Wiedergabeposition als Prozentsatz der Dateidauer und aktualisiert die Trackbar entsprechend. Beispielsweise entspricht die Spurleistenposition "50" immer der Mitte der Datei.

Wenn der Benutzer eine Datei öffnet, erstellen Sie mithilfe von RenderFile ein Dateiwiedergabediagramm. Der Code dafür wird unter Wiedergeben einer Datei angezeigt. Fragen Sie dann den Filter Graph-Manager nach der IMediaSeeking-Schnittstelle ab, und speichern Sie den Schnittstellenzeiger:

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

Um zu bestimmen, ob die Datei suchbar ist, rufen Sie entweder die IMediaSeeking::CheckCapabilities-Methode oder die IMediaSeeking::GetCapabilities-Methode auf . Diese Methoden machen fast das gleiche, aber ihre Semantik unterscheidet sich geringfügig. Im folgenden Beispiel wird CheckCapabilites verwendet:

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

Das AM_SEEKING_CanSeekAbsolute-Flag überprüft, ob die Quelldatei suchbar ist, und das AM_SEEKING_CanGetDuration-Flag überprüft, ob die Dauer der Datei im Voraus bestimmt werden kann. Wenn beide Funktionen unterstützt werden, aktiviert die Anwendung die Trackbar und ruft die Dateidauer ab.

Wenn das Diagramm suchbar ist, verwendet die Anwendung einen Timer, um die Position der Trackleiste während der Wiedergabe zu aktualisieren. Wenn Sie das Filterdiagramm zum Wiedergeben der Datei ausführen, starten Sie das Timerereignis, indem Sie eine der Windows-Timerfunktionen aufrufen, z. B. SetTimer. Weitere Informationen zu Timern finden Sie im Thema "Timer" im 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;
    }
}

Verwenden Sie das Timerereignis, um die Position der Trackleiste zu aktualisieren. Rufen Sie IMediaSeeking::GetCurrentPosition auf, um die Wiedergabeposition der Johannisbeere abzurufen, und berechnen Sie dann die Position als Prozentsatz der Dateidauer:

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;

Der Benutzer kann auch die Trackbar verschieben, um die Datei zu suchen. Wenn der Benutzer das Trackbar-Steuerelement zieht oder klickt, empfängt die Anwendung ein WM_HSCROLL-Ereignis. Das niedrige Wort des wParam-Parameters ist die Trackbar-Benachrichtigungsnachricht. Beispielsweise wird TB_ENDTRACK am Ende der Trackbar-Aktion gesendet, und TB_THUMBTRACK wird kontinuierlich gesendet, während der Benutzer die Trackleiste zieht. Der folgende Code zeigt eine Möglichkeit, die WM_HSCROLL Nachricht zu behandeln:

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

Wenn der Benutzer die Trackbar zieht, gibt die Anwendung eine Reihe von Suchbefehlen aus, einen für jede TB_THUMBTRACK Nachricht, die sie empfängt. Um die Suchvorgänge so reibungslos wie möglich zu gestalten, hält die Anwendung das Diagramm an. Das Anhalten des Diagramms beendet die Wiedergabe, stellt jedoch sicher, dass das Videofenster aktualisiert wird. Wenn die Anwendung die TB_ENDTRACK-Nachricht empfängt, wird das Diagramm wieder in den ursprünglichen Zustand versetzt.