C++ 如何在未注册的筛选器上使用属性页?

C++ 如何在未注册的筛选器上使用属性页?,c++,winapi,com,directshow,multimedia,C++,Winapi,Com,Directshow,Multimedia,我使用过滤器DS LAME来压缩音频。我从文件“lame.ax”中加载了它,如下所示: // pPath - path to LAME "lame.ax" HRESULT CMyFilter::CreateObjectFromPath(wchar_t *pPath, REFCLSID clsid, IUnknown **ppUnk) { // load the target DLL directly if (!m_hLibFilter) m_hLibFilter = LoadLi

我使用过滤器DS LAME来压缩音频。我从文件“lame.ax”中加载了它,如下所示:

// pPath - path to LAME "lame.ax"
HRESULT CMyFilter::CreateObjectFromPath(wchar_t *pPath, REFCLSID clsid, IUnknown **ppUnk)
{
    // load the target DLL directly
    if (!m_hLibFilter) m_hLibFilter = LoadLibrary(pPath);
    if (!m_hLibFilter)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }

    // the entry point is an exported function
    FN_DLLGETCLASSOBJECT fn = (FN_DLLGETCLASSOBJECT)GetProcAddress(m_hLibFilter, "DllGetClassObject");
    if (fn == NULL)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }

    // create a class factory
    IUnknownPtr pUnk;
    HRESULT hr = fn(clsid, IID_IUnknown, (void**)(IUnknown**)&pUnk);
    if (SUCCEEDED(hr))
    {
        IClassFactoryPtr pCF = pUnk;
        if (pCF == NULL)
        {
            hr = E_NOINTERFACE;
        }
        else
        {
            // ask the class factory to create the object
            hr = pCF->CreateInstance(NULL, IID_IUnknown, (void**)ppUnk);
        }
    }
    return hr;
}
进一步

HRESULT hr = 0;
IUnknown *ppUnk = 0;
ULONG lRef = 0;    
hr = CreateObjectFromPath(L"lame.ax", CLSID_LAMEDShowFilter, (IUnknown **)&ppUnk);
hr = ppUnk->QueryInterface(&m_pFilter);
lRef = ppUnk->Release();
它工作得很好。LAME编码音频

我想显示筛选器设置-属性页,但此代码失败

bool ShowConfigWindow(HWND hParent)
{
    ISpecifyPropertyPages *pProp;
    HRESULT hr = m_pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
    if (SUCCEEDED(hr))
    {
        // Get the filter's name and IUnknown pointer.
        FILTER_INFO FilterInfo;
        hr = m_pFilter->QueryFilterInfo(&FilterInfo);
        IUnknown *pFilterUnk;
        m_pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);

        // Show the page. 
        CAUUID caGUID;
        pProp->GetPages(&caGUID);
        pProp->Release();
        HRESULT hr = OleCreatePropertyFrame(
            hParent,                   // Parent window
            0, 0,                   // Reserved
            FilterInfo.achName,     // Caption for the dialog box
            1,                      // Number of objects (just the filter)
            &pFilterUnk,            // Array of object pointers. 
            caGUID.cElems,          // Number of property pages
            caGUID.pElems,          // Array of property page CLSIDs
            0,                      // Locale identifier
            0, NULL                 // Reserved
        );

        // Clean up.
        pFilterUnk->Release();
        FilterInfo.pGraph->Release();
        CoTaskMemFree(caGUID.pElems);
    }
    return true;
}
我发现

我应该为每个属性页调用CoRegisterClassObject,但是怎么做呢?
或者正确的方法是什么?

OleCreatePropertyFrame采用属性页类标识符(CLSID),因此您需要找到一种方法使它们对API“可见”

使用
CoRegisterClassObject
是实现上述任务的方法之一(也许最简单,另一种方法是reg free COM)。您需要检索属性页CLSID的
IClassFactory
指针,方法与在第一个代码段中相同。然后使用接口指针作为
CoRegisterClassObject
API的参数,而不是调用
IClassFactory::CreateInstance
。确保在与以下调用相同的线程上执行此操作
CoRevokeClassObject
将在事后清理