[DirectShow有关问题]Windows Mobile平台,CameraCapture的Preview的有关问题

[DirectShow问题]Windows Mobile平台,CameraCapture的Preview的问题
背景:WM平台Camera程序开发:Windows Mobile SDK 6.0 Professional 包中的CameraCapture例子程序,这个例子程序是SDK的,我将它修改成MFC对话框工程。但是该程序没有预览功能,所以我要在它的基础上加上预览,主要修改了CGraphManager类的CreateCaptureGraphInternal函数和RunCaptureGraphInternal函数,然后自己加个自定义函数PreviewCaptureGraph用来预览。PreviewCaptureGraph函数是在主对话框类中调用间接调用的,不是像例子程序中那样什么都放到工作线程中(因为我发现放到线程中,函数会卡在pMediaControl->Run()处,所有我就自定义了PreviewCaptureGraph函数,改写了原来的RunCaptureGraphInternal()函数)

问题:现在可以预览,但是预览的效果如下所示:

PreviewCaptureGraph()函数中的CHK(pVideoWindow->SetWindowPosition(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));这句调用没有作用,函数调用本身并没有失败,而且发现前面两个参数有效,即left和top有效,可以改变预览的left和top坐标位置。希望那个预览的窗口可以填充满那个CStatic控件区域(黑色边框那个)。

对DirectShow不了解,希望有做过或者开发过的兄弟指点一下~

C/C++ code
HRESULT CGraphManager::CreateCaptureGraphInternal()
{
    HRESULT       hr = S_OK;
    CComVariant   varCamName;
    CPropertyBag  PropBag;
    OAEVENT       oaEvent;
    WCHAR          wzDeviceName[MAX_PATH + 1] = {0};

    CComPtr<IMediaEvent>            pMediaEvent;
    CComPtr<IGraphBuilder>          pFilterGraph;
    CComPtr<IBaseFilter>            pVideoEncoder;
    CComPtr<IBaseFilter>            pASFMultiplexer;
    CComPtr<IFileSinkFilter>        pFileSinkFilter;
    CComPtr<IPersistPropertyBag>    pPropertyBag;
    CComPtr<IDMOWrapperFilter>      pWrapperFilter;
    CComPtr<IBaseFilter>            pImageSinkFilter;

    //
    // Create the capture graph builder and register the filtergraph manager. 
    //
    CHK(m_pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder));
    CHK(pFilterGraph.CoCreateInstance(CLSID_FilterGraph));
    CHK(m_pCaptureGraphBuilder->SetFiltergraph(pFilterGraph));


    //
    // Create and initialize the video capture filter
    //
    CHK(m_pVideoCaptureFilter.CoCreateInstance(CLSID_VideoCapture));
    CHK(m_pVideoCaptureFilter.QueryInterface(&pPropertyBag));

    // We are loading the driver CAM1 in the video capture filter. 
    CHK(GetFirstCameraDriver(wzDeviceName, MAX_PATH));
    varCamName = wzDeviceName;
    if(varCamName.vt != VT_BSTR)
    {
        ERR(E_OUTOFMEMORY);
    }

    CHK(PropBag.Write(L"VCapName", &varCamName));   
    CHK(pPropertyBag->Load(&PropBag, NULL));

    // Everything succeeded, the video capture filter is added to the filtergraph
    CHK(pFilterGraph->AddFilter(m_pVideoCaptureFilter, L"Video Capture Filter Source" ));


    // 
    // Third step: Create the video encoder DMO, load the WMV9 encoder, and 
    // add it to the graph
    //

    // Create the video encoder
    CHK(pVideoEncoder.CoCreateInstance(CLSID_DMOWrapperFilter ));
    CHK(pVideoEncoder.QueryInterface(&pWrapperFilter));

    // Load the WMV9 DMO
    CHK(pWrapperFilter->Init(CLSID_CWMV9EncMediaObject, DMOCATEGORY_VIDEO_ENCODER));

    // Everything succeeded, let's add the encoder to the graph
    CHK(pFilterGraph->AddFilter(pVideoEncoder, L"WMV9 DMO Encoder"));

    //
    // Create the ASF multiplexer and add it to the graph
    //
    CHK(m_pCaptureGraphBuilder->SetOutputFileName(&MEDIASUBTYPE_Asf, L"\\video1.asf", &pASFMultiplexer, &pFileSinkFilter));

    // Create preview 
    CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, NULL));
    //
    // Connect the video capture filter, the encoder and the multiplexer together
    // 
    CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, pVideoEncoder, pASFMultiplexer));

    //
    // Create the still image filter, and connect it to the video capture filter
    //
    CHK(pImageSinkFilter.CoCreateInstance(CLSID_IMGSinkFilter));
    CHK(pFilterGraph->AddFilter(pImageSinkFilter, L"Still image filter"));
    CHK(m_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_STILL, &MEDIATYPE_Video, m_pVideoCaptureFilter, NULL, pImageSinkFilter));
    CHK(pImageSinkFilter.QueryInterface(&m_pImageSinkFilter));

    //
    // Prevent the data from flowing into the capture stream
    //
    CHK(m_pCaptureGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCaptureFilter, 0, 0 ,0,0));

    //
    // Let's get the handle for DShow events. The main loop will listen to both notifications from 
    // the UI thread and for DShow notifications
    //
    CHK(pFilterGraph->QueryInterface(IID_IMediaEvent, (void**) &pMediaEvent));
    CHK(pMediaEvent->GetEventHandle(&oaEvent));
    m_handle[1] = (HANDLE) oaEvent;

    m_bGraphBuilt = TRUE;

_CLEANUP:
    if(FAILED(hr))
    {
        NotifyMessage(MESSAGE_ERROR, _T("Building the graph failed"));
    }
    return hr;
}

HRESULT CGraphManager::RunCaptureGraphInternal()
{
    HRESULT hr = S_OK;

//    CComPtr<IGraphBuilder> pGraphBuilder;
//     CComPtr<IMediaControl> pMediaControl;

    // Let's make sure that the graph has been initialized
    if((NULL == m_pCaptureGraphBuilder) || (FALSE == m_bGraphBuilt))
    {
        ERR(E_FAIL);
    }

    // Retrieve the filtergraph off the capture graph builder
//    CHK(m_pCaptureGraphBuilder->GetFiltergraph(&pGraphBuilder));


    // Get the media control interface, and run the graph
//    CHK(pGraphBuilder->QueryInterface(&pMediaControl));
//    CHK(pMediaControl->Run());

    CHK(NotifyMessage(MESSAGE_INFO, L"The Graph is Running ..."));

_CLEANUP:
    if(FAILED(hr))
    {
        NotifyMessage(MESSAGE_ERROR, L"Running The Capture Graph Failed");
    }

    PostMessage(m_hWnd, MSG_EVENTNOTIFICATION, 0, 0); // 这里我发送一个自定义消息到主对话框,在主对话框类的消息响应函数中调用PreviewCaptureGraph()函数。
    return hr;
}

HRESULT CGraphManager::PreviewCaptureGraph()
{
    HRESULT hr = S_OK;

    CComPtr<IGraphBuilder> pGraphBuilder;
    CComPtr<IMediaControl> pMediaControl;
    CComPtr<IVideoWindow>  pVideoWindow;

    // Let's make sure that the graph has been initialized
    if((NULL == m_pCaptureGraphBuilder) || (FALSE == m_bGraphBuilt))
    {
        ERR(E_FAIL);
    }

    // Retrieve the filtergraph off the capture graph builder
    CHK(m_pCaptureGraphBuilder->GetFiltergraph(&pGraphBuilder));

    // Previewer
    {
        ASSERT(m_hWndPreviewer);
        RECT rect = {0};
        GetClientRect(m_hWndPreviewer, &rect);
        CHK(pGraphBuilder->QueryInterface(&pVideoWindow));
        CHK(pVideoWindow->put_Owner((OAHWND)m_hWndPreviewer));
        CHK(pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
        CHK(pVideoWindow->SetWindowPosition(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
        // 这里无效,SetWindowPosition()中的最后两个参数宽度和高度似乎没起作用
        CHK(pVideoWindow->put_Visible(OATRUE));

        //CHK(pMediaControl->Run());
    }

    // Get the media control interface, and run the graph
    CHK(pGraphBuilder->QueryInterface(&pMediaControl));
    //CHK(pMediaControl->Stop());
    CHK(pMediaControl->Run());

    CHK(NotifyMessage(MESSAGE_INFO, L"The Graph is Running ..."));

_CLEANUP:
    if(FAILED(hr))
    {
        NotifyMessage(MESSAGE_ERROR, L"Running The Capture Graph Failed");
    }
    return hr;
}