Reputation: 5090
I've been trying to get string representation of HICON. I was able to get the HICON from here. I'm able to save it to a file using this answer. I know I can save to to a temp file and read and get the bytes, but I want to directly convert the stream into byte array. When I do a IStream::Read
or IStream_Read
, I consistently get Zero bytes. Can you tell me what I'm doing wrong or point me to some documentation on the same?
The following is the code that I've been working on:
std::wstring get_str(HICON hIcon) {
// Create the IPicture intrface
PICTDESC desc = {sizeof(PICTDESC)};
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture *pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void **)&pPicture);
if (FAILED(hr)) return L"Erorr creating empty pic";
// Create a stream and save the image
IStream *pStream = 0;
// Use SHCreateMemStream?
// https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shcreatememstream
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr)) {
HGLOBAL hBuf = 0;
std::wstring ret;
char buffer[4096];
hr = IStream_Read(pStream, &buffer, cbSize);
if (FAILED(hr))
return L"Uneven reading from buffer"; // + std::to_wstring(cbSize) + L" " + std::to_wstring(read_size);
return L"Success"; // std::wstring(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return L"Fail fail fail";
}
Upvotes: 1
Views: 437
Reputation: 5090
@SimonMourier Gave the answer in the comments. For anyone looking for code:
std::wstring get_str(HICON hIcon) {
// Create the IPicture interface
PICTDESC desc = {sizeof(PICTDESC)};
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
// Create an ATL smart pointer.
CComPtr<IPicture> pPicture;
LONG cbSize = 0;
BYTE buffer[4096];
// Create a Smart pointer stream and save the image
IStreamPtr pStream;
if (FAILED(OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void **)&pPicture))) {
LOG_EXCEPTION(L"Unable to create an empty image");
return L"";
}
// Use SHCreateMemStream?
// https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shcreatememstream
if (FAILED(CreateStreamOnHGlobal(0, TRUE, &pStream))) {
LOG_EXCEPTION(L"Unable to create stream for icon.");
return L"";
}
if (FAILED(pPicture->SaveAsFile(pStream, TRUE, &cbSize))) {
LOG_EXCEPTION(L"Error saving as IPicture.");
return L"";
}
if (IStream_Reset(pStream) != S_OK) {
LOG_EXCEPTION(L"Error Seeking");
return L"";
}
if (IStream_Read(pStream, &buffer, cbSize) != S_OK) {
LOG_EXCEPTION(L"Uneven reading from buffer.");
return L"";
}
std::vector<BYTE> data(buffer, buffer + (cbSize / sizeof(BYTE)));
// Here some function could be type conversion or post processing
std::wstring ans = some_function(data);
return ans;
}
Upvotes: 0
Reputation: 3890
You need to seek the stream's read position to the beginning of the stream after saving and before reading.
The following code works for me:
std::wstring get_str(HICON hIcon) {
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return L"Erorr creating empty pic";
// Create a stream and save the image
IStream* pStream;
// Use SHCreateMemStream?
// https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shcreatememstream
if (SUCCEEDED(CreateStreamOnHGlobal(0, TRUE, &pStream)))
{
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
LARGE_INTEGER li;
li.HighPart = 0;
li.LowPart = 0;
HRESULT hrr = pStream->Seek(li, STREAM_SEEK_SET, NULL);
// Write the stream content to the file
if (SUCCEEDED(hr)) {
HGLOBAL hBuf = 0;
std::wstring ret;
char buffer[4096] = "";
ULONG ll = 0;
hr = pStream->Read(buffer, cbSize, &ll);
if (FAILED(hr))
{
pStream->Release();
pPicture->Release();
return L"Uneven reading from buffer"; // + std::to_wstring(cbSize) + L" " + std::to_wstring(read_size);
}
pStream->Release();
pPicture->Release();
return L"Success"; // std::wstring(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
}
else
{
pPicture->Release();
return L"Fail fail fail";
}
}
Upvotes: 2