Problem mit IVideoWindow bei DirectShow



  • Hallo,

    ich habe versucht das DirectX-Sample PlayCap nachzuarbeiten.
    Leider tritt bei mir der Fehler in der folgenden Anweisung auf:

    // Set the video window to be a child of the main window
    hr = pVW->put_Owner((OAHWND)hWnd);
    if (FAILED(hr))
    {
    	MessageBox(NULL, "Test", "Test", MB_ICONINFORMATION | MB_OK);
            return hr;
    }
    

    d.h. mein Fenster kann nicht als Videoausgabefenster genutzt werden, warum?

    Lasse ich die Methode SetupVideoWindow weg, funktioniert alles, nur das ich ein extra Fenster zur ausgabe bekomme.

    Hier der gesamte Code:

    // DSTest.cpp : Definiert den Einsprungpunkt für die Anwendung.
    //
    
    #include "stdafx.h"
    #include "resource.h"
    #include "Dshow.h"
    #include "string"
    using namespace std;
    
    #define MAX_LOADSTRING 100
    
    // Globale Variablen:
    HINSTANCE hInst;					// aktuelle Instanz
    TCHAR szTitle[MAX_LOADSTRING];								// Text der Titelzeile
    TCHAR szWindowClass[MAX_LOADSTRING];								// Text der Titelzeile
    IGraphBuilder *pGraph = NULL;
    ICaptureGraphBuilder2 *pCap = NULL;
    IBaseFilter *pFilter = NULL;
    IVideoWindow  * pVW = NULL;
    IMediaControl * pMC = NULL;
    HWND hWnd;
    
    // Vorausdeklarationen von Funktionen, die in diesem Code-Modul enthalten sind:
    ATOM				MyRegisterClass( HINSTANCE hInstance );
    BOOL				InitInstance( HINSTANCE, int );
    LRESULT CALLBACK	WndProc( HWND, UINT, WPARAM, LPARAM );
    LRESULT CALLBACK	About( HWND, UINT, WPARAM, LPARAM );
    HRESULT				Init(void);
    HRESULT				InitCaptureDevice(void);
    HRESULT				SetupVideoWindow(void);
    void				ResizeVideoWindow(void);
    void				CleanUp(void);
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow )
    {
     	// ZU ERLEDIGEN: Fügen Sie hier den Code ein.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	// Globale Zeichenfolgen initialisieren
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_DSTEST, szWindowClass, MAX_LOADSTRING);
    	MyRegisterClass(hInstance);
    
    	// Initialisierung der Anwendung durchführen:
    	if( !InitInstance( hInstance, nCmdShow ) ) 
    	{
    		return FALSE;
    	}
    
    	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DSTEST);
    
    	//Startausführungen
    	Init();
    
    	// Hauptnachrichtenschleife:
    	while( GetMessage(&msg, NULL, 0, 0) ) 
    	{
    		if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) 
    		{
    			TranslateMessage( &msg );
    			DispatchMessage( &msg );
    		}
    	}
    
    	//Säuberung
    	CleanUp();
    
    	return msg.wParam;
    }
    
    //
    //  FUNKTION: MyRegisterClass()
    //
    //  AUFGABE: Registriert die Fensterklasse.
    //
    //  KOMMENTARE:
    //
    //    Diese Funktion und ihre Verwendung sind nur notwendig, wenn dieser Code
    //    mit Win32-Systemen vor der 'RegisterClassEx'-Funktion kompatibel sein soll,
    //    die zu Windows 95 hinzugefügt wurde. Es ist wichtig diese Funktion aufzurufen,
    //    damit der Anwendung kleine Symbole mit den richtigen Proportionen zugewiesen
    //    werden.
    //
    ATOM MyRegisterClass( HINSTANCE hInstance )
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX); 
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= (WNDPROC)WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_DSTEST);
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= (LPCSTR)IDC_DSTEST;
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNKTION: InitInstance(HANDLE, int)
    //
    //   AUFGABE: Speichert die Instanzzugriffsnummer und erstellt das Hauptfenster
    //
    //   KOMMENTARE:
    //
    //        In dieser Funktion wird die Instanzzugriffsnummer in einer globalen Variable
    //        gespeichert und das Hauptprogrammfenster erstellt und angezeigt.
    //
    BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
    {
    
       hInst = hInstance; // Instanzzugriffsnummer in unserer globalen Variable speichern
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
       if( !hWnd ) 
       {
          return FALSE;
       }
    
       ShowWindow( hWnd, nCmdShow );
       UpdateWindow( hWnd );
    
       return TRUE;
    }
    
    //
    //  FUNKTION: WndProc(HWND, unsigned, WORD, LONG)
    //
    //  AUFGABE:  Verarbeitet Nachrichten für das Hauptfenster.
    //
    //  WM_COMMAND	- Anwendungsmenü verarbeiten
    //  WM_PAINT	- Hauptfenster darstellen
    //  WM_DESTROY	- Beendigungsnachricht ausgeben und zurückkehren
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    	TCHAR szHello[MAX_LOADSTRING];
    	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
    
    	switch( message ) 
    	{
    		case WM_COMMAND:
    			wmId    = LOWORD(wParam); 
    			wmEvent = HIWORD(wParam); 
    			// Menüauswahlen analysieren:
    			switch( wmId ) 
    			{
    				case IDM_\1:
    				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
    				   break;
    				case IDM_EXIT:
    				   DestroyWindow( hWnd );
    				   break;
    				default:
    				   return DefWindowProc( hWnd, message, wParam, lParam );
    			}
    			break;
    		case WM_PAINT:
    			hdc = BeginPaint (hWnd, &ps);
    			// ZU ERLEDIGEN: Hier beliebigen Code zum Zeichnen hinzufügen...
    			RECT rt;
    			GetClientRect( hWnd, &rt );
    			DrawText( hdc, szHello, strlen(szHello), &rt, DT_CENTER );
    			EndPaint( hWnd, &ps );
    			break;
    		case WM_DESTROY:
    			PostQuitMessage( 0 );
    			break;
    		default:
    			return DefWindowProc( hWnd, message, wParam, lParam );
       }
       return 0;
    }
    
    // Nachrichtenbehandlungsroutine für "Info"-Feld.
    LRESULT CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
    {
    	switch( message )
    	{
    		case WM_INITDIALOG:
    				return TRUE;
    
    		case WM_COMMAND:
    			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
    			{
    				EndDialog(hDlg, LOWORD(wParam));
    				return TRUE;
    			}
    			break;
    	}
        return FALSE;
    }
    
    HRESULT	Init(void)
    {
    	CoInitialize(NULL);
    
    	HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, 
    					IID_ICaptureGraphBuilder2, (void**)&pCap);
    
    	if (SUCCEEDED(hr))
        {
            // Create the Filter Graph Manager.
            hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
    								IID_IGraphBuilder, (void**)&pGraph);
    
    		if (SUCCEEDED(hr))
            {
                // Initialize the Capture Graph Builder.
                pCap->SetFiltergraph(pGraph);
    			hr = pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &pMC);
    			if (FAILED(hr))
    				return hr;
    
    			//Device initialisieren
    
    			hr = InitCaptureDevice();
    			if (SUCCEEDED(hr))
    			{
    				MessageBox(NULL, "CaptureDevice initialisiert", "Information", MB_ICONINFORMATION | MB_OK );
    				hr = pCap->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 
    											pFilter, NULL, NULL);
    
    				// Obtain interfaces for media control and Video Window
    				hr = pMC->Run();
    
    			}
    
    			return S_OK;
    		}
    		else MessageBox(NULL, "Fehler bei der Initialisierung des GraphBuilders", "Fehler", MB_ICONSTOP | MB_OK);
    	}
    	else MessageBox(NULL, "Fehler bei der Initialisierung des CaptureGraphBuilders", "Fehler", MB_ICONSTOP | MB_OK);
    
    	return hr;
    }
    
    HRESULT	InitCaptureDevice(void)
    {
    	ICreateDevEnum *pDevEnum = NULL;
    	IEnumMoniker *pEnum = NULL;
    	IMoniker *pMoniker = NULL;
    
    	// Create the System Device Enumerator.
    	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
    					CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
    					reinterpret_cast<void**>(&pDevEnum));
    	if (SUCCEEDED(hr))
    	{
    		// Create an enumerator for the video capture category.
    		hr = pDevEnum->CreateClassEnumerator(
    						CLSID_VideoInputDeviceCategory,
    						&pEnum, 0);
    		if (FAILED(hr))
    		{
    			MessageBox(NULL, "Fehler bei der Initialisierung des VideoDeviceEnumerator", "Fehler", MB_ICONSTOP | MB_OK);
    			return hr;
    		}
    		else
    		{
    			//Device auswählen
    			while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
    			{
    
    				IPropertyBag *pPropBag;
    				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
    											(void**)(&pPropBag));
    				if (FAILED(hr))
    				{
    					pMoniker->Release();
    					continue;  // Skip this one, maybe the next one will work.
    				}
    				if (SUCCEEDED(hr))
    				{
    					//Devicename ausgeben und setzen
    					VARIANT varName;
    					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    					//MessageBox(NULL, varName.bstrVal, "Device gefunden", MB_ICONINFORMATION | MB_OK);
    
    					//Capturefilter dem CaptureGraphBuilder hinzufügen
    					hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter);
    					if (SUCCEEDED(hr))
    					{
    					    hr = pGraph->AddFilter(pFilter, L"Capture Filter");
    
    						hr = SetupVideoWindow();
    
    						return hr;
    					}
    
    				}
    			}
    		}
    
    	}
    	else MessageBox(NULL, "Fehler bei der Initialisierung des SystemDeviceEnumerator", "Fehler", MB_ICONSTOP | MB_OK);
    
    	return hr;
    }
    
    void CleanUp(void)
    {
    	pCap->Release();
    	pGraph->Release();
    	pFilter->Release();
    	pVW->Release();
    }
    
    HRESULT SetupVideoWindow(void)
    {
        HRESULT hr;
    
    	hr = pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &pVW);
        if (FAILED(hr)) {
    
            return hr;
    	}
    
        // Set the video window to be a child of the main window
        hr = pVW->put_Owner((OAHWND)hWnd);
        if (FAILED(hr))
    	{
    		MessageBox(NULL, "Test", "Test", MB_ICONINFORMATION | MB_OK);
            return hr;
    	}
    
        // Set video window style
        hr = pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
        if (FAILED(hr))
            return hr;
    
        // Use helper function to position video window in client rect 
        // of main application window
        ResizeVideoWindow();
    
        // Make the video window visible, now that it is properly positioned
        hr = pVW->put_Visible(OATRUE);
        if (FAILED(hr))
            return hr;
    
        return hr;
    }
    
    void ResizeVideoWindow(void)
    {
        // Resize the video preview window to match owner window size
        if (pVW)
        {
            RECT rc;
    
            // Make the preview video fill our window
            GetClientRect(hWnd, &rc);
            pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
        }
    }
    

Anmelden zum Antworten