2017-07-29 2 views
1

J'essaie d'implémenter une fonction wrapper pour que la fonction API EnumWindows soit incluse dans mon dll wrapper, elle peut donc être utilisée avec de nombreux langages de script. En premier lieu, j'ai dû le tester en utilisant VBScript. J'ai implémenté une fonction wrapper et une fonction callback pour EnumWindows à l'aide de mes recherches utiles, mais ça ne marche pas comme je le veux.ATL COM - La fonction de rappel EnumWindows ne fonctionne pas avec IDispatch :: Invoke

Voici le code que j'ai actuellement:

fonctions wrapper pour EnumWindows et EnumWindowsProc rappel:

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 structure:

typedef struct tagENUMWINDOWSPARAMS { 
    LPDISPATCH DISPATCH; 
    LPVARIANT lParam; 
    VARIANT CallbackResult; 
} ENUMWINDOWSPARAMS, *PENUMWINDOWSPARAMS, *LPENUMWINDOWSPARAMS; 

Voici les tests VBScript Je suis en train de en utilisant:

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) 

Une chose fonctionne, EnumWindows est de retour True. Mais, au lieu de ce que j'attends, je ne reçois pas les poignées de fenêtres en écho. Et quand j'appelle GetLastError, il renvoie ERROR_SUCCESS.

Merci d'avance pour votre aide.

Répondre

1

je résolu le problème, fait rien de spécial, il est seulement un petit changement:

Changé le type de varArgsCComVariant-VARIANT comme ceci:

VARIANT varArgs[2] = { vResult, vhWnd }; 

Changé DISPPARAMS comme ci-dessous:

DISPPARAMS Parameters = {}; 
Parameters.cArgs = 2; 
Parameters.rgvarg = varArgs; 

Invoke La méthode est toujours la même:

pewParams->DISPATCH->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &Parameters, &vResult, NULL, NULL); 

Toutes les bonnes suggestions sont en outre appréciées.