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)
}
}
}
- iPhilip
P.S.:The function name, MsgBoxTBI, stands for MsgBox with a Title Bar Icon.
EDIT: Simplified function and added error handling.