[英]Win32 COM Programming in Plain C
如何使用純 C 正確實現多個 COM 接口? 如果我們查看CommonFileDialog 示例,我們會看到事件處理程序的聲明是這樣的:
class CDialogEventHandler : public IFileDialogEvents,
public IFileDialogControlEvents
{...};
該類實現了IFileDialogEvents
和IFileDialogControlEvents
的方法。 哪個是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.