Sign in to follow this  
Followers 0
unexpectedpanda

[SOLVED] High resolution, high DPI sysmenu, taskbar, alt+tab icons?

7 posts in this topic

#1 ·  Posted (edited)

Hi all,

I've been doing some work on a MacBook Pro with Retina Display, and so have been toying with high DPI interfaces (~200% dpi) and ?do=embed' frameborder='0' data-embedContent> to make sure things are nice and sharp.

The last barrier appears to be window icons used at the top left of the application. I've done a fair bit of searching about icons on the forums, but although there have been references here and there to blurry icons or telling AutoIt specifically what icon to use within the .ICO file, so far I haven't found a solution that's quite fit.

Posted Image

As you can see, the desktop icon is great, so is the tray icon, but the window icon at the top left is scaled up and blurry. Native Windows apps don't seem to have this issue. Any hints of how to correct this would be very much welcome. I've uploaded some sample code here, as well as the .ico file that I'm using (374KB ZIP). It's just sample code to illustrate the point, it's not meant to be a functional GUI.

You'll likely need to compile with the ?do=embed' frameborder='0' data-embedContent> to be able to see everything at properly sharp high DPI levels, rather than blurry DWM scaling ("Go" (F5) doesn't work for high DPI, you have to compile (F7)... I'm guessing I'd need access to the aut2exe code to modify that behaviour).

Here's the code I'm currently using (also in the ZIP):

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=beta
#AutoIt3Wrapper_Icon=cnet.ico
#AutoIt3Wrapper_Outfile=test.exe
#AutoIt3Wrapper_Res_Description=test
#AutoIt3Wrapper_Res_Fileversion=0.992.0.0
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#AutoIt3Wrapper_Res_Compatibility=Windows7
#AutoIt3Wrapper_Res_HiDpi=1
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

TraySetIcon(@ScriptDir & "\cnet.ico",1)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <_GetDPI.au3>

Opt("GUIOnEventMode", 1)

$a1 = _GetDPI()
$iDPIRat = $a1[2]
$FormMainGUI = GUICreate("test", 450 * $iDPIRat, 190 * $iDPIRat)
GuiSetIcon(@ScriptDir & "\cnet.ico",1,$FormMainGUI)
$Administratorlbl = GUICtrlCreateLabel("You MUST be signed into an administrative account before running installation",0,85 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($Administratorlbl,0x777777)
GuiCtrlSetFont($Administratorlbl,7,400)
$btnAutomated = GuiCtrlCreateButton("Prepare system and install benchmarks",25 * $iDPIRat,105 * $iDPIRat,400 * $iDPIRat,41 * $iDPIRat)
$TipLabel = GUICtrlCreateLabel("Press CTRL + ALT + Q to quit the script at any time, CTRL + ALT + G to enter GOD MODE", 0,160 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($TipLabel,0x777777)
GUICtrlSetFont($Tiplabel,7,400)
GUISetState(@SW_SHOW,$FormMainGUI)
GUISetOnEvent($GUI_EVENT_CLOSE,"CloseGui")
Sleep(10000)

;**************************************************
;Kill the Program

Func CloseGui()
Exit
EndFunc

Thanks,

Unexpectedpanda

Edited by unexpectedpanda

Share this post


Link to post
Share on other sites



insteed GUISetIcon try this _GUISetIcon function:

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

That seems to work well for the referenced shell32.dll, no dice for the included .ico though. Here's the code I tried below, still getting a blurry icon -- guessing I'm not referencing properly?

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=beta
#AutoIt3Wrapper_Icon=cnet.ico
#AutoIt3Wrapper_Outfile=test2.exe
#AutoIt3Wrapper_Res_Description=test
#AutoIt3Wrapper_Res_Fileversion=0.992.0.0
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#AutoIt3Wrapper_Res_Compatibility=Windows7
#AutoIt3Wrapper_Res_HiDpi=1
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

TraySetIcon(@ScriptDir & "\cnet.ico",1)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <_GetDPI.au3>

Opt("GUIOnEventMode", 1)

$a1 = _GetDPI()
$iDPIRat = $a1[2]
$FormMainGUI = GUICreate("test", 450 * $iDPIRat, 190 * $iDPIRat)
_GUISetIcon($FormMainGUI, @ScriptDir & "\cnet.ico", 1); name and not ordinal value
$Administratorlbl = GUICtrlCreateLabel("You MUST be signed into an administrative account before running installation",0,85 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($Administratorlbl,0x777777)
GuiCtrlSetFont($Administratorlbl,7,400)
$btnAutomated = GuiCtrlCreateButton("Prepare system and install benchmarks",25 * $iDPIRat,105 * $iDPIRat,400 * $iDPIRat,41 * $iDPIRat)
$TipLabel = GUICtrlCreateLabel("Press CTRL + ALT + Q to quit the script at any time, CTRL + ALT + G to enter GOD MODE", 0,160 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($TipLabel,0x777777)
GUICtrlSetFont($Tiplabel,7,400)
GUISetState(@SW_SHOW,$FormMainGUI)
GUISetOnEvent($GUI_EVENT_CLOSE,"CloseGui")
Sleep(10000)

;**************************************************
;Kill the Program

Func CloseGui()
Exit
EndFunc

;***************************************************
;Set high-res window icons

Func _GUISetIcon($hGui, $sModule, $iName); this for loaded modules in this shape

    Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "wstr", $sModule)

    Local $hModule = $a_hCall[0]

    $a_hCall = DllCall("user32.dll", "hwnd", "LoadImageW", _
            "hwnd", $hModule, _
            "int", $iName, _
            "dword", 1, _; IMAGE_ICON
            "int", 32, _
            "int", 32, _
            "dword", 0); LR_DEFAULTCOLOR

    Local $hIcon = $a_hCall[0]

    DllCall("user32.dll", "hwnd", "SendMessageW", _
            "hwnd", $hGui, _
            "dword", 0x0080, _; WM_SETICON
            "dword", 1, _; 1 = ICON_BIG, 0 = ICON_SMALL
            "hwnd", $hIcon)

EndFunc  ;==>_GUISetIcon
Edited by unexpectedpanda

Share this post


Link to post
Share on other sites

Try this, it should load successfully the main icon "99" of your exe with 32x32 pixel.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=beta
#AutoIt3Wrapper_Icon=cnet.ico
#AutoIt3Wrapper_Outfile=test2.exe
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Res_Description=test
#AutoIt3Wrapper_Res_Fileversion=0.992.0.0
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#AutoIt3Wrapper_Res_Compatibility=Windows7
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_HiDpi=1

TraySetIcon(@ScriptDir & "\cnet.ico",1)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <_GetDPI.au3>

Opt("GUIOnEventMode", 1)

$a1 = _GetDPI()
$iDPIRat = $a1[2]
$FormMainGUI = GUICreate("test", 450 * $iDPIRat, 190 * $iDPIRat)
_GUISetIcon($FormMainGUI, "", 99); name and not ordinal value
$Administratorlbl = GUICtrlCreateLabel("You MUST be signed into an administrative account before running installation",0,85 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($Administratorlbl,0x777777)
GuiCtrlSetFont($Administratorlbl,7,400)
$btnAutomated = GuiCtrlCreateButton("Prepare system and install benchmarks",25 * $iDPIRat,105 * $iDPIRat,400 * $iDPIRat,41 * $iDPIRat)
$TipLabel = GUICtrlCreateLabel("Press CTRL + ALT + Q to quit the script at any time, CTRL + ALT + G to enter GOD MODE", 0,160 * $iDPIRat,450 * $iDPIRat,20 * $iDPIRat,$SS_CENTER)
GuiCtrlSetColor($TipLabel,0x777777)
GUICtrlSetFont($Tiplabel,7,400)
GUISetState(@SW_SHOW,$FormMainGUI)
GUISetOnEvent($GUI_EVENT_CLOSE,"CloseGui")
Sleep(10000)

;**************************************************
;Kill the Program

Func CloseGui()
Exit
EndFunc

;***************************************************
;Set high-res window icons

Func _GUISetIcon($hGui, $sModule, $iName); this for loaded modules in this shape

IF $sModule = "" Then
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "ptr", 0)
Else
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "wstr", $sModule)
EndIf

Local $hModule = $a_hCall[0]

$a_hCall = DllCall("user32.dll", "hwnd", "LoadImageW", _
"hwnd", $hModule, _
"int", $iName, _
"dword", 1, _; IMAGE_ICON
"int", 32, _
"int", 32, _
"dword", 0); LR_DEFAULTCOLOR

Local $hIcon = $a_hCall[0]

DllCall("user32.dll", "hwnd", "SendMessageW", _
"hwnd", $hGui, _
"dword", 0x0080, _; WM_SETICON
"dword", 1, _; 1 = ICON_BIG, 0 = ICON_SMALL
"hwnd", $hIcon)

EndFunc ;==>_GUISetIcon

Share this post


Link to post
Share on other sites

Ah wonderful, it works, thank you so much! So now it's referencing the icon with the resource name "99" in the file itself -- fancy :)

Adding this to the source:

;Special thanks to JFX for making the high res icon code work from TranceXX

:)

Share this post


Link to post
Share on other sites

New complication: I set different sized icons for different levels of DPI scaling, which now properly scales the tray and window icons. Sadly, the ALT+TAB and tray icons (which are much larger images) are now scaling incorrectly, as they're using the smaller sizes I've set for the window icon.

As an interesting aside, calling MsgBox scales the icon perfectly for the taskbar (although displays nothing on ALT+TAB).

Don't know if it's possible to separate the window icon from ALT-TAB and Tray? I'm afraid the DLL calling stuff is a little beyond me at this stage!

Func _GUISetIcon($hGui, $sModule, $iName); this for loaded modules in this shape
If $sModule = "" Then
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "ptr", 0)
Else
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "wstr", $sModule)
EndIf
Local $hModule = $a_hCall[0]
If $a1[1] >= 96 and $a1[1] < 120 Then $iconsize = 16
If $a1[1] >= 120 and $a1[1] < 144 Then $iconsize = 20
If $a1[1] >= 144 and $a1[1] < 192 Then $iconsize = 24
If $a1[1] >= 192 Then $iconsize = 32
$a_hCall = DllCall("user32.dll", "hwnd", "LoadImageW", _
"hwnd", $hModule, _
"int", $iName, _
"dword", 1, _; IMAGE_ICON
"int", $iconsize, _
"int", $iconsize, _
"dword", 0); LR_DEFAULTCOLOR
Local $hIcon = $a_hCall[0]
DllCall("user32.dll", "hwnd", "SendMessageW", _
"hwnd", $hGui, _
"dword", 0x0080, _; WM_SETICON
"dword", 1, _; 1 = ICON_BIG, 0 = ICON_SMALL
"hwnd", $hIcon)
EndFunc ;==>_GUISetIcon

Share this post


Link to post
Share on other sites

So this took much, much longer to figure out than I care to admit, but here's what fixed all the icons for me up to 200% DPI, with independent scaling of taskbar/ALT+TAB icons and the sysmenu icon. I'm sure you can do that DLL call in one go but I'm not yet experienced enough to figure out how to do so.

;**************************************************
;Window icon resizing
;**************************************************
;Version 1.1 | Last updated 29 August 2012
;
; Special thanks to JFX, TranceXX, ProgAndy, guinness and Yashied,
; whose separate coding efforts enabled this
;
;--------------------------------------------------

;***************************************************
;Set high-res window icons

Func _GUISetIcon($hGui, $sModule, $iName); this for loaded modules in this shape
If $sModule = "" Then
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "ptr", 0)
Else
Local $a_hCall = DllCall("kernel32.dll", "hwnd", "GetModuleHandleW", "wstr", $sModule)
EndIf

Local $hModule = $a_hCall[0]

If $a1[1] >= 96 and $a1[1] < 120 Then
$iconsize = 16
$tasksize = 32
EndIf
If $a1[1] >= 120 and $a1[1] < 144 Then
$iconsize = 20
$tasksize = 48
EndIf

If $a1[1] >= 144 and $a1[1] < 192 Then
$iconsize = 24
$tasksize = 48
EndIf

If $a1[1] >= 192 Then
$iconsize = 32
$tasksize = 256
EndIf

$a_hCall = DllCall("user32.dll", "hwnd", "LoadImageW", _
"hwnd", $hModule, _
"int", $iName, _
"dword", 1, _; IMAGE_ICON
"int", $iconsize, _ ;x width
"int", $iconsize, _ ;y height
"dword", 0); LR_DEFAULTCOLOR

Local $hIcon = $a_hCall[0]

DllCall("user32.dll", "hwnd", "SendMessageW", _
"hwnd", $hGui, _
"dword", 0x0080, _; WM_SETICON
"dword", 0, _; 1 = ICON_BIG, 0 = ICON_SMALL
"hwnd", $hIcon)

$a_hCall = DllCall("user32.dll", "hwnd", "LoadImageW", _
"hwnd", $hModule, _
"int", $iName, _
"dword", 1, _; IMAGE_ICON
"int", $tasksize, _ ;x width
"int", $tasksize, _ ;y height
"dword", 0); LR_DEFAULTCOLOR

Local $hIcon = $a_hCall[0]

DllCall("user32.dll", "hwnd", "SendMessageW", _
"hwnd", $hGui, _
"dword", 0x0080, _; WM_SETICON
"dword", 1, _; 1 = ICON_BIG, 0 = ICON_SMALL
"hwnd", $hIcon)
EndFunc ;==>_GUISetIcon

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0