簡體   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