In the Windows Volume Mixer, when your application plays sounds, it adds your application's icon and a custom volume slider to adjust volume specific to that application... nice! However, when you use a large-sized icon for your application (especially important in high-DPI when Windows scales your icons for the Taskbar, etc.), the icon in the Volume Mixer doesn't scale correctly. Specifically, the following code is what I use to set the application's icon:
// set icons the normal way
cWnd.SetIcon( theApp.LoadIcon( res_id ), FALSE );
cWnd.SetIcon( theApp.LoadIcon( res_id ), TRUE );
// set hi-res if available
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof( osv );
if ( GetVersionEx( &osv ) ) {
// if we're Vista or more recent, use hi-def icons
if ( osv.dwMajorVersion >= 6 ) {
HICON hIcon = (HICON)::LoadImage( theApp.m_hInstance, MAKEINTRESOURCE( res_id ), IMAGE_ICON, 256, 256, LR_SHARED );
if ( hIcon ) {
cWnd.SetIcon( hIcon, TRUE );
}
}
}
The culprit is the "hi-res if available" part. If I include that, the Taskbar icon looks great but the Volume Mixer isn't scaled and looks terrible. If I exclude that, the Taskbar icon looks bad (terrible scaling) but the Volume Mixer at least is the right size:
Has anyone found a solution that makes it so that BOTH icons look good?
EDIT: In my icon file, I have the following resolutions: 256x256, 48x48, 32x32, 24x24, and 16x16, all 32-bit. The 256x256 one is PNG compressed, the others are raw. All of the sizes look great at the resolutions they are in the file (I was trying to put the ICO here or in imgur but apparently neither allow icons). Additionally I have tried including some 8-bit images but that doesn't seem to change things.
EDIT: I'm using GetDeviceCaps( hdc, LOGPIXELSX )
(and Y) to determine the Desktop scaling. Normally desktop scaling is 100% and I get the normal 96 result. But more and more I'm seeing computers default to 125%. This can be changed via right-click Desktop, Personalize, other: Display... there's a slider there (requires log out/in for change).
EDIT: I also want to point out that the Tray ICON suffers a similar scaling issue fate when in high-DPI modes (that is, when using Shell_NotifyIcon
). In this case, however, I'm able to use GetDeviceCaps( hdc, LOGPIXELSX )
to determine what Windows wants.. if I have the size, provide it directly, otherwise provide the 256x256 one and Windows does scale it correctly.
EDIT: Sadness ensues. This problem may be a Windows issue. While capturing images for demonstration purposes, I noticed the Volume Mixer icon itself looks poor. For comparison:
FINAL EDIT: As described below, the workaround for the issue is to scale the icons. So, the final code that works is to load a pointer to the LoadIconWithScaleDown
function from Comctl32.dll
(not shown) and use that if it was available, or fall back to the "regular/old" way:
HICON hIcon = 0;
if ( FAILED( comctl32Loader.LoadIconWithScaleDown( theApp.m_hInstance, MAKEINTRESOURCE( res_id ), GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), &hIcon ) ) ) {
hIcon = theApp.LoadIcon( res_id );
}
cWnd.SetIcon( hIcon, FALSE );
if ( FAILED( comctl32Loader.LoadIconWithScaleDown( theApp.m_hInstance, MAKEINTRESOURCE( res_id ), GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), &hIcon ) ) ) {
hIcon = theApp.LoadIcon( res_id );
}
cWnd.SetIcon( hIcon, TRUE );