[英]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.