繁体   English   中英

普通 C 语言中的 Win32 COM 编程

[英]Win32 COM Programming in Plain C

如何使用纯 C 正确实现多个 COM 接口? 如果我们查看CommonFileDialog 示例,我们会看到事件处理程序的声明是这样的:

class CDialogEventHandler : public IFileDialogEvents,
                            public IFileDialogControlEvents
{...};

该类实现了IFileDialogEventsIFileDialogControlEvents的方法。 哪个是CDialogEventHandler的正确vTable ,我应该如何在 C 中实现QueryInterface 我知道使用 C++ 更合适,但我需要用 C 来做。

对我有用的代码:

typedef struct CDialogEventHandler
{
    const IFileDialogEventsVtbl* lpVtbl1;
    const IFileDialogControlEventsVtbl* lpVtbl2;
    long _cRef;
}CDialogEventHandler;

// IUnknown methods
IFACEMETHODIMP QueryInterface_IFileDialogEvents(IFileDialogEvents* this, REFIID riid, void** ppv)
{
    static const QITAB qit[] = 
    {
        QITABENT(CDialogEventHandler, IFileDialogEvents),
        {&IID_IFileDialogControlEvents, sizeof(void*)},
        { 0 }
    };
    HRESULT hr = QISearch(this, qit, riid, ppv);
    if (SUCCEEDED(hr)) this->lpVtbl->AddRef(this);
    return hr;
}

IFACEMETHODIMP_(ULONG) AddRef_IFileDialogEvents(IFileDialogEvents* this)
{
    return InterlockedIncrement(&(((CDialogEventHandler*)this)->_cRef));
}

IFACEMETHODIMP_(ULONG) Release_IFileDialogEvents(IFileDialogEvents* this)
{
    long cRef = InterlockedDecrement(&(((CDialogEventHandler*)this)->_cRef));
    if (!cRef) free(this);
    return cRef;
}

IFACEMETHODIMP QueryInterface_IFileDialogControlEvents(IFileDialogControlEvents* this, REFIID riid, void** ppv)
{
    this = ((BYTE*)this) - sizeof(void*);
    static const QITAB qit[] = {
        QITABENT(CDialogEventHandler, IFileDialogEvents),
        {&IID_IFileDialogControlEvents, sizeof(void*)},
        { 0 }
    };
    HRESULT hr = QISearch(this, qit, riid, ppv);
    if (SUCCEEDED(hr)) this->lpVtbl->AddRef(this);
    return hr;
}

IFACEMETHODIMP_(ULONG) AddRef_IFileDialogControlEvents(IFileDialogControlEvents* this)
{
    this = ((BYTE*)this) - sizeof(void*);
    return InterlockedIncrement(&(((CDialogEventHandler*)this)->_cRef));
}

IFACEMETHODIMP_(ULONG) Release_IFileDialogControlEvents(IFileDialogControlEvents* this)
{
    this = ((BYTE*)this) - sizeof(void*);
    long cRef = InterlockedDecrement(&(((CDialogEventHandler*)this)->_cRef));
    if (!cRef) free(this);
    return cRef;
}
//implementation of the remaining functions
...
//Creation of the object
static const IFileDialogEventsVtbl vtbl1 =
{
    //IUnknown
    .AddRef = AddRef_IFileDialogEvents,
    .QueryInterface = QueryInterface_IFileDialogEvents,
    .Release = Release_IFileDialogEvents,

    //IFileDialogEvents
    .OnFileOk = _OnFileOk,
    .OnFolderChange = _OnFolderChange,
    .OnFolderChanging = _OnFolderChanging,
    .OnSelectionChange = _OnSelectionChange,
    .OnShareViolation = _OnShareViolation,
    .OnTypeChange = _OnTypeChange,
    .OnOverwrite = _OnOverwrite,
};
static const IFileDialogControlEventsVtbl vtbl2 =
{
    //IUnknown
    .AddRef = AddRef_IFileDialogControlEvents,
    .QueryInterface = QueryInterface_IFileDialogControlEvents,
    .Release = Release_IFileDialogControlEvents,

    //IFileDialogControlEvents
    .OnItemSelected = _OnItemSelected,
    .OnControlActivating = _OnControlActivating,
    .OnButtonClicked = _OnButtonClicked,
    .OnCheckButtonToggled = _OnCheckButtonToggled,
};

CDialogEventHandler* InitCDialogEventHandler()
{
    CDialogEventHandler* h = malloc(sizeof(CDialogEventHandler));
    if (!h) return NULL;
    h->lpVtbl1 = &vtbl1;
    h->lpVtbl2 = &vtbl2;
    h->_cRef = 1;
    return h;
}
    

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM