问题
Where, in Windows, is this icon stored? I need to use it in a TaskDialog emulation for XP and am having a hard time tracking it down.
It's not in shell32.dll, explorer.exe, ieframe.dll or wmploc.dll (as these contain a lot of icons commonly used in Windows).
Edit: For clarification, I am emulating a certain type of dialog in XP. The icon is (most likely) not present there. So I want to extract it from the library that holds it in Windows 7. I am extending an existing implementation of this emulation and want to provide a full feature set.
回答1:
I wanted to point it out explicitly.
You are supposed to put a shield on UI elements that will trigger an elevation: MSDN: Step 4: Redesign Your UI for UAC Compatibility.
Of course, you don't have to go spelunking around DLLs to extract images (although it certainly does make it easier at design time when you can design your design with a design time interface).
Microsoft provides a couple of supported (and therefore guaranteed) ways that you can get ahold of the shield icon at runtime:
Add a shield icon to the user interface?:
Extract a small icon
SHSTOCKICONINFO sii; sii.cbSize = sizeof(sii); SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &sii); hiconShield = sii.hIcon;
Extract a large icon
SHSTOCKICONINFO sii; sii.cbSize = sizeof(sii); SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_LARGEICON, &sii); hiconShield = sii.hIcon;
Extract an icon of custom size
SHSTOCKICONINFO sii; sii.cbSize = sizeof(sii); SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii); hiconShield = ExtractIconEx(sii. ...);
Add a Shield Icon to a Button
Button_SetElevationRequiredState(hwndButton, TRUE);
The article forgot to mention LoadIcon:
hIconShield = LoadIcon(0, IDI_SHIELD);
Although LoadIcon has been "superseded" by LoadImage:
hIconShield = LoadImage(0, IDI_SHIELD, IMAGE_ICON, desiredWith, desiredHeight, LR_SHARED); //passing LR_SHARED causes size to be ignored. And you must pass LR_SHARED
Loading the size you want - by avoiding shared images
In order to avoid loading a "shared" version of the icon, you have to load the icon directly out of the file.
We all know that the shield exists in user32.dll
as resource id 106
:
| Icon | Standard Icon ID | Real Resource ID |
|------------------|-------------------|------------------|
| IDI_APPLICATION | 32512 | 100 |
| IDI_QUESTION | 32514 | 102 |
| IDI_WINLOGO | 32517 | 105 |
| IDI_WARNING | 32515 | 101 |
| IDI_ERROR | 32513 | 103 |
| IDI_INFORMATION | 32516 | 104 |
| IDI_SHIELD | 32518 | 106 |
That was undocumented spellunking.
SHGetStockIconInfo can give us the actual, current, guaranteed to change in the future, path and index:
TSHStockIconInfo sii;
ZeroMemory(@sii, SizeOf(sii));
sii.cbSize := SizeOf(sii);
SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, {var}sii);
resulting in:
- sii.szPath:
C:\WINDOWS\System32\imageres.dll
- sii.iIcon:
-78
You can load this image for the size you desire using LoadImage
:
HMODULE hmod := LoadLibrary(sii.szPath);
Integer nIconIndex := Abs(sii.iIcon); //-78 --> 78
ico = LoadImage(hmod, MAKEINTRESOURCE(nIconIndex), IMAGE_ICON, 256, 256, 0);
Another slightly easier way is to use SHDefExtractIcon
:
HICON GetStockIcon(DWORD StockIconID, Integer IconSize)
{
HRESULT hr;
TSHStockIconInfo sii;
ZeroMemory(@sii, SizeOf(sii));
sii.cbSize := SizeOf(sii);
hr = SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, {var}sii);
OleCheck(hr);
HICON ico;
hr = SHDefExtractIcon(sii.szPath, sii.iIcon, 0, ref ico, null, IconSize);
OleCheck(hr);
return ico;
}
It does the loading for you, and it handles the negative icon index (and the secret meaning that has):
HICON shieldIcon = GetStockIcon(SIID_SHIELD, 256);
Personally, i then use WIC to wrap that into a IWICBitmap:
IWICBitmap GetStockWicBitmap(DWORD StockIconID, Integer IconSize)
{
HICON ico = GetStockIcon(StockIconID, IconSize);
IWICBitmap bitmap;
IWICImagingFactory factory = new WICImagingFactory();
HRESULT hr = factory.CreateBitmapFromHICON(ico, out bitmap);
OleCheck(hr);
return bitmap;
}
and so:
IWICBitmap bmp = GetStockWicBitmap(SIID_SHIELD, 256);
Now that you have the bitmap, at runtime, do with it what you want.
Small and Large
The problem with ExtractIconEx
is that you're again stuck with the two shell sizes:
- "small" (i.e.
GetSystemMetrics(SM_CXSMICON)
) - "large" (i.e.
GetSystemMetrics(SM_CXICON)
)
Loading icons is something that is quite a dark art in Windows:
- LoadIcon
- LoadImage
- LoadImage(..., LR_SHARED)
- ExtractIcon
- ExtractIconEx
- IExtractImage
- SHDefExtractIcon
- SHGetFileInfo(..., SHGFI_ICON, ...);
- SHGetFileInfo(..., SHGFI_SYSICONINDEX, ...);
- SHGetFileInfo(..., SHGFI_ICONLOCATION, ...);
- IThumbnailProvider
Icons available through SHGetStockIconInfo
Microsoft gives a handy page that gives an example, and description, of all the stock icons.
- SHSTOCKICONID (archive)
And the 256px shield icon (as of Windows 10):
回答2:
The shield icon is located in the file C:\Windows\System32\imageres.dll
(at least, in my copy of English 32-bit Windows 7). There are several versions of the shield icon there, including the blue and yellow version you have above (icon 78).
回答3:
Icons extracted from Windows 7 x64 SP1 English:
16x16 shield icon:
24x24 shield icon:
32x32 shield icon:
回答4:
You are asking the wrong question. It doesn't matter where this icon is stored on any version of windows. If Microsoft don't tell you then you should not use it - it might not be there in windows 8 (or whatever comes after 7).
If you want the icon so bad, there is a decent graphical representation of it above in this question. You could do alt-prt scrn then use your favourite graphics app to turn it into an icon and add it to your app. This may not be legal though (remember, IANAL)
来源:https://stackoverflow.com/questions/2798922/storage-location-of-yellow-blue-shield-icon