Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. è stata sostituita da MediaPlayer, IMFMediaEnginee acquisizione audio/video in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice utilizzi MediaPlayer, IMFMediaEngine e Acquisizione audio/video nella 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.
Per scrivere il file, è sufficiente eseguire il grafico del filtro chiamando il metodo IMediaControl::Run. Attendere il completamento della riproduzione e arrestare in modo esplicito il grafico chiamando IMediaControl::Stop; in caso contrario, il file non viene scritto correttamente.
Per visualizzare lo stato di avanzamento dell'operazione di scrittura dei file, eseguire una query sul filtro Mux per l'interfaccia IMediaSeeking. Chiamare il metodo IMediaSeeking::GetDuration per recuperare la durata del file. Periodicamente mentre il grafico è in esecuzione, chiamare il metodo IMediaSeeking::GetCurrentPosition per recuperare la posizione corrente del grafico nel flusso. La posizione corrente divisa per la durata fornisce la percentuale di completamento.
Nota
Un'applicazione di solito interroga il Filter Graph Manager per IMediaSeeking, ma la scrittura di file è un'eccezione a questa regola. Filter Graph Manager calcola la posizione corrente dalla posizione iniziale e per quanto tempo il grafico è stato eseguito, che è accurato per la riproduzione dei file, ma non per la scrittura di file. Pertanto, per ottenere un risultato accurato, è necessario recuperare la posizione dal filtro MUX.
Il codice seguente ottiene la durata del file, avvia un timer per aggiornare l'interfaccia utente dell'applicazione ed esegue il grafico del filtro. Il controllo degli errori viene omesso per maggiore chiarezza.
IMediaSeeking *pSeek = NULL;
IMediaEventEx *pEvent = NULL;
IMediaControl *pControl = NULL;
REFERENCE_TIME rtTotal;
// Query for interfaces. Remember to release them later.
hr = pMux->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
hr = pGraph->QueryInterface(IID_IMediaEventEx, (void**)&pEvent);
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
// Error checking is omitted for clarity.
// Set the DirectShow event notification window.
hr = pEvent->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0);
// Set the range of the progress bar to the file length (in seconds).
hr = pSeek->GetDuration(&rtTotal);
SendDlgItemMessage(hwnd, IDC_PROGRESS1, PBM_SETRANGE, 0,
MAKELPARAM(0, rtTotal / 10000000));
// Start the timer.
UINT_PTR res = SetTimer(hwnd, nIDEvent, 100, NULL);
// Run the graph.
pControl->Run();
Quando l'applicazione riceve un evento timer, può aggiornare l'interfaccia utente con la posizione corrente:
void OnTimer(HWND hDlg, IMediaSeeking *pSeek)
{
REFERENCE_TIME rtNow;
HRESULT hr = pSeek->GetCurrentPosition(&rtNow);
if (SUCCEEDED(hr))
{
SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, rtNow/10000000, 0);
}
}
Quando l'applicazione riceve un evento di completamento DirectShow, deve arrestare il grafico, come illustrato nel codice seguente:
// Application window procedure
LRESULT CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
/* ... */
case WM_GRAPHNOTIFY:
DoHandleEvent();
break;
/* ... */
}
}
void DoHandleEvent()
{
long evCode, param1, param2;
bool bComplete = false;
if (!pEvent) return;
// Get all the events, and see we're done.
while (SUCCEEDED(pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0))
{
pEvent->FreeEventParams(evCode, param1, param2);
switch(evCode)
{
case EC_USERABORT:
case EC_ERRORABORT:
case EC_COMPLETE:
bComplete = true;
break;
}
}
if (bComplete)
{
pControl->Stop(); // Important! You must stop the graph!
// Turn off event notification.
pEvent->SetNotifyWindow(NULL, 0, 0);
pEvent->Release();
pEvent = NULL;
// Reset the progress bar to zero and get rid of the timer.
SendDlgItemMessage(IDC_PROGRESS1, PBM_SETPOS, 0, 0);
KillTimer(hwnd, nIDEvent);
}
}