IWebbrowser2: использование массива Uint8 (заполнение без зацикливания)

Я могу создать массив Uint8 в окне IWebbrowser2:

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;

Теперь я могу установить элементы полей my_new_uint8array с помощью IDispatch::Invoke(..., DISPATCH_PROPERTYPUT, ...) в петле.

Но не существует ли надлежащего интерфейса для заполнения всего буфера одним вызовом? Например. я могу как-то получить содержащийся буфер?

Где-то есть определение интерфейса, что-то вроде IUint8Array?

1

Решение

Я придумал невероятно уродливый хак: использование ArrayBuffer <canvas>, Я буду публиковать только псевдокод, потому что полный C ++, включая проверку ошибок, распаковку и т. Д., Слишком длинный:

Прелюдия:

  • FEATURE_BROWSER_EMULATION был установлен на 11001
  • IWebBrowser2::get_ReadyState возвращается READYSTATE_COMPLETE
  • IHTMLDocument6::get_documentMode возвращается 11
  • IHTMLDocument5::get_compatMode возвращается "CSS1Compat"
  • IHTMLDocument2 *doc а также IHTMLWindow2 *win установлены.
  • Я использую простые строки в своем псевдокоде, но вы должны использовать BSTRконечно!
  • Возможно, вам придется queryInterface один или два раза, чтобы результаты соответствовали.
  • Не игнорируйте ошибки!

Как получить «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();

ArrayBuffer array_buffer всегда имеет размер, кратный четырем. Это работает для меня, но может не работать для других случаев использования. Ты можешь использовать array_bufferметод slice(0, LENGTH_I_WANT) удалить лишние байты после memcpy’ing byte_buffer,

1

Другие решения

Других решений пока нет …