[Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

Post your working scripts, libraries and tools.
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

[Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

17 Apr 2024, 10:05

Hi Folks,

There are many posts in the forum about ways to display an icon in the title bar of a MsgBox window. Some fail to destroy the created icon(s), leading to a memory leak. The function below addresses that problem. The icons are automatically destroyed shortly after the window is created.

Here is the function:

Code: Select all

; ===============================================================================================================================
; MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?)
; Function:       Displays a MsgBox window with an icon in the title bar.
; Parameters:     Text - (Optional) The text to be displayed in the MsgBox window. If omitted, it defaults to the default text
;                    of the MsgBox function.
;                 Title - (Optional) The title of the MsgBox window. If omitted, it defaults to A_ScriptName.
;                 Options - (Optional) A string of options for the built-in MsgBox function.
;                 IconFile - (Optional) The name of the icon file, e.g. A_AhkPath or 'shell32.dll'. If omitted, no icon will
;                    be displayed in the MsgBox window title bar.
;                 IconNumber - (Optional) The number of the icon group to use. If omitted, it defaults to 1. If IconFile is
;                    omitted, this parameter is ignored.
; Return values:  A string representing which button was pressed.
; Global vars:    None
; Depenencies:    None
; Requirements:   AHK v2.0
; Tested with:    AHK v2.0.0 (U32/U64)
; Tested on:      Win 10 Pro (x64)
; Written by:     iPhilip
; Forum link:     https://www.autohotkey.com/boards/viewtopic.php?f=83&t=128882
; References:     https://www.autohotkey.com/docs/v2/lib/MsgBox.htm
; ===============================================================================================================================

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      static PID := ProcessExist()
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      if !WinExist('ahk_class #32770 ahk_pid' PID)
         throw Error('Unable to detect window.', -1)
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      DetectHiddenWindows HiddenWindowsState
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      SetTimer () => DestroyIcon(hIconSmall), -100
      SetTimer () => DestroyIcon(hIconBig)  , -100
      
      DestroyIcon(hIcon) {
         if !DllCall('User32.dll\DestroyIcon', 'Ptr', hIcon, 'Int')
            throw Error('DestroyIcon failed.', -1)
      }
   }
}

Here is a self-contained example:

Code: Select all

#Requires AutoHotkey v2.0

MsgBoxTBI( , , 'T3')
MsgBoxTBI( , , 'T3', A_AhkPath)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 2)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 87)

; ===============================================================================================================================
; MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?)
; Function:       Displays a MsgBox window with an icon in the title bar.
; Parameters:     Text - (Optional) The text to be displayed in the MsgBox window. If omitted, it defaults to the default text
;                    of the MsgBox function.
;                 Title - (Optional) The title of the MsgBox window. If omitted, it defaults to A_ScriptName.
;                 Options - (Optional) A string of options for the built-in MsgBox function.
;                 IconFile - (Optional) The name of the icon file, e.g. A_AhkPath or 'shell32.dll'. If omitted, no icon will
;                    be displayed in the MsgBox window title bar.
;                 IconNumber - (Optional) The number of the icon group to use. If omitted, it defaults to 1. If IconFile is
;                    omitted, this parameter is ignored.
; Return values:  A string representing which button was pressed.
; Global vars:    None
; Depenencies:    None
; Requirements:   AHK v2.0
; Tested with:    AHK v2.0.0 (U32/U64)
; Tested on:      Win 10 Pro (x64)
; Written by:     iPhilip
; Forum link:     https://www.autohotkey.com/boards/viewtopic.php?f=83&t=128882
; References:     https://www.autohotkey.com/docs/v2/lib/MsgBox.htm
; ===============================================================================================================================

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      static PID := ProcessExist()
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      if !WinExist('ahk_class #32770 ahk_pid' PID)
         throw Error('Unable to detect window.', -1)
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      DetectHiddenWindows HiddenWindowsState
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      SetTimer () => DestroyIcon(hIconSmall), -100
      SetTimer () => DestroyIcon(hIconBig)  , -100
      
      DestroyIcon(hIcon) {
         if !DllCall('User32.dll\DestroyIcon', 'Ptr', hIcon, 'Int')
            throw Error('DestroyIcon failed.', -1)
      }
   }
}
I hope you find it useful.

- iPhilip

P.S.:The function name, MsgBoxTBI, stands for MsgBox with a Title Bar Icon.

EDIT: Simplified function and added error handling.
Last edited by iPhilip on 19 Apr 2024, 10:27, edited 4 times in total.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
kunkel321
Posts: 1107
Joined: 30 Nov 2015, 21:19

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 07:35

Cool idea. I'm getting errors though... I'm on Win 10 with RaptorX's AHKToolBox, to test your self contained example. It has AHK v2.0.2.

First two message boxes work, but there is no icon...
Third msgbox causes error:
Error: Expected a Number but got an empty string.

069: If wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd
069: {
? 070: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
071: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig, 'Int')
072: OnMessage(MsgNum, ShellMessage, 0)
Click 'continue' get:
Error: Expected a Number but got an empty string.

069: {
070: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
? 071: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig, 'Int')
072: OnMessage(MsgNum, ShellMessage, 0)
073: }
Click 'continue' get:
Critical Error: Invalid memory read/write.

070: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
071: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig, 'Int')
? 072: OnMessage(MsgNum, ShellMessage, 0)
073: }
074: }
I tried it multiple times... Oddly, I did see a MsgBox with an icon one time.
EDIT: My clipboard tool has turned the above arrows into question marks. Sorry about that.
ste(phen|ve) kunkel
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 09:58

kunkel321 wrote:
18 Apr 2024, 07:35
Cool idea. I'm getting errors though... I'm on Win 10 with RaptorX's AHKToolBox, to test your self contained example. It has AHK v2.0.2.

First two message boxes work, but there is no icon...
Third msgbox causes error:
@kunkel321 Thank you for reporting your tests. I went back and dowloaded earlier versions of AHK v2 and confirmed that it doesn't work with AHK v2.0.2 but works with AHK v2.0.3. I suspect that it has to do with this fix:
https://www.autohotkey.com/docs/v2/ChangeLog.htm#v2.0.3 wrote: Fixed inter-referenced closures being deleted prematurely.
I updated the original post to clarify that the function requires AHK v2.0.3+.

Thanks again for your help.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 11:29

@iPhilip, I'm having trouble with this also, AHK 2.0.12. Not getting icons in the title bars. No errors, just no icons.
Best regards,
burque505
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 12:35

@burque505 Sorry you are having trouble with the function.

Would you be willing to post the code you are using and take a look at the values of the hIconSmall and hIconBig variables, especially in the ShellMessage nested function?

Thank you.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 12:40

Sure, I just used the code you provided above. I'll check the vars. Back in a few.

Quick and very dirty, MsgBoxes for the var values.

Code: Select all

#Requires AutoHotkey v2.0

MsgBoxTBI( , , 'T3')
MsgBoxTBI( , , 'T3', A_AhkPath)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 2)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 87)

; ===============================================================================================================================
; MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?)
; Function:       Displays a MsgBox window with an icon in the title bar.
; Parameters:     Text - (Optional) The text to be displayed in the MsgBox window. If omitted, it defaults to the default text
;                    of the MsgBox function.
;                 Title - (Optional) The title of the MsgBox window. If omitted, it defaults to A_ScriptName.
;                 Options - (Optional) A string of options for the built-in MsgBox function.
;                 IconFile - (Optional) The name of the icon file, e.g. A_AhkPath or 'shell32.dll'. If omitted, no icon will
;                    be displayed in the MsgBox window title bar.
;                 IconNumber - (Optional) The number of the icon group to use. If omitted, it defaults to 1. If IconFile is
;                    omitted, this parameter is ignored.
; Return values:  A string representing which button was pressed.
; Global vars:    None
; Depenencies:    None
; Requirements:   AHK v2.0
; Tested with:    AHK v2.0.12 (U32/U64)
; Tested on:      Win 10 Pro (x64)
; Written by:     iPhilip
; Forum link:     https://www.autohotkey.com/boards/viewtopic.php?f=83&t=128882
; References:     https://www.autohotkey.com/docs/v2/lib/MsgBox.htm
; ===============================================================================================================================

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   static MsgNum := DllCall('User32.dll\RegisterShellHookWindow', 'Ptr', A_ScriptHwnd, 'Int')
                 && DllCall('User32.dll\RegisterWindowMessageW', 'WStr', 'SHELLHOOK', 'UInt')
   
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      MsgBox(hIconBig, "HIconBig")
      MsgBox(hIconSmall, "HIconSmaill")
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
      OnMessage MsgNum, ShellMessage
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      WinExist 'ahk_class #32770'
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      DetectHiddenWindows HiddenWindowsState
   }
   
   ShellMessage(wParam, lParam, *) {
      static HSHELL_WINDOWCREATED   := 1
      static HSHELL_WINDOWDESTROYED := 2
      static hwnd
      
      if wParam = HSHELL_WINDOWCREATED
         hwnd := lParam
      else if wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd {
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig,   'Int')
         OnMessage MsgNum, ShellMessage, 0
      }
   }
}
Sorry, didn't check inside the ShellMessage function. Back in a sec.
With this code I do get an error:
071: hwnd := lParam
072: Else
? 072: If wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd
072: {
073: DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')

Code: Select all

#Requires AutoHotkey v2.0

MsgBoxTBI( , , 'T3')
MsgBoxTBI( , , 'T3', A_AhkPath)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 2)
MsgBoxTBI( , , 'T3', 'DDORes.dll', 87)

; ===============================================================================================================================
; MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?)
; Function:       Displays a MsgBox window with an icon in the title bar.
; Parameters:     Text - (Optional) The text to be displayed in the MsgBox window. If omitted, it defaults to the default text
;                    of the MsgBox function.
;                 Title - (Optional) The title of the MsgBox window. If omitted, it defaults to A_ScriptName.
;                 Options - (Optional) A string of options for the built-in MsgBox function.
;                 IconFile - (Optional) The name of the icon file, e.g. A_AhkPath or 'shell32.dll'. If omitted, no icon will
;                    be displayed in the MsgBox window title bar.
;                 IconNumber - (Optional) The number of the icon group to use. If omitted, it defaults to 1. If IconFile is
;                    omitted, this parameter is ignored.
; Return values:  A string representing which button was pressed.
; Global vars:    None
; Depenencies:    None
; Requirements:   AHK v2.0
; Tested with:    AHK v2.0.12 (U32/U64)
; Tested on:      Win 10 Pro (x64)
; Written by:     iPhilip
; Forum link:     https://www.autohotkey.com/boards/viewtopic.php?f=83&t=128882
; References:     https://www.autohotkey.com/docs/v2/lib/MsgBox.htm
; ===============================================================================================================================

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   static MsgNum := DllCall('User32.dll\RegisterShellHookWindow', 'Ptr', A_ScriptHwnd, 'Int')
                 && DllCall('User32.dll\RegisterWindowMessageW', 'WStr', 'SHELLHOOK', 'UInt')
   
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      MsgBox(hIconBig, "HIconBig")
      MsgBox(hIconSmall, "HIconSmaill")
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
      OnMessage MsgNum, ShellMessage
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      WinExist 'ahk_class #32770'
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      DetectHiddenWindows HiddenWindowsState
   }
   
   ShellMessage(wParam, lParam, *) {
      static HSHELL_WINDOWCREATED   := 1
      static HSHELL_WINDOWDESTROYED := 2
      static hwnd
      MsgBox(hIconBig, "HIconBig inside ShellMessage")
      MsgBox(hIconSmall, "HIconSmaill inside ShellMessage")
      if wParam = HSHELL_WINDOWCREATED
         hwnd := lParam
      else if wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd {
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig,   'Int')
         OnMessage MsgNum, ShellMessage, 0
      }
   }
}
Commented out the ShellMessage MsgBoxes and no errors. The remaining message boxes all appear to contain pointer values, but I'm not sure.

Best regards,
burque505
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 17:54

@burque505 Thank you for your testing. From what you reported, it looks like LoadPicture is working. The fact that you don't see any icons suggests that you are not getting to the SetTitleBarIcon nested function.

I would appreciate it if you could run the following diagnostic code and report any errors or what is displayed in the final MsgBox:

Code: Select all

#Requires AutoHotkey v2.0.3+

StatusLog := A_TickCount '`n'
MsgBoxTBI( , , 'T1')
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', A_AhkPath)
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', 'DDORes.dll', 2)
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', 'DDORes.dll', 87)
MsgBox StatusLog

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   static MsgNum := DllCall('User32.dll\RegisterShellHookWindow', 'Ptr', A_ScriptHwnd, 'Int')
                 && DllCall('User32.dll\RegisterWindowMessageW', 'WStr', 'SHELLHOOK', 'UInt')
   
   global StatusLog
   SetTitleBarIconState := false
   ShellMessageState := false
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      if ImageType != 1  ; IMAGE_ICON
         throw Error('Unable to extract icon from resource.', -1, 'Small icon.')
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      if ImageType != 1  ; IMAGE_ICON
         throw Error('Unable to extract icon from resource.', -1, 'Big icon.')
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
      OnMessage MsgNum, ShellMessage
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      ; Critical
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      if !WinExist('ahk_class #32770')
         throw Error('There is no such window.', -1, 'ahk_class #32770')
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      DetectHiddenWindows HiddenWindowsState
      StatusLog .= A_TickCount '`tSetTitleBarIcon`n'
   }
   
   ShellMessage(wParam, lParam, *) {
      ; Critical
      static HSHELL_WINDOWCREATED   := 1
      static HSHELL_WINDOWDESTROYED := 2
      static hwnd
      
      if wParam = HSHELL_WINDOWCREATED {
         hwnd := lParam
         StatusLog .= A_TickCount '`tHSHELL_WINDOWCREATED`n'
      } else if wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd {
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig,   'Int')
         OnMessage MsgNum, ShellMessage, 0
         StatusLog .= A_TickCount '`tHSHELL_WINDOWDESTROYED`n'
      }
   }
}
I get the following on my machine:

Code: Select all

179182953

179184015	SetTitleBarIcon
179184031	HSHELL_WINDOWCREATED
179185015	HSHELL_WINDOWDESTROYED

179185031	SetTitleBarIcon
179185031	HSHELL_WINDOWCREATED
179186031	HSHELL_WINDOWDESTROYED

179186046	SetTitleBarIcon
179186062	HSHELL_WINDOWCREATED
179187046	HSHELL_WINDOWDESTROYED
If you don't get something like that, you might try to uncomment the two Critical statements in the SetTitleBarIcon and ShellMessage nested functions.

Thank you for your help.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
User avatar
kunkel321
Posts: 1107
Joined: 30 Nov 2015, 21:19

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 20:12

Getting a different error message with AHK v1.0.12
Maybe it's a "run as admin" problem?
Error: (5) Access is denied.

054: DetectHiddenWindows(true)
055: WinExist('ahk_class #32770')
▶ 056: SendMessage(WM_SETICON, ICON_SMALL, hIconSmall)
057: SendMessage(WM_SETICON, ICON_BIG, hIconBig)
058: OnMessage(WM_COMMNOTIFY, SetTitleBarIcon, 0)
ste(phen|ve) kunkel
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

18 Apr 2024, 23:31

kunkel321 wrote:
18 Apr 2024, 20:12
Getting a different error message with AHK v1.0.12
Maybe it's a "run as admin" problem?
Error: (5) Access is denied.

054: DetectHiddenWindows(true)
055: WinExist('ahk_class #32770')
▶ 056: SendMessage(WM_SETICON, ICON_SMALL, hIconSmall)
057: SendMessage(WM_SETICON, ICON_BIG, hIconBig)
058: OnMessage(WM_COMMNOTIFY, SetTitleBarIcon, 0)
Thank you for letting me know. It looks like WinExist is finding a window that is running at a higher integrity level than the script. Can you try the following and let me know if it makes a difference? Please post the output of the last MsgBox window so I can see what's happening.

Code: Select all

#Requires AutoHotkey v2.0.3+

StatusLog := A_TickCount '`n'
MsgBoxTBI( , , 'T1')
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', A_AhkPath)
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', 'DDORes.dll', 2)
StatusLog .= '`n'
MsgBoxTBI( , , 'T1', 'DDORes.dll', 87)
MsgBox StatusLog

MsgBoxTBI(Text?, Title?, Options?, IconFile?, IconNumber?) {
   static CXICON   := SysGet(11)
   static CYICON   := SysGet(12)
   static CXSMICON := SysGet(49)
   static CYSMICON := SysGet(50)
   static WM_COMMNOTIFY := 0x0044
   static MsgNum := DllCall('User32.dll\RegisterShellHookWindow', 'Ptr', A_ScriptHwnd, 'Int')
                 && DllCall('User32.dll\RegisterWindowMessageW', 'WStr', 'SHELLHOOK', 'UInt')
   
   global StatusLog
   SetTitleBarIconState := false
   ShellMessageState := false
   if IsSet(IconFile) {
      IconNumber := IconNumber ?? 1
      hIconSmall := LoadPicture(IconFile, 'w' CXSMICON ' h' CYSMICON ' Icon' IconNumber, &ImageType)
      if ImageType != 1  ; IMAGE_ICON
         throw Error('Unable to extract icon from resource.', -1, 'Small icon.')
      hIconBig   := LoadPicture(IconFile, 'w' CXICON   ' h' CYICON   ' Icon' IconNumber, &ImageType)
      if ImageType != 1  ; IMAGE_ICON
         throw Error('Unable to extract icon from resource.', -1, 'Big icon.')
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon
      OnMessage MsgNum, ShellMessage
   }
   return MsgBox(Text?, Title?, Options?)
   
   SetTitleBarIcon(*) {
      ; Critical
      static ICON_SMALL := 0
      static ICON_BIG   := 1
      static WM_SETICON := 0x0080
      static PID := ProcessExist()
      
      HiddenWindowsState := A_DetectHiddenWindows 
      DetectHiddenWindows true
      if !WinExist('ahk_class #32770 ahk_pid' PID)
         throw Error('There is no such window.', -1, 'ahk_class #32770')
      SendMessage WM_SETICON, ICON_SMALL, hIconSmall
      SendMessage WM_SETICON, ICON_BIG,   hIconBig
      OnMessage WM_COMMNOTIFY, SetTitleBarIcon, 0
      DetectHiddenWindows HiddenWindowsState
      StatusLog .= A_TickCount '`tSetTitleBarIcon`n'
   }
   
   ShellMessage(wParam, lParam, *) {
      ; Critical
      static HSHELL_WINDOWCREATED   := 1
      static HSHELL_WINDOWDESTROYED := 2
      static hwnd
      
      if wParam = HSHELL_WINDOWCREATED {
         hwnd := lParam
         StatusLog .= A_TickCount '`tHSHELL_WINDOWCREATED`n'
      } else if wParam = HSHELL_WINDOWDESTROYED && lParam = hwnd {
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconSmall, 'Int')
         DllCall('User32.dll\DestroyIcon', 'Ptr', hIconBig,   'Int')
         OnMessage MsgNum, ShellMessage, 0
         StatusLog .= A_TickCount '`tHSHELL_WINDOWDESTROYED`n'
      }
   }
}
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 06:38

Thanks for staying on top of this, @iPhilip, much appreciated. I got this with your diagnostic code (no icons still):

Code: Select all

602941234

602942390	SetTitleBarIcon
602942390	HSHELL_WINDOWCREATED
602943390	HSHELL_WINDOWDESTROYED

602943562	SetTitleBarIcon
602943578	HSHELL_WINDOWCREATED
602944562	HSHELL_WINDOWDESTROYED

602944656	SetTitleBarIcon
602944656	HSHELL_WINDOWCREATED
602945656	HSHELL_WINDOWDESTROYED
User avatar
kunkel321
Posts: 1107
Joined: 30 Nov 2015, 21:19

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 07:20

Yes, thank you! No error messages for me this time. No icon on the first msgbox, but the next three does have them. Final box has:
---------------------------
TBI text box icons.ahk
---------------------------
77346937

77348000 SetTitleBarIcon
77348015 HSHELL_WINDOWCREATED
77349000 HSHELL_WINDOWDESTROYED

77349031 SetTitleBarIcon
77349031 HSHELL_WINDOWCREATED
77350031 HSHELL_WINDOWDESTROYED

77350062 SetTitleBarIcon
77350062 HSHELL_WINDOWCREATED
77351078 HSHELL_WINDOWDESTROYED

---------------------------
OK
---------------------------
As I look more closely at the parameters in the msgboxes... It's doing what it is supposed to do. :D
ste(phen|ve) kunkel
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 08:37

kunkel321 wrote:
19 Apr 2024, 07:20
Yes, thank you! No error messages for me this time.
Great! I will update the original post with the improvement.
kunkel321 wrote:
19 Apr 2024, 07:20
Yes, thank you! No error messages for me this time. No icon on the first msgbox, but the next three does have them.
That was the intended behavior. No icons are displayed when IconFile is omitted.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 10:10

I did some additional tests and decided to simplify the function. Instead of trying to detect the creation and destruction of the MsgBox window (which can be fooled by other MsgBox's in the same or other scripts), I decided to destroy the icons shortly after the MsgBox window is created. The window makes a copy of the icons so those resources are not needed after that. This change means that the function now works with AHK v2.0.0.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 10:40

@iPhilip, it's working great for me now too. Very nice, thank you!
Best regards,
burque505
iPhilip
Posts: 823
Joined: 02 Oct 2013, 12:21

Re: [Function] MsgBoxTBI - Display a MsgBox window with an icon in the title bar

19 Apr 2024, 10:44

You are welcome and thank you for sticking with me on this. :)
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: No registered users and 20 guests