Page 1 of 1

Obscure GUI Picture-related bug

Posted: 07 Mar 2018, 15:16
by jballi
Introduction
I came across these obscure GUI bugs quite by accident. I'm posting them here because I'm not sure that the bugs can be reproduced on other computers.

The Bugs
There are two bugs that I found but the problem may affect other GUI commands.

Bug 1: The "gui,Add" command sometimes does not correctly identify the size of an icon.

Bug 2: The GUIControl command sometimes does not correctly identify the size of an icon and (this is the part that alarms me) will sometimes change the size of the control when updating the contents.

Script

Code: Select all

#NoEnv
#SingleInstance Force
ListLines Off

;-- Initialize
File :="shell32.dll"

;-- Load and count files
ListOfIndexes :=""
Loop 306
    ListOfIndexes.=(A_Index>1 ? "|":"") . A_Index

;-- Choose a random Index
;;;;;Random RandomIndex,1,306
RandomIndex :=112

;-- Build GUI
gui -DPIScale -MinimizeBox

gui Add,Text,xm,16x16:
gui Add,Picture,xm y+1 vLP16,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w16 h16",IconType)

gui Add,Text,xm,24x24:
gui Add,Picture,xm y+1 vLP24,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w24 h24",IconType)

gui Add,Text,xm,32x32:
gui Add,Picture,xm y+1 vLP32,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w32 h32",IconType)

gui Add,Text,xm,48x48:
gui Add,Picture,xm y+1 vLP48,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w48 h48",IconType)

gui Add,Text,xm,64x64:
gui Add,Picture,xm y+1 vLP64,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w64 h64",IconType)
GUIControlGet LP64Pos,Pos,LP64
gui Add,Text,xm y+0 vLP64Size,Control size: %LP64PosW%x%LP64PosH%

gui Add,Text,xm,128x128:
gui Add,Picture,xm y+1 vLP128,% "HICON: " . LoadPicture(File,"Icon" . RandomIndex . " w128 h128",IconType)
GUIControlGet LP128Pos,Pos,LP128
gui Add,Text,xm y+0 vLP128Size,Control size: %LP128PosW%x%LP128PosH%

;;;;;gui Add,Picture,xm w128 h128 Icon115,Shell32.dll

gui Add,DropDownList,xm r12 Choose%RandomIndex% vDDL gUpdateIcons,%ListOfIndexes%

gui Add,Button,xm gReload Default,%A_Space% Reload... %A_Space%

;-- Show it
gui Show
GUIControl Focus,DDL
return


GUIEscape:
GUIClose:
ExitApp


Reload:
Reload
return


UpdateIcons:
gui Submit,NoHide
GUIControl,,LP16,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w16 h16",IconType)
GUIControl,,LP24,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w24 h24",IconType)
GUIControl,,LP32,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w32 h32",IconType)
GUIControl,,LP48,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w48 h48",IconType)
GUIControl,,LP64,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w64 h64",IconType)
GUIControlGet LP64Pos,Pos,LP64
GUIControl,,LP64Size,Control size: %LP64PosW%x%LP64PosH%
GUIControl,,LP128,% "HICON: " . LoadPicture(File,"Icon" . DDL . " w128 h128",IconType)
GUIControlGet LP128Pos,Pos,LP128
GUIControl,,LP128Size,Control size: %LP128PosW%x%LP128PosH%
return
Reproducing the Bugs
The bugs occur with icon index 115 of the "Shell32.dll" file. After the script starts, press the Down key to get to icon index 115. Once the images for icon index 115 are displayed, all other icons are displayed with the wrong size. The completely unexpected part is that the GUIControl command changes the size of the control when this bug occurs. And once the size of the control is changed to a smaller size, it is never changed back.

These bugs do not occur if the icon for index 115 is never shown. All of the icons are displayed as expected.

These bugs also occur if the image is loaded without the LoadPicture function. For example,

Code: Select all

gui Add,Picture,xm w128 h128 Icon115,Shell32.dll
Help
Like I said, I have no idea whether this bug can be reproduced on other computers. Please let me know either way.

Edit: This bug is occurring on my Win7 Pro machine. Let me know which Windows version you are running on. Thanks.

Re: Obscure GUI Picture-related bug

Posted: 08 Mar 2018, 04:34
by just me
Hi jballi,

I can confirm the issue on Win 10.

The icon group 115 of Shell32.dll contains only two icons:
  1. 32*32 (1 BPP)
  2. 32*32 (4 BPP)
Seemingly, the icons cannot be scaled properly for some reason. So the controls are resized to 32*32 automatically and keep this new size afterwards (for some reason). You can prevent the controls from resizing by specifying +0x0200 (SS_CENTERIMAGE). Specifying the control dimensions explicitely in the Gui, Add, ... commands does not work for me on its own, but you should do it to avoid such 'scaling errors', though.
Static Control Styles wrote:
SS_ICON:
The style ignores the CreateWindow parameters nWidth and nHeight; the control automatically sizes itself to accommodate the icon.

SS_CENTERIMAGE:
A bitmap is centered in the static control that contains it. The control is not resized, so that a bitmap too large for the control will be clipped.

Re: Obscure GUI Picture-related bug

Posted: 09 Mar 2018, 19:18
by jballi
Thanks for the feedback and for confirming that this occurs on other versions of Windows.

About the icons... There are several groups of icons in this dll with only 2 icons. There are also several groups with only 16x16 icons. In this dll, AutoHotkey only has a problem with the 115 icon.

About extracting/scaling... Other programs (Ex: PrivateExtractIcons) have no problem extracting the 115 icon and scaling it to requested size. Also, if the icon is loaded to an image list (Ex: IL_Add), the icon is scaled to the size of the images in the image list.

The thing that I thought was really odd is that the GUIControl command is resizing the Picture control when is only supposed to be updating the contents of the control. I guess this is happening because AutoHotkey is returning a 32x32 icon instead of an icon with the requested size (48x48, 64x64, etc.)

Anywho... obscure bugs that are reproducible but are very rare.

Re: Obscure GUI Picture-related bug

Posted: 10 Mar 2018, 04:22
by just me
Group 115 seems to be the only group in Shell32.dll containing only two icons of same size where the first one is monochrome. Obviously, AHK takes the monochrome icon in this case and fails to scale it properly.

Sample:

Code: Select all

#NoEnv
Mod := "Shell32.dll"
Icon := "#223"
IW := 128
IH := 128
HMOD := DllCall("LoadLibraryEx", "Str", Mod, "Ptr", 0, "UInt", 0x02, "UPtr")
; LoadImage() -> msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
HICON1 := DllCall("LoadImage", "Ptr", HMOD, "Str", Icon, "Int", 1, "Int", IW, "Int", IH, "UInt", 0x00002000, "UPtr")
; LoadIconWithScaleDown() -> msdn.microsoft.com/en-us/library/windows/desktop/bb775703(v=vs.85).aspx (Win Vista+)
DllCall("LoadIconWithScaleDown", "Ptr", HMOD, "Str", Icon, "Int", IW, "Int", IH, "PtrP", HICON2)
DllCall("FreeLibrary", "Ptr", HMOD)

Gui, Add, Picture, xm, HICON:%HICON1%
Gui, Add, Picture, xm, HICON:%HICON2%
Gui, Add, Picture, xm w128 h128 Icon115 vPic, Shell32.dll
GuiControlGet, Pic, Pos
Gui, Add, Text, xm, %PicW% * %PicH%
Gui, Show, w400 h400, Icon115
Return

GuiClose:
ExitApp
Related code in util.cpp:

Code: Select all

			for (int i = 1; i < resCount; ++i)
			{
				// Find the closest match for size, preferring the next larger icon if there's
				// no exact match.  Normally the system will just pick the closest size, but
				// at least for our icon, the 32x32 icon rendered at 20x20 looks much better
				// than the 16x16 icon rendered at 20x20 (i.e. small icon size for 125% DPI).
				if (resDir[i].Icon.Width > chosen->Icon.Width
					? chosen->Icon.Width < aWidth // Current icon smaller than desired, so up-size.
					: resDir[i].Icon.Width >= aWidth) // Current icon larger than desired, so down-size (without going below aWidth).
					chosen = &resDir[i];
			}
			if (   (hres = FindResource(hdatafile, MAKEINTRESOURCE(chosen->IconCursorId), RT_ICON))
				&& (hresdata = LoadResource(hdatafile, hres))
				&& (presdata = LockResource(hresdata))   )
			{
				hicon = CreateIconFromResourceEx((PBYTE)presdata, SizeofResource(hdatafile, hres), TRUE, 0x30000, 0, 0, 0);
			}
I call this a bug, too. Maybe the whole icon search in util.cpp could be replaced by LoadIconWithScaleDown() for Win Vista+.

Re: Obscure GUI Picture-related bug

Posted: 10 Mar 2018, 07:33
by just me
Additionally, the code from util.cpp posted above doesn't work for 256x256 icons, because

Code: Select all

resDir[i].Icon.Width
is zero in this case.

Re: Obscure GUI Picture-related bug

Posted: 10 Mar 2024, 12:04
by iPhilip
Looks like the issue for 256x256 icons has been addressed but the scaling issue is still not resolved in AHK v2.

Source code from util.cpp:

Code: Select all

			for (int i = 0; i < resCount; ++i)
			{
				int this_width = resDir[i].Icon.Width;
				if (!this_width) // Workaround for 256x256 icons.
					this_width = 256;
				// Find the closest match for size, preferring the next larger icon if there's
				// no exact match.  Normally the system will just pick the closest size, but
				// at least for our icon, the 32x32 icon rendered at 20x20 looks much better
				// than the 16x16 icon rendered at 20x20 (i.e. small icon size for 125% DPI).
				if (this_width > chosen_width
					? chosen_width < aWidth // Current icon smaller than desired, so up-size.
					: this_width >= aWidth) // This icon is closer to the desired size, so down-size.
				{
					chosen = &resDir[i];
					chosen_width = this_width;
				}
			}
Test code:

Code: Select all

#Requires AutoHotkey v2.0
MyGui := Gui(, 'Icons')
Pic1 := MyGui.Add('Picture', 'w128 h128 Icon115', 'Shell32.dll')
Pic1.GetPos(, , &Pic1W, &Pic1H)
MyGui.Add('Text', 'xm', Pic1W '*' Pic1H)
Pic2 := MyGui.Add('Picture', 'w256 h256 Icon116', 'Shell32.dll')
Pic2.GetPos(, , &Pic2W, &Pic2H)
MyGui.Add('Text', 'xm', Pic2W '*' Pic2H)
MyGui.Show('w400 h400')

Re: Obscure GUI Picture-related bug  Topic is solved

Posted: 22 Mar 2024, 20:12
by lexikos
It appears to be the case that LoadImage and CopyImage are unable to resize a monochrome icon. It doesn't seem worth coming up with another way to resize the icon, just to allow monochrome icons to scale.

The resizing issue is avoided for icon 115 in v2.0.12, as it no longer selects the monochrome icon.

Re: Obscure GUI Picture-related bug

Posted: 23 Mar 2024, 01:48
by iPhilip
Thank you. I appreciate the change.