Share via


검색 표시줄 구현

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드가 DirectShow 대신 Media Foundation에서 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

이 섹션에서는 미디어 플레이어 애플리케이션에 대한 검색 표시줄을 구현하는 방법을 설명합니다. 검색 표시줄은 트랙바 컨트롤로 구현됩니다. DirectShow에서 검색에 대한 개요는 필터 그래프 검색을 참조하세요.

애플리케이션이 시작되면 트랙바를 초기화합니다.

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

사용자가 미디어 파일을 열 때까지 트랙바를 사용할 수 없습니다. 트랙바 범위는 0에서 100으로 설정됩니다. 파일 재생 중에 애플리케이션은 재생 위치를 파일 기간의 백분율로 계산하고 그에 따라 트랙바를 업데이트합니다. 예를 들어 트랙바 위치 "50"은 항상 파일의 중간에 해당합니다.

사용자가 파일을 열면 RenderFile을 사용하여 파일 재생 그래프를 빌드합니다. 이에 대한 코드는 파일 재생 방법에 나와 있습니다. 그런 다음 IMediaSeeking 인터페이스에 대한 Filter Graph Manager를 쿼리하고 인터페이스 포인터를 저장합니다.

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

파일을 검색할 수 있는지 확인하려면 IMediaSeeking::CheckCapabilities 메서드 또는 IMediaSeeking::GetCapabilities 메서드를 호출합니다. 이러한 메서드는 거의 동일한 작업을 수행하지만 의미 체계는 약간 다릅니다. 다음 예제에서는 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);
}

AM_SEEKING_CanSeekAbsolute 플래그는 원본 파일을 검색할 수 있는지 여부를 확인하고 AM_SEEKING_CanGetDuration 플래그는 파일의 기간을 미리 확인할 수 있는지 여부를 확인합니다. 두 기능이 모두 지원되는 경우 애플리케이션은 트랙바를 사용하도록 설정하고 파일 기간을 검색합니다.

그래프를 검색할 수 있는 경우 애플리케이션은 타이머를 사용하여 재생 중에 트랙바 위치를 업데이트합니다. 필터 그래프를 실행하여 파일을 재생하는 경우 SetTimer와 같은 Windows 타이머 함수 중 하나를 호출하여 타이머 이벤트를 시작합니다. 타이머에 대한 자세한 내용은 플랫폼 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;
    }
}

타이머 이벤트를 사용하여 트랙바의 위치를 업데이트합니다. IMediaSeeking::GetCurrentPosition을 호출하여 건포도 재생 위치를 검색한 다음, 파일 기간의 백분율로 위치를 계산합니다.

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;

사용자는 트랙바를 이동하여 파일을 검색할 수도 있습니다. 사용자가 트랙바 컨트롤을 끌거나 클릭하면 애플리케이션은 WM_HSCROLL 이벤트를 받습니다. wParam 매개 변수의 하위 단어는 트랙바 알림 메시지입니다. 예를 들어 TB_ENDTRACK 트랙바 작업의 끝에 전송되고 사용자가 트랙바를 끄는 동안 TB_THUMBTRACK 지속적으로 전송됩니다. 다음 코드는 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;
        }
    }
}

사용자가 트랙바를 끌면 애플리케이션에서 수신하는 각 TB_THUMBTRACK 메시지에 대해 하나씩 일련의 검색 명령을 실행합니다. 검색 작업을 최대한 원활하게 만들기 위해 애플리케이션은 그래프를 일시 중지합니다. 그래프를 일시 중지하면 재생이 중지되지만 비디오 창이 업데이트되었는지 확인합니다. 애플리케이션은 TB_ENDTRACK 메시지를 받으면 그래프를 원래 상태로 복원합니다.