Partager via


Implémentation d’une barre de recherche

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement au nouveau code d’utiliser MediaPlayer, IMFMediaEngine et La capture audio/vidéo dans Media Foundation au lieu de DirectShow, lorsque cela est possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Cette section explique comment implémenter une barre de recherche pour une application de lecteur multimédia. La barre de recherche est implémentée en tant que contrôle trackbar. Pour obtenir une vue d’ensemble de la recherche dans DirectShow, consultez La recherche du graphe de filtre.

Lorsque l’application démarre, initialisez la barre de suivi :

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 barre de suivi est désactivée jusqu’à ce que l’utilisateur ouvre un fichier multimédia. La plage de la barre de suivi est définie de 0 à 100. Pendant la lecture du fichier, l’application calcule la position de lecture en tant que pourcentage de la durée du fichier et met à jour la barre de piste en conséquence. Par exemple, la position de la barre de suivi « 50 » correspond toujours au milieu du fichier.

Lorsque l’utilisateur ouvre un fichier, créez un graphique de lecture de fichiers à l’aide de RenderFile. Le code correspondant s’affiche dans Comment lire un fichier. Ensuite, interrogez le Gestionnaire de graphes de filtre pour l’interface IMediaSeeking et stockez le pointeur d’interface :

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

Pour déterminer si le fichier peut être recherché, appelez la méthode IMediaSeeking::CheckCapabilities ou la méthode IMediaSeeking::GetCapabilities . Ces méthodes font presque la même chose, mais leur sémantique est légèrement différente. L’exemple suivant utilise 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);
}

L’indicateur AM_SEEKING_CanSeekAbsolute vérifie si le fichier source est recherché et l’indicateur AM_SEEKING_CanGetDuration vérifie si la durée du fichier peut être déterminée à l’avance. Si les deux fonctionnalités sont prises en charge, l’application active la barre de suivi et récupère la durée du fichier.

Si le graphique est recherché, l’application utilise un minuteur pour mettre à jour la position de la barre de piste pendant la lecture. Lorsque vous exécutez le graphe de filtre pour lire le fichier, démarrez l’événement du minuteur en appelant l’une des fonctions du minuteur Windows, telles que SetTimer. Pour plus d’informations sur les minuteurs, consultez la rubrique « Minuteurs » dans le Kit de développement logiciel (SDK) de plateforme.

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

Utilisez l’événement du minuteur pour mettre à jour la position de la barre de suivi. Appelez IMediaSeeking::GetCurrentPosition pour récupérer la position de lecture de la boucle, puis calculez la position sous la forme d’un pourcentage de la durée du fichier :

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’utilisateur peut également déplacer la barre de suivi pour rechercher le fichier. Lorsque l’utilisateur fait glisser ou clique sur le contrôle trackbar, l’application reçoit un événement WM_HSCROLL. Le mot bas du paramètre wParam est le message de notification trackbar. Par exemple, TB_ENDTRACK est envoyé à la fin de l’action trackbar et TB_THUMBTRACK est envoyé en continu pendant que l’utilisateur fait glisser la barre de suivi. Le code suivant montre une façon de gérer le message 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;
        }
    }
}

Si l’utilisateur fait glisser la barre de suivi, l’application émet une série de commandes de recherche, une pour chaque message TB_THUMBTRACK qu’elle reçoit. Pour rendre les opérations de recherche aussi fluides que possible, l’application interrompt le graphe. La suspension du graphique arrête la lecture, mais garantit la mise à jour de la fenêtre vidéo. Lorsque l’application reçoit le message TB_ENDTRACK, elle restaure le graphe à son état d’origine.