Vasantha Ganesh
Vasantha Ganesh

Reputation: 5090

How to read HICON into a wchar array?

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

Answers (2)

Vasantha Ganesh
Vasantha Ganesh

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

Zeus
Zeus

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

Related Questions