2017-08-24 2 views
1

Je peux créer une Uint8array dans une fenêtre IWebBrowser2:IWebBrowser2: L'utilisation d'un Uint8array (remplissage sans looping)

IHTMLWindow2 window = ...; 
DISPID dispid_uint8array = ...; 

VARIANT self; 
self.vt = VT_NULL; 

VARIANT length; 
length.vt = VT_I4; 
length.lVal = 100; 

VARIANT args[2] = { self, length }; 
DISPID named_args[1] = { DISPID_THIS }; 

DISPPARAMS params; 
params.rgvarg = args; 
params.rgdispidNamedArgs = named_args; 
params.cArgs = 2; 
params.cNamedArgs = 1; 

VARIANT result; 
result.vt = VT_EMPTY; 
HRESULT hr = container->Invoke(
    dispid_uint8array, IID_NULL, LOCALE_USER_DEFAULT, 
    DISPATCH_METHOD, &params, &result, nullptr, nullptr 
); 

assert(hr == S_OK); 
assert(result.vt == VT_DISPATCH); 

IDispatch my_new_uint8array = result.pdispVal; 

Maintenant, je peux définir des éléments de champs my_new_uint8array en utilisant IDispatch::Invoke(..., DISPATCH_PROPERTYPUT, ...) dans une boucle.

Mais n'y a-t-il pas une interface appropriée pour remplir tout le tampon avec un seul appel? Par exemple. puis-je en quelque sorte récupérer le tampon contenu?

Existe-t-il une définition de l'interface quelque part, quelque chose comme IUint8Array?

+0

Ces tableaux ne sont-ils pas plus javascript (chakra)? https://docs.microsoft.com/en-us/scripting/chakra-hosting/jscreatetypedarray-function Je suis curieux de savoir comment obtenez-vous dispid_uint8array en premier lieu? –

+0

@SimonMourier, j'ai simplement utilisé 'window-> GetIDsOfNames (...)' en fournissant '' Uint8Array ''. – kay

+0

Auriez-vous un projet de reproduction prêt, par hasard? –

Répondre

1

Je suis venu avec un hack incroyablement moche: Utilisation du ArrayBuffer d'un <canvas>. Je ne posterai le code pseudo, parce que le plein C++, y compris la vérification des erreurs, déballant etc, est tout simplement trop long:

Prelude:

  • FEATURE_BROWSER_EMULATION a été mis à 11001
  • IWebBrowser2::get_ReadyState retours READYSTATE_COMPLETE
  • IHTMLDocument6::get_documentMode retours 11
  • IHTMLDocument5::get_compatMode retours "CSS1Compat"
  • IHTMLDocument2 *doc et IHTMLWindow2 *win sont définies. J'utilise des chaînes simples dans mon pseudo code, mais il faut bien sûr utiliser BSTR s!
  • Vous devrez peut-être queryInterface une ou deux fois, de sorte que les résultats correspondent.
  • Ne pas ignorer les erreurs!

Comment obtenir un "Uint8Array":

ULONG len_in_dwords = (LENGTH_I_WANT + 3)/4; 

IHTMLCanvasElement *canvas = doc->createElement("canvas"); 
ICanvasRenderingContext2D *context = canvas->getContext("2d"); 
ICanvasPixelArrayData *array_data = context->createImageData(len_in_dwords, 1); 

// use this variable for interfaces that accept an ArrayBuffer 
IDispatch *array_buffer = Get property "buffer" of array_data; 

// use this variable to edit the content: 
BYTE *byte_buffer; 
ULONG buffer_length_in_bytes; 
array_data->GetBufferPointer(&byte_buffer, &buffer_length_in_bytes); 

// no need for that anymore: 
canvas->Release(); 
context->Release(); 
array_data->Release(); 

Le ArrayBuffer array_buffer a toujours une taille divisible par quatre. Cela fonctionne pour moi, mais pourrait ne pas fonctionner pour d'autres cas d'utilisation. Vous pouvez utiliser la méthode slice(0, LENGTH_I_WANT) pour supprimer les octets supplémentaires après memcpy'ing à byte_buffer.