Я хочу добавить специальные возможности к своему пользовательскому элементу управления Windows, и, поскольку мне все еще нужно поддерживать все версии Windows XP, я должен использовать MSAA. (Я понимаю, что некоторые люди будут думать, что именно мы должны отталкивать людей от XP, создавая несовместимое программное обеспечение. Лично я этого не понимаю, но это не относится к делу). Этот элемент управления написан на C, поэтому я использую CINTERFACE
.
Я написал необходимые заглушки и просто хочу убедиться, что он компилируется нормально. Однако мои вызовы IsEqualIID()
и LresultFromObject()
жалуются, что IID_IUnknown
, IID_IDispatch
и IID_IAccessible
не являются допустимыми REFIID
, а просто обычными GUID
без указателя:
In file included from /usr/share/mingw-w64/include/winnt.h:602:0,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
accessibility.h: In function ‘tableAccQueryInterface’:
accessibility.h:13:6: error: incompatible type for argument 2 of ‘memcmp’
if (IsEqualIID(riid, IID_IUnknown) ||
^
In file included from /usr/share/mingw-w64/include/guiddef.h:148:0,
from /usr/share/mingw-w64/include/winnt.h:602,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
/usr/share/mingw-w64/include/string.h:40:15: note: expected ‘const void *’ but argument is of type ‘GUID’
int __cdecl memcmp(const void *_Buf1,const void *_Buf2,size_t _Size);
^
In file included from /usr/share/mingw-w64/include/winnt.h:602:0,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
accessibility.h:14:3: error: incompatible type for argument 2 of ‘memcmp’
IsEqualIID(riid, IID_IDispatch) ||
^
In file included from /usr/share/mingw-w64/include/guiddef.h:148:0,
from /usr/share/mingw-w64/include/winnt.h:602,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
/usr/share/mingw-w64/include/string.h:40:15: note: expected ‘const void *’ but argument is of type ‘GUID’
int __cdecl memcmp(const void *_Buf1,const void *_Buf2,size_t _Size);
^
In file included from /usr/share/mingw-w64/include/winnt.h:602:0,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
accessibility.h:15:3: error: incompatible type for argument 2 of ‘memcmp’
IsEqualIID(riid, IID_IAccessible)) {
^
In file included from /usr/share/mingw-w64/include/guiddef.h:148:0,
from /usr/share/mingw-w64/include/winnt.h:602,
from /usr/share/mingw-w64/include/minwindef.h:146,
from /usr/share/mingw-w64/include/windef.h:8,
from /usr/share/mingw-w64/include/windows.h:69,
from main.c:13:
/usr/share/mingw-w64/include/string.h:40:15: note: expected ‘const void *’ but argument is of type ‘GUID’
int __cdecl memcmp(const void *_Buf1,const void *_Buf2,size_t _Size);
^
accessibility.h:259:13: error: incompatible type for argument 1 of ‘LresultFromObject’
*lResult = LresultFromObject(IID_IAccessible, wParam, t->ta);
^
In file included from main.c:22:0:
/usr/share/mingw-w64/include/oleacc.h:109:20: note: expected ‘const struct IID * const’ but argument is of type ‘GUID’
STDAPI_(LRESULT) LresultFromObject(REFIID riid,WPARAM wParam,LPUNKNOWN punk);
^
Я не понимаю, почему. Практически каждый фрагмент кода, который я нашел, просто использует эти переменные IID напрямую; нет &
или что-то в этом роде. Поиск в Google также не помогает; на самом деле он показал мне код, который использует &
! Это как-то связано с CINTERFACE
? Я делаю что-то еще не так?
(Я знаю, что, скорее всего, нарушу здесь кучу правил COM; я просто хочу убедиться, что все компилируется нормально.)
Используя mingw-w64, который поставляется с Ubuntu GNOME 14.10.
Спасибо.
// 24 december 2014
struct tableAcc {
IAccessibleVtbl vtbl;
ULONG refcount;
struct table *t;
};
static HRESULT STDMETHODCALLTYPE tableAccQueryInterface(IAccessible *this, REFIID riid, void **ppvObject)
{
if (ppvObject == NULL)
return E_POINTER;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_IDispatch) ||
IsEqualIID(riid, IID_IAccessible)) {
*ppvObject = (void *) this;
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
#define TA ((struct tableAcc *) this)
// TODO use InterlockedIncrement()/InterlockedDecrement() for these?
static ULONG STDMETHODCALLTYPE tableAccAddRef(IAccessible *this)
{
TA->refcount++;
return TA->refcount;
}
static ULONG STDMETHODCALLTYPE tableAccRelease(IAccessible *this)
{
TA->refcount--;
if (TA->refcount == 0) {
free(TA);
return 0;
}
return TA->refcount;
}
// disregard IDispatch: http://msdn.microsoft.com/en-us/library/windows/desktop/cc307844.aspx
// TODO DISP_E_MEMBERNOTFOUND? http://blogs.msdn.com/b/saraford/archive/2004/08/20/which-controls-support-which-msaa-properties-and-how-these-controls-implement-msaa-properties.aspx
static HRESULT STDMETHODCALLTYPE tableAccGetTypeInfoCount(IAccessible *this, UINT *pctinfo)
{
if (pctinfo == NULL)
return E_INVALIDARG;
// TODO assign something to *pctinfo?
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE tableAccGetTypeInfo(IAccessible *this, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
if (ppTInfo == NULL)
return E_INVALIDARG;
*ppTInfo = NULL;
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE tableAccGetIDsOfNames(IAccessible *this, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
// TODO verify this one
if (rgDispId == NULL)
return E_INVALIDARG;
// TODO overwrite rgDispId?
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE tableAccInvoke(IAccessible *this, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
// TODO check this one
return E_NOTIMPL;
}
// IAccessible
static HRESULT STDMETHODCALLTYPE tableAccget_accParent(IAccessible *this, IDispatch **ppdispParent)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accChildCount(IAccessible *this, long *pcountChildren)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accChild(IAccessible *this, VARIANT varChild, IDispatch **ppdispChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accName(IAccessible *this, VARIANT varChild, BSTR *pszName)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accValue(IAccessible *this, VARIANT varChild, BSTR *pszValue)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accDescription(IAccessible *this, VARIANT varChild, BSTR *pszDescription)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accRole(IAccessible *this, VARIANT varChild, VARIANT *pvarRole)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accState(IAccessible *this, VARIANT varChild, VARIANT *pvarState)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accHelp(IAccessible *this, VARIANT varChild, BSTR *pszHelp)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accHelpTopic(IAccessible *this, BSTR *pszHelpFile, VARIANT varChild, long *pidTopic)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accKeyboardShortcut(IAccessible *this, VARIANT varChild, BSTR *pszKeyboardShortcut)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accFocus(IAccessible *this, VARIANT *pvarChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accSelection(IAccessible *this, VARIANT *pvarChildren)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccget_accDefaultAction(IAccessible *this, VARIANT varChild, BSTR *pszDefaultAction)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccaccSelect(IAccessible *this, long flagsSelect, VARIANT varChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccaccLocation(IAccessible *this, long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccaccNavigate(IAccessible *this, long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccaccHitTest(IAccessible *this, long xLeft, long yTop, VARIANT *pvarChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccaccDoDefaultAction(IAccessible *this, VARIANT varChild)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccput_accName(IAccessible *this, VARIANT varChild, BSTR szName)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static HRESULT STDMETHODCALLTYPE tableAccput_accValue(IAccessible *this, VARIANT varChild, BSTR szValue)
{
// TODO
return DISP_E_MEMBERNOTFOUND;
}
static const IAccessibleVtbl tableAccVtbl = {
.QueryInterface = tableAccQueryInterface,
.AddRef = tableAccAddRef,
.Release = tableAccRelease,
.GetTypeInfoCount = tableAccGetTypeInfoCount,
.GetTypeInfo = tableAccGetTypeInfo,
.GetIDsOfNames = tableAccGetIDsOfNames,
.Invoke = tableAccInvoke,
.get_accParent = tableAccget_accParent,
.get_accChildCount = tableAccget_accChildCount,
.get_accChild = tableAccget_accChild,
.get_accName = tableAccget_accName,
.get_accValue = tableAccget_accValue,
.get_accDescription = tableAccget_accDescription,
.get_accRole = tableAccget_accRole,
.get_accState = tableAccget_accState,
.get_accHelp = tableAccget_accHelp,
.get_accHelpTopic = tableAccget_accHelpTopic,
.get_accKeyboardShortcut = tableAccget_accKeyboardShortcut,
.get_accFocus = tableAccget_accFocus,
.get_accSelection = tableAccget_accSelection,
.get_accDefaultAction = tableAccget_accDefaultAction,
.accSelect = tableAccaccSelect,
.accLocation = tableAccaccLocation,
.accNavigate = tableAccaccNavigate,
.accHitTest = tableAccaccHitTest,
.accDoDefaultAction = tableAccaccDoDefaultAction,
.put_accName = tableAccput_accName,
.put_accValue = tableAccput_accValue,
};
static struct tableAcc *newTableAcc(struct table *t)
{
struct tableAcc *ta;
ta = (struct tableAcc *) malloc(sizeof (struct tableAcc)); ZeroMemory(ta, sizeof (struct tableAcc));
ta->vtbl = tableAccVtbl;
ta->vtbl.AddRef(ta);
ta->t = t;
return ta;
}
static void freeTableAcc(struct tableAcc *ta)
{
ta->t = NULL;
ta->vtbl.Release(ta);
}
static BOOL accessibilityHandler(struct table *t, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
if (uMsg != WM_GETOBJECT)
return FALSE;
if (wParam != OBJID_CLIENT)
return FALSE;
*lResult = LresultFromObject(IID_IAccessible, wParam, t->ta);
// TODO check *lResult
return TRUE;
}
Заголовки (включены в другой файл, который включает в себя выше):
// 19 october 2014
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#define CINTERFACE
// get Windows version right; right now Windows XP
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
#include <windows.h>
#include <commctrl.h>
#include <stdint.h>
#include <uxtheme.h>
#include <string.h>
#include <wchar.h>
#include <windowsx.h>
#include <vsstyle.h>
#include <vssym32.h>
#include <oleacc.h>
REFIID
из C вам нужен оператор & для передачи адреса. - person Raymond Chen   schedule 25.12.2014REFIID
меняется в зависимости от того, компилируете ли вы для C или C++. - person Raymond Chen   schedule 25.12.2014LresultFromObject()
(именно это я имел в виду под перегрузкой), а не определение типаREFIID
. - person andlabs   schedule 25.12.2014