The code that worked for me:
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 }
    };
    return QISearch(this, qit, riid, ppv);
}
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 }
    };
    return QISearch(this, qit, riid, ppv);
}
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;
}