ATL COM - EnumWindows 回调函数不适用于 IDispatch::Invoke
ATL COM - EnumWindows callback function not working with IDispatch::Invoke
我正在尝试为 EnumWindows
API 函数实现一个包装函数以包含在我的包装 dll 中,因此它可以与许多脚本语言一起使用。
首先,我必须使用 VBScript 对其进行测试。在我有用的研究的帮助下,我为 EnumWindows
实现了一个包装函数和一个回调函数,但它并没有像我想要的那样工作。
这是我目前拥有的代码:
EnumWindows
和 EnumWindowsProc
回调的包装函数:
BOOL CALLBACK EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam) {
LPENUMWINDOWSPARAMS pewParams;
VARIANT vhWnd, vResult; HRESULT HR = S_OK;
VariantInit(&vhWnd);
VariantInit(&vResult);
vhWnd.vt = VT_I4;
vhWnd.lVal = (LONG)(LONG_PTR)hWnd;
pewParams = reinterpret_cast<LPENUMWINDOWSPARAMS>(lParam);
// ^ PASSING MY PARAMETERS THROUGH LPARAM
CComVariant varArgs[2] = { &vResult, &vhWnd };
DISPPARAMS Parameters = { &varArgs[0], NULL, 2, 0 };
pewParams->DISPATCH->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &vResult, NULL, NULL);
// ^ I SUSPECT SOMETHING IS WRONG WITH THIS INVOKE METHOD. BUT IT RETURNS S_OK.
if (vResult.vt != VT_BOOL) { HR = DISP_E_TYPEMISMATCH; }
pewParams->CallbackResult.vt = VT_ERROR;
pewParams->CallbackResult.scode = HR;
if (HR == S_OK)
return (vResult.boolVal == VARIANT_TRUE ? TRUE : FALSE);
else
return FALSE;
}
STDMETHODIMP CWinAPI::WinAPI_EnumWindows(VARIANT EnumFunc, int lParam, int *Result) {
ENUMWINDOWSPARAMS ewParams; HRESULT HR = S_OK;
switch (EnumFunc.vt)
{
case VT_DISPATCH:
ewParams.DISPATCH = EnumFunc.pdispVal;
break;
case VT_VARIANT | VT_BYREF:
if (EnumFunc.pvarVal->vt == VT_DISPATCH) { ewParams.DISPATCH = EnumFunc.pvarVal->pdispVal; }
break;
default: return DISP_E_TYPEMISMATCH;
}
ewParams.lParam = reinterpret_cast<LPVARIANT>(&lParam);
*Result = (int)EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&ewParams));
HR = ewParams.CallbackResult.scode;
return HR;
}
ENUMWINDOWSPARAMS
结构:
typedef struct tagENUMWINDOWSPARAMS {
LPDISPATCH DISPATCH;
LPVARIANT lParam;
VARIANT CallbackResult;
} ENUMWINDOWSPARAMS, *PENUMWINDOWSPARAMS, *LPENUMWINDOWSPARAMS;
这是我目前使用的测试 VBScript:
Dim WINAPI: Set WINAPI = WScript.CreateObject("WinAPIWrapperLib.WINAPI")
Function EnumWindowsProc(HWND, lParam)
WScript.Echo "Handle to the window: 0x" + CStr(UCase(Hex(HWND)))
EnumWindowsProc = True
End Function
Dim Result: Result = WINAPI.WinAPI_EnumWindows(GetRef("EnumWindowsProc"), 0)
WScript.Echo "EnumWindows returned " + CStr(Result)
有一件事有效,EnumWindows
返回 True
。
但是,与我期望的相反,我没有得到 windows 的句柄回显。
当我调用 GetLastError
时,它 returns ERROR_SUCCESS
.
在此先感谢您的帮助。
我解决了这个问题,没什么特别的,只是一个小改动:
将 varArgs
的类型从 CComVariant
更改为 VARIANT
,如下所示:
VARIANT varArgs[2] = { vResult, vhWnd };
更改DISPPARAMS
如下:
DISPPARAMS Parameters = {};
Parameters.cArgs = 2;
Parameters.rgvarg = varArgs;
Invoke
方法还是一样:
pewParams->DISPATCH->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &vResult, NULL, NULL);
如有任何好的建议,我们将不胜感激。
我正在尝试为 EnumWindows
API 函数实现一个包装函数以包含在我的包装 dll 中,因此它可以与许多脚本语言一起使用。
首先,我必须使用 VBScript 对其进行测试。在我有用的研究的帮助下,我为 EnumWindows
实现了一个包装函数和一个回调函数,但它并没有像我想要的那样工作。
这是我目前拥有的代码:
EnumWindows
和 EnumWindowsProc
回调的包装函数:
BOOL CALLBACK EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam) {
LPENUMWINDOWSPARAMS pewParams;
VARIANT vhWnd, vResult; HRESULT HR = S_OK;
VariantInit(&vhWnd);
VariantInit(&vResult);
vhWnd.vt = VT_I4;
vhWnd.lVal = (LONG)(LONG_PTR)hWnd;
pewParams = reinterpret_cast<LPENUMWINDOWSPARAMS>(lParam);
// ^ PASSING MY PARAMETERS THROUGH LPARAM
CComVariant varArgs[2] = { &vResult, &vhWnd };
DISPPARAMS Parameters = { &varArgs[0], NULL, 2, 0 };
pewParams->DISPATCH->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &vResult, NULL, NULL);
// ^ I SUSPECT SOMETHING IS WRONG WITH THIS INVOKE METHOD. BUT IT RETURNS S_OK.
if (vResult.vt != VT_BOOL) { HR = DISP_E_TYPEMISMATCH; }
pewParams->CallbackResult.vt = VT_ERROR;
pewParams->CallbackResult.scode = HR;
if (HR == S_OK)
return (vResult.boolVal == VARIANT_TRUE ? TRUE : FALSE);
else
return FALSE;
}
STDMETHODIMP CWinAPI::WinAPI_EnumWindows(VARIANT EnumFunc, int lParam, int *Result) {
ENUMWINDOWSPARAMS ewParams; HRESULT HR = S_OK;
switch (EnumFunc.vt)
{
case VT_DISPATCH:
ewParams.DISPATCH = EnumFunc.pdispVal;
break;
case VT_VARIANT | VT_BYREF:
if (EnumFunc.pvarVal->vt == VT_DISPATCH) { ewParams.DISPATCH = EnumFunc.pvarVal->pdispVal; }
break;
default: return DISP_E_TYPEMISMATCH;
}
ewParams.lParam = reinterpret_cast<LPVARIANT>(&lParam);
*Result = (int)EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&ewParams));
HR = ewParams.CallbackResult.scode;
return HR;
}
ENUMWINDOWSPARAMS
结构:
typedef struct tagENUMWINDOWSPARAMS {
LPDISPATCH DISPATCH;
LPVARIANT lParam;
VARIANT CallbackResult;
} ENUMWINDOWSPARAMS, *PENUMWINDOWSPARAMS, *LPENUMWINDOWSPARAMS;
这是我目前使用的测试 VBScript:
Dim WINAPI: Set WINAPI = WScript.CreateObject("WinAPIWrapperLib.WINAPI")
Function EnumWindowsProc(HWND, lParam)
WScript.Echo "Handle to the window: 0x" + CStr(UCase(Hex(HWND)))
EnumWindowsProc = True
End Function
Dim Result: Result = WINAPI.WinAPI_EnumWindows(GetRef("EnumWindowsProc"), 0)
WScript.Echo "EnumWindows returned " + CStr(Result)
有一件事有效,EnumWindows
返回 True
。
但是,与我期望的相反,我没有得到 windows 的句柄回显。
当我调用 GetLastError
时,它 returns ERROR_SUCCESS
.
在此先感谢您的帮助。
我解决了这个问题,没什么特别的,只是一个小改动:
将 varArgs
的类型从 CComVariant
更改为 VARIANT
,如下所示:
VARIANT varArgs[2] = { vResult, vhWnd };
更改DISPPARAMS
如下:
DISPPARAMS Parameters = {};
Parameters.cArgs = 2;
Parameters.rgvarg = varArgs;
Invoke
方法还是一样:
pewParams->DISPATCH->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &vResult, NULL, NULL);
如有任何好的建议,我们将不胜感激。