6

On Windows 10 calling LoadIcon asking for the standard icon IDI_INFORMATION yields this icon:

enter image description here

On the other hand, calling MessageBox passing IDI_INFORMATION produces a dialog that uses this icon:

enter image description here

How can I obtain the second icon, if the obvious call to LoadIcon does not do so?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Andrey
  • 65
  • 5
  • I re-wrote the question to include images to make it more clear what you refer to, and to target the question at a broader winapi audience. Accordingly I removed language specific references since they don't seem pertinent. This is really a question about winapi and not the specific language used to access the API. I trust that is reasonable. – David Heffernan Jun 23 '17 at 11:10
  • MessageBox use `MAKEINTRESOURCE(81)` from `"imageres.dll"` - not sure that `81` resourse somehow documented. you can test this: `MSGBOXPARAMSW mbi = { sizeof(mbi), HWND_DESKTOP, LoadLibraryEx(L"imageres", 0, LOAD_LIBRARY_AS_DATAFILE), L"lpszText", L"lpszCaption", MB_USERICON, MAKEINTRESOURCE(81), }; MessageBoxIndirectW(&mbi);` – RbMm Jun 23 '17 at 11:27
  • and compare with `MSGBOXPARAMSW mbi = { sizeof(mbi), HWND_DESKTOP, 0, L"lpszText", L"lpszCaption", MB_USERICON, IDI_INFORMATION, }; MessageBoxIndirectW(&mbi);` – RbMm Jun 23 '17 at 11:28
  • Icon from 'LoadLibraryEx(L"imageres", 0, LOAD_LIBRARY_AS_DATAFILE)' exactly what i need. Thanks. The answer: 'LoadIconW(LoadLibraryEx('imageres', 0, LOAD_LIBRARY_AS_DATAFILE), MAKEINTRESOURCE(81));' – Andrey Jun 23 '17 at 12:07

2 Answers2

4

This feels like a bug in user32.dll but Windows 8 has the same issue so I guess Microsoft doesn't care.

You can get the flat icon used by MessageBox by calling SHGetStockIconInfo:

SHSTOCKICONINFO sii;
sii.cbSize = sizeof(sii);
if (SUCCEEDED(SHGetStockIconInfo(SIID_INFO, SHGSI_ICON|SHGSI_LARGEICON, &sii)))
{
    // Use sii.hIcon here...
    DestroyIcon(sii.hIcon);
}

SHGetStockIconInfo is the documented way to get icons used in the Windows UI on Vista and later. Most of the icons come from imageres.dll but you should not assume that this is the case...

Anders
  • 97,548
  • 12
  • 110
  • 164
0

we can try next code for test/demo

    MSGBOXPARAMSW mbi = { 
        sizeof(mbi), 
        HWND_DESKTOP, 
        NULL,
        L"lpszText",
        L"lpszCaption",
        MB_USERICON,
        IDI_INFORMATION
    };
    MessageBoxIndirectW(&mbi);

    if (HMODULE hmodImageRes = LoadLibraryEx(L"imageres", 0, LOAD_LIBRARY_AS_DATAFILE))
    {
        mbi.hInstance = hmodImageRes;
        mbi.lpszIcon = MAKEINTRESOURCE(81);
        MessageBoxIndirectW(&mbi);
        FreeLibrary(hmodImageRes);
    }

first message box use standard IDI_INFORMATION icon enter image description here

when second the same icon on windows 7, and enter image description here on windows 8.1 and windows 10.

are MAKEINTRESOURCE(81) from imageres.dll somehow documented and be stable - i doubt


so obtain the second icon you can by LoadIcon(hmodImageRes, MAKEINTRESOURCE(81)) where HMODULE hmodImageRes = LoadLibraryEx(L"imageres", 0, LOAD_LIBRARY_AS_DATAFILE) or simply LoadLibrary(L"imageres")

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • 2
    Why use implementation details when there is a documented function that gets the correct icon? – Anders Jun 23 '17 at 12:39
  • @Anders - agree, I simply look how MessageBox load icon, from which resource. however use `SHGetStockIconInfo` is much better. – RbMm Jun 23 '17 at 12:43
  • I failed trying to use `SHGetStockIconInfo` and worked with you method @RbMm. Now i understand how to use it right. – Andrey Jun 23 '17 at 13:50