Icon Extraction with Fallback System
Overview
The ExtractIconFromImageres
method provides a robust icon extraction system that automatically falls back to embedded resources when imageres.dll
is not available. This ensures your application always has access to essential system icons, particularly UAC shield icons.
How It Works
Primary Method: imageres.dll
The method first attempts to extract icons directly from Windows' imageres.dll
:
// Primary extraction from imageres.dll
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Medium);
Fallback System: Embedded Resources
If imageres.dll
is unavailable or the icon extraction fails, the system automatically falls back to embedded resources:
// Automatic fallback to embedded resources if imageres.dll fails
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield);
// This will work even if imageres.dll is not available
Available Fallback Icons
Currently Supported Icons
- Shield (
PI.ImageresIconID.Shield
) - UAC shield icon - ShieldAlt (
PI.ImageresIconID.ShieldAlt
) - Alternative UAC shield icon
OS-Specific Resources
The fallback system uses OS-specific embedded resources:
Windows Version | Resource File | Available Sizes |
---|---|---|
Windows 11 | Windows11UACShieldIconResources |
16x16, 20x20, 24x24, 32x32, 40x40, 48x48, 64x64, 256x256 |
Windows 10 | Windows10UACShieldIconResources |
16x16, 20x20, 24x24, 32x32, 40x40, 48x48, 64x64, 256x256 |
Windows 7/8.x | Windows7And8xUACShieldIconResources |
8x8, 16x16, 24x24, 32x32, 48x48, 64x64, 128x128, 256x256 |
Windows Vista | WindowsVistaUACShieldIconResources |
8x8, 16x16, 24x24, 32x32, 48x48, 128x128, 256x256 |
Size Mapping
Exact Size Matching
The system first tries to find an exact size match in the embedded resources:
// Exact size match - uses 32x32 resource directly
var icon32 = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Medium);
Size Approximation
If an exact size isn't available, the system uses the closest available size:
// Size approximation examples:
// 8x8 request → uses 16x16 resource (scaled down)
// 96x96 request → uses 64x64 resource (scaled up)
// 192x192 request → uses 256x256 resource (scaled down)
Size Mapping Table
Requested Size | Windows 11/10 | Windows 7/8.x | Windows Vista |
---|---|---|---|
8x8 | 16x16 (scaled) | 8x8 | 8x8 |
16x16 | 16x16 | 16x16 | 16x16 |
20x20 | 20x20 | 24x24 (scaled) | 24x24 (scaled) |
24x24 | 24x24 | 24x24 | 24x24 |
32x32 | 32x32 | 32x32 | 32x32 |
40x40 | 40x40 | 48x48 (scaled) | 48x48 (scaled) |
48x48 | 48x48 | 48x48 | 48x48 |
64x64 | 64x64 | 64x64 | 32x32 (scaled) |
96x96 | 64x64 (scaled) | 64x64 (scaled) | 128x128 (scaled) |
128x128 | 64x64 (scaled) | 128x128 | 128x128 |
192x192 | 256x256 (scaled) | 256x256 (scaled) | 256x256 (scaled) |
256x256 | 256x256 | 256x256 | 256x256 |
Usage Examples
Basic Usage (Automatic Fallback)
// This will work regardless of imageres.dll availability
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Medium);
// Use the icon
if (shieldIcon != null)
{
button.Image = shieldIcon.ToBitmap();
shieldIcon.Dispose(); // Remember to dispose
}
Error Handling
public Image? GetSafeShieldIcon(IconSize size = IconSize.Medium)
{
try
{
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, size);
return icon?.ToBitmap();
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to extract shield icon: {ex.Message}");
return null;
}
}
OS-Aware Usage
// The fallback automatically uses the correct OS-specific icon
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres(PI.ImageresIconID.Shield);
// On Windows 11: Uses Windows 11 shield design
// On Windows 10: Uses Windows 10 shield design
// On Windows 7: Uses Windows 7 shield design
// On Windows Vista: Uses Windows Vista shield design
Performance Considerations
Resource Loading
- Embedded resources are loaded from the assembly, not from disk
- No network access required for fallback icons
- Fast loading compared to disk-based resources
Memory Management
// Always dispose of icons when done
using var icon = GraphicsExtensions.ExtractIconFromImageres(PI.ImageresIconID.Shield);
if (icon != null)
{
button.Image = icon.ToBitmap();
}
// Icon is automatically disposed here
Caching Strategy
private static readonly Dictionary<IconSize, Image> _iconCache = new();
public static Image? GetCachedShieldIcon(IconSize size)
{
if (!_iconCache.ContainsKey(size))
{
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, size);
_iconCache[size] = icon?.ToBitmap();
}
return _iconCache[size];
}
Common Scenarios
UAC Shield Buttons
// Create an "Run as Administrator" button
var adminButton = new KryptonButton();
adminButton.Text = "Run as Administrator";
// This will work even in environments where imageres.dll is not available
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Small);
if (shieldIcon != null)
{
adminButton.Image = shieldIcon.ToBitmap();
shieldIcon.Dispose();
}
Security Dialogs
// Use shield icon for security dialogs
var securityForm = new KryptonForm();
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Medium);
if (shieldIcon != null)
{
securityForm.Icon = shieldIcon;
shieldIcon.Dispose();
}
Toolbar Icons
// Add shield icon to toolbar
var toolbar = new KryptonToolStrip();
var shieldButton = new KryptonToolStripButton();
var shieldIcon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, IconSize.Small);
if (shieldIcon != null)
{
shieldButton.Image = shieldIcon.ToBitmap();
shieldIcon.Dispose();
}
toolbar.Items.Add(shieldButton);
Troubleshooting
Icon Not Found
// Check if icon extraction failed
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield);
if (icon == null)
{
// Both imageres.dll and fallback resources failed
Debug.WriteLine("Shield icon extraction failed completely");
// Use a default icon or handle gracefully
}
Size Not Available
// Check available sizes for debugging
var sizes = UACShieldHelper.GetAvailableImageresSizes();
Debug.WriteLine($"Available imageres.dll sizes: {string.Join(", ", sizes.Select(s => $"{s.Width}x{s.Height}"))}");
Performance Issues
// For frequently used icons, cache them
private static Image? _cachedShieldIcon;
public static Image GetShieldIcon()
{
if (_cachedShieldIcon == null)
{
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield);
_cachedShieldIcon = icon?.ToBitmap();
icon?.Dispose();
}
return _cachedShieldIcon;
}
Best Practices
1. Always Check for Null
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield);
if (icon != null)
{
// Use the icon
button.Image = icon.ToBitmap();
icon.Dispose();
}
else
{
// Handle the case where both imageres.dll and fallback failed
button.Image = Properties.Resources.DefaultShield;
}
2. Dispose Icons Properly
// Use using statement for automatic disposal
using var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield);
if (icon != null)
{
button.Image = icon.ToBitmap();
}
3. Cache Frequently Used Icons
// Cache icons to avoid repeated extraction
private static readonly Dictionary<IconSize, Image> _shieldIconCache = new();
public static Image GetShieldIcon(IconSize size)
{
if (!_shieldIconCache.ContainsKey(size))
{
var icon = GraphicsExtensions.ExtractIconFromImageres((int)PI.ImageresIconID.Shield, size);
_shieldIconCache[size] = icon?.ToBitmap();
icon?.Dispose();
}
return _shieldIconCache[size];
}
4. Handle Theme Changes
// Clear cache when theme changes
KryptonManager.GlobalPaletteChanged += (sender, e) =>
{
_shieldIconCache.Clear(); // Force re-extraction
RefreshShieldIcons();
};
Benefits
1. Reliability
- Always works - No dependency on external files
- Graceful degradation - Falls back automatically
- Cross-platform - Works in different deployment scenarios
2. Performance
- Fast loading - Embedded resources load quickly
- No disk access - Resources are in memory
- Efficient caching - Can cache frequently used icons
3. Consistency
- OS-specific - Uses appropriate design for each Windows version
- Theme-aware - Integrates with Krypton theming system
- Professional appearance - Maintains visual quality
4. Developer Experience
- Simple API - Same method call regardless of fallback
- Automatic handling - No manual fallback logic needed
- Comprehensive documentation - Clear usage guidelines
Summary
The ExtractIconFromImageres
method with fallback system provides:
- Robust icon extraction from
imageres.dll
with automatic fallback - OS-specific embedded resources for UAC shield icons
- Automatic size mapping and approximation
- Performance optimization through caching and efficient loading
- Professional appearance that matches the Windows design language
This system ensures your application always has access to essential system icons, providing a consistent and professional user experience across different deployment environments.