MsgBox with custom icon (from resource)

Post your working scripts, libraries and tools for AHK v1.1 and older
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

MsgBox with custom icon (from resource)

18 Mar 2017, 20:56

I realised that MessageBoxIndirect can show a message box with a custom icon, although it must exist as a Win32 resource of a loaded module. Here's a quick proof of concept.

Code: Select all

MsgBoxResIcon(IconID, Text, Title:="", Options:=0, HwndOwner:=0) {
    if (Title = "")
        Title := A_ScriptName
    Options |= 0x80
    VarSetCapacity(prms, 10*A_PtrSize, 0), NumPut(10*A_PtrSize, prms)
    NumPut(HwndOwner, prms, 1*A_PtrSize)
    NumPut(DllCall("GetModuleHandle", "ptr", 0, "ptr"), prms, 2*A_PtrSize)
    NumPut(&Text, prms, 3*A_PtrSize)
    NumPut(&Title, prms, 4*A_PtrSize)
    NumPut(Options, prms, 5*A_PtrSize)
    NumPut(IconID, prms, 6*A_PtrSize)
    return DllCall("MessageBoxIndirect", "ptr", &prms)
}
This version only uses icons in the AutoHotkey exe (or compiled script).

Example usage:

Code: Select all

MsgBoxResIcon(160, "Script files look like this.")
Image
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 03:30

Why not reorder the parameters to match the built-in command and make it a built-in extended function? If any parameters in any position are allowed to be blank it would be easy to simulate the original command behavior.

Code: Select all

MsgBox(Options:=0, Title:="", Text="", Timeout="", File="", IconID="")
Then:
- if Options is not a number and all other parameters are missing, it'll behave like MsgBox, Text
- if File is zero and IconID is not blank it'll retrieve and use own module handle
- if File is a valid filename it'll load and use that file's handle and icon resource
Part of my AHK work can be found here.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 03:47

Remember when I said "Here's a quick proof of concept"? :roll:

I did re-order the parameters to (closer) match the built-in command - the one that's built into the next v2 alpha. See this topic. This function was just a brief distraction from today's real project, which was implementing the changes described there.

Feel free to reimplement MsgBox in script if you really want to, but there's more to it than you might think.
- if Options is not a number and all other parameters are missing, it'll behave like MsgBox, Text
I don't like this switching the parameter order depending on the number of parameters. Text is by far the most used, so should come first; but in this case, the purpose of the function is to demonstrate how to show an icon, and the icon is shown to the left of the text... so that's where I put the parameter. ;)
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 04:41

Yes, we have different ways of thinking, it's normal. :)

If I'm not mistaken, Murphy said something like "any improvisation remains definitive" (quote from a hazy memory) so I tend to do things as right as possible from the first attempt in order not to get stuck with a faulty first version (not that it always comes out right :D ).
As such I envisioned people starting to implement and use this proof-of-concept version of the function immediately, leading to confusion later on.

Sorry, I wasn't too clear regarding Options. What I meant was, if first parameter (called Options) is not a (valid) style number, it will become the Text. So the simplest usage would be MsgBox("text to be displayed") - no need for trailing commas for blank parameters. It'll be parameter function switching, not parameter order switching. :)

Can't know for sure but I believe Chris arranged the parameters the way he did - apart from the logical left-to-right clockwise count: Icon, Title, Text - because of a tiny aesthetic issue: when using A_ScriptName for the default title it'll always append the extension, be that ahk or exe, which at least in my opinion looks kinda unprofessional although occasionally it may help distinguish between compiled and uncompiled scripts with same name, probably mostly when debugging. Therefore in 3 or 4 parameters mode, Title has probably a higher importance than thought. Just an idea.

Anyway, I see there are many changes in v2 and many of them not backwards compatible, but since I'm stubbornly stuck with 98SE and AHK Basic forever plus XP ocasionally, AHKv2 won't probably affect me. ;)
Well, I'll leave you to the real project. Good luck! :)
Part of my AHK work can be found here.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 05:48

AutoHotkey was designed to be compatible with AutoIt v2. That is undoubtedly the primary reason for the current order.
Sorry, I wasn't too clear regarding Options.
I don't know why you think that. I'm pretty sure I understood correctly.
It'll be parameter function switching, not parameter order switching.
I don't think that's rational. There are four parameters (in the original MsgBox): Options, Title, Text and Timeout. The function of the Options parameter does not change to Text; the position of the Text parameter changes depending on the number of commas.

Obviously, when you define the function in script you would give the first parameter a name, and then aim to change its function depending on the presence or absence of other parameters. That's an implementation detail which really has nothing to do with the function's usage.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 07:02

Ah, the AutoIt compatibility slipped my mind; you're right, of course.

I wasn't going to pursue this - don't wanna waste your time - but in case there's something I'm not getting right: isn't it the same with the example below?
From the Help file:

Code: Select all

MsgBox, Text
MsgBox [, Options, Title, Text, Timeout]
From user's point of view, first parameter changes its meaning according to the command variant used. There are no extra commas in the single-parameter variant, so what appears to be third parameter in 3-4 parameter mode becomes first (and only) parameter in single-parameter mode. What happens internally (in AHK's code) is completely opaque to the user. That's the implementation detail you mentioned above.

Same thing I suggested for the function: in single-parameter mode, Options would become Text, otherwise it would act accordingly.
Command turned into function, with similar syntax, with only the addition of File and IconID for the user defined-icon mode.

Code: Select all

MsgBox(Text)
MsgBox(Options , Title, Text [,Timeout, File, IconID])
The only remaining issue would be HwndOwner, which - without hitting MSDN - I suppose would be the actual GUI that owns the message box, which may not be the main GUI. That could be an extra parameter as well - when missing, it would default to main GUI's HWND (if any) or module's HWND:

Code: Select all

MsgBox(Options , Title, Text [,Timeout, File, IconID, HwndOwner])
Well, that's it. Hope anyone reading this will understand what we're talking about. It'd be nice to see this in v1.1 sometime but if not we can always implement it independently as a library. ;)
Now off to work with me too! :D
Part of my AHK work can be found here.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: MsgBox with custom icon (from resource)

19 Mar 2017, 23:18

isn't it the same with the example below?
From the Help file:
Yes, exactly. The v1 help file. I'm pretty sure you missed the point I made about the syntax being closer to the new v2 syntax, not the v1 syntax.
From user's point of view, first parameter changes its meaning according to the command variant used.
Not from this user's point of view. Well, call it whatever you want.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

20 Mar 2017, 04:43

Oh, I got the part about v2 but was/am still hoping for a "classic" syntax implementation in v1.1. :)
Maybe I'm perceiving certaing things more in a visual way than in a code-wise way. Yep, we're different alright. And life goes on. :)
Part of my AHK work can be found here.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: MsgBox with custom icon (from resource)

26 Mar 2017, 08:10

Nice one. Thanks :wave:
I did a small modification to enable usage of other icons, it seems to work with some of the icons in shell32.dll but not all shown, eg, here.
I also made it return Yes, No, etc depending on which button is choosen.

Code: Select all

MsgBox, % MsgBoxResIcon({source:"shell32.dll", IconNumber:42}, "Text", "Title")
MsgBoxResIcon(IconID, Text, Title:="", Options:=0, HwndOwner:=0) {
    if (Title = "")
        Title := A_ScriptName
    Options |= 0x80
    VarSetCapacity(prms, 10*A_PtrSize, 0), NumPut(10*A_PtrSize, prms)
    NumPut(HwndOwner, prms, 1*A_PtrSize)
	if IsObject(IconID)
		NumPut(DllCall("GetModuleHandle", "Str", IconID.source, "Uptr"), prms, 2*A_PtrSize), NumPut(IconID.IconNumber, prms, 6*A_PtrSize)
	else
		NumPut(DllCall("GetModuleHandle", "ptr", 0, "ptr"), prms, 2*A_PtrSize), NumPut(IconID, prms, 6*A_PtrSize)
	
    NumPut(&Text, prms, 3*A_PtrSize)
    NumPut(&Title, prms, 4*A_PtrSize)
    NumPut(Options, prms, 5*A_PtrSize)
    
    return ["OK", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No",,, "Try Again","Continue"][DllCall("MessageBoxIndirect", "ptr", &prms)]
}
Image
Image hosted by: tinypic.com
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: MsgBox with custom icon (from resource)

26 Mar 2017, 21:03

A list of image resources on a third-party site may be inaccurate and may not apply to all Windows versions. You can use a Win32 resource viewer/editor to find which images exist on your version.

That list includes modules which have no reason to be loaded into the script by default. You can load such modules as data files (not executable) with (iirc) GetModuleHandleEx or LoadLibraryEx.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: MsgBox with custom icon (from resource)

27 Mar 2017, 12:21

lexikos wrote:A list of image resources on a third-party site may be inaccurate and may not apply to all Windows versions.
I wasn't really relying on that list for the statement that some icons in shell32.dll doesn't work, those that didn't work with the modified version of MsgBoxResIcon() where found by LoadPicture(). :think:
lexikos wrote: You can use a Win32 resource viewer/editor to find which images exist on your version.
I guess I should do that :oops:
lexikos wrote:You can load such modules as data files (not executable) with (iirc) GetModuleHandleEx or LoadLibraryEx.
That is good information, thanks.

Cheers.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

28 Mar 2017, 07:22

Maybe MessageBoxIndirect() expects an image/icon of a certain type, size and/or bpp range and rejects those resources that do not match. Such ranges could be dependent of the OS version too.

You may try VILister at my repository - can't handle PNGs and icon export is broken but can list icons in known resource files (DLL, EXE, OCX etc).
It's not optimized for AHK_L though so either use the precompiled EXE or compile with AHK Basic.
Part of my AHK work can be found here.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: MsgBox with custom icon (from resource)

28 Mar 2017, 11:20

Drugwash wrote:You may try VILister at my repository
Very nice Drugwash :bravo:
For example, LoadPicture("shell32.dll", "icon55") is a stack of papers (see the list from my first post in this thread), but MessageBoxIndirect() is blank for that number, however, VILister says that stack of paper is number 133, and MessageBoxIndirect() agrees :D
It seems it comes down to different enumertions.
thanks.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: MsgBox with custom icon (from resource)

28 Mar 2017, 11:30

The resource number is different from the resource index. That's a common mistake. ;)
VILister offers the AHK code to use for Gui, Add, Picture and IL_Add() depending on the radio switch at bottom-right, where the difference between the two can be seen.
Glad to be of help. :)
Part of my AHK work can be found here.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: MsgBox with custom icon (from resource)

29 Mar 2017, 01:04

jfyi I use this IconEx.ahk
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Alguimist
Posts: 428
Joined: 05 Oct 2015, 16:41
Contact:

Re: MsgBox with custom icon (from resource)

04 Apr 2017, 19:30

MagicBox generates code for MessageBoxIndirect, but here is another way to change the icon of a message box that doesn't rely on a DLL/EXE module resource ID:

Code: Select all

OnMessage(0x44, "OnMsgBox")
MsgBox 0x80, Title, Message
OnMessage(0x44, "")

OnMsgBox() {
    DetectHiddenWindows, On
    Process, Exist
    If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) {
        hIcon := LoadPicture("explorer.exe", "w32 Icon22", _)
        SendMessage 0x172, 1, %hIcon% , Static1 ; STM_SETIMAGE
    }
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: MsgBox with custom icon (from resource)

05 Apr 2017, 03:10

Alguimist wrote:

Code: Select all

OnMessage(0x44, "OnMsgBox")
[...]
Very nice. I couldn't find any (windows) documentaion for wm_commnotify:=0x44. Do you have additional information?
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: MsgBox with custom icon (from resource)

05 Apr 2017, 03:14

From WinUser.h (Win10)

Code: Select all

#define WM_COMMNOTIFY                   0x0044  /* no longer suported */
WM_COMMNOTIFY (3.1)
WM_COMMNOTIFY
idDevice = wParam; /* communication-device ID */
nNotifyStatus = LOWORD(lParam); /* notification-status flag */

The WM_COMMNOTIFY message is posted by a communication device driver whenever a COM port
event occurs. The message indicates the status of a window's input or output queue.

Parameter Description

idDevice Value of wParam. Specifies the identifier of the communication device that is posting the
notification message.

nNotifyStatus Value of the low-order word of lParam. Specifies the notification status in the low-order
word. The notification status may be one or more of the following flags:

Value Meaning

CN_EVENT Indicates that an event has occurred that was enabled in the event
word of the communication device. This event was enabled by a
call to the SetCommEventMask function. The application
should call the GetCommEventMask function to determine
which event occurred and to clear the event.
CN_RECEIVE Indicates that at least cbWriteNotify bytes are in the input queue.
The cbWriteNotify parameter is a parameter of the
EnableCommNotification function.
CN_TRANSMIT Indicates that fewer than cbOutQueue bytes are in the output
queue waiting to be transmitted. The cbOutQueue parameter is a
parameter of the EnableCommNotification function.

Returns

An application should return zero if it processes this message.

Comments

This message is sent only when the event word changes for the communication device. The application
that sends WM_COMMNOTIFY must clear each event to be sure of receiving future notifications.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: MsgBox with custom icon (from resource)

05 Apr 2017, 03:22

qwerty12 gives me some help on my afh-topic and this may be helpful here too

I used this to diable move a MsgBox

Code: Select all

MessageBox(handle, title, text, options) {
    WndHook := DllCall("SetWindowsHookEx", "int", 12, "ptr", RegisterCallback("CallWndRetProc", ""), "ptr", 0, "uint", DllCall("GetCurrentThreadId"), "ptr") ; WH_CALLWNDPROCRET := 12
    ret := DllCall("user32\MessageBox", "ptr", handle, "str", text, "str", title, "uint", options)
    if (WndHook)
        DllCall("UnhookWindowsHookEx", "ptr", WndHook)
    return ret
}

Code: Select all

CallWndRetProc(code, wParam, lParam) {
    ;critical 1000
    if (code >= 0) { ; code >= HC_ACTION := 0
        if (NumGet(lParam+0, A_PtrSize * 3, "uint") = 0x0110) { ; cwpmessage = WM_INITDIALOG := 0x0110
            cwplparam := NumGet(lParam+0, A_PtrSize, "ptr"), cwphwnd := NumGet(lParam+0, A_PtrSize * 4, "ptr")
            if (cwplparam && DllCall("GetWindowLong" (A_PtrSize = 8 ? "Ptr" : ""), "ptr", cwphwnd, "int", -21, "ptr") = cwplparam) ; GWLP_USERDATA := -21
                if (NumGet(cwplparam+0, "uint") = A_PtrSize * 10) ; MSGBOXPARAMS := A_PtrSize * 10
                    ;GuiDisableMove(cwphwnd) DO SOMETHING HERE
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", code, "ptr", wParam, "ptr", lParam, "ptr")
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: MsgBox with custom icon (from resource)

05 Apr 2017, 03:31

jNizM wrote:jfyi I use this IconEx.ahk
Nice one.
jNizM wrote:From WinUser.h (Win10)
Thanks. :thumbup:

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: shawn_xwang, terraformars and 156 guests