just change the hIconSm using the SetClassLong API


Hi QvasiModo

I tried using the SetClassLong, but it fails :(

What have I done wrong with the parameters :confused:
Posted on 2004-06-10 01:11:40 by The SharK
First off you should not be changing global classes like #32770. If you really want to put an icon in a message box just use a hook...

invoke LoadIconA, NULL, IDI_HAND

mov [hIcon], eax

invoke MessageBoxIcon,NULL,[hIcon],"Hello",NULL,MB_OK

invoke DestroyIcon, [hIcon]
invoke ExitProcess, 0

MessageBoxIcon FRAME hWnd,hMBIcon,lpText,lpCaption,uType
.data
hMsgBoxIcon DD ?
hMsgBoxHook DD ?
.code

/*
If hWnd is supplied and hMBIcon is NULL
the icon is loaded from hWnd, if both are
NULL the message box is displayed normally
*/

mov eax, [hMBIcon]
mov [hMsgBoxIcon], eax
or eax,eax
jnz >
cmp [hWnd],eax
je >.NORMAL
invoke SendMessageA, [hWnd], WM_GETICON, ICON_SMALL, 0
mov [hMsgBoxIcon], eax
:
invoke GetCurrentThreadId
invoke SetWindowsHookExA, WH_CALLWNDPROC, offset WndProcHook, NULL, eax
mov [hMsgBoxHook], eax
.NORMAL
invoke MessageBoxA, [hWnd], [lpText], [lpCaption], [uType]
RET
ENDF

WndProcHook FRAME icode,wParam,lParam

invoke CallNextHookEx, [hMsgBoxHook], [icode], [wParam], [lParam]
push eax

mov eax,[lParam]
cmp D[eax+CWPSTRUCT.message],WM_INITDIALOG
jne >
invoke SendMessageA, [eax+CWPSTRUCT.hwnd], WM_SETICON, ICON_SMALL, [hMsgBoxIcon]
invoke UnhookWindowsHookEx,[hMsgBoxHook]
:
pop eax
RET
ENDF
Posted on 2004-06-10 02:07:17 by donkey
Here is the compiled example for GoAsm, RadASM project format. Tested with WinNT4, Win95 and Win2K :
Posted on 2004-06-10 03:28:17 by donkey

First off you should not be changing global classes like #32770. If you really want to put an icon in a message box just use a hook...

IMHO it's much easier to change the global class, consumes less resources too.
Under Win9X (I haven't tested other platforms) such changes are always local so there should be no problems.
Posted on 2004-06-10 12:20:39 by QvasiModo
@Shark: Ok, I've found the problem in your code :). SetClassLong takes a window handle, not instance handle. I know it sound a bit strange :/ but you have to actually create a window of that class in order to change it's properties. Also there's a call to SendMessage passing the hInstance as well, this won't work either.
Posted on 2004-06-10 12:30:30 by QvasiModo
Seems to work fine under Win98. Could anyone please test it on other platforms? :)
Posted on 2004-06-10 13:27:57 by QvasiModo
Hi QvasiModo,

I don't think the hook consumes alot of resources, and it only exists for an instant until just before the message is displayed and then it is unhooked and the resource is freed. It also allows you to quickly switch icons for different message boxes, not easily done with the SetClassLong method. The reason I don't believe it is a good idea to change global classes is that it may adversely affect other parts of your program and in the case of #32770 you have to consider it when creating any type of dialog or displaying any common dialog. System global classes are copied to your process in all versions of Windows so there is no cross-process contamination, but the in-process one is more than enough for me. As you said he will have to include code to create a window of the class and destroy it after he sets the class icon, he will have to do this everytime he wants to change the icon or leave a window of that class open for the entire run of his application, I personally believe this is a much greater waste of resources.
Posted on 2004-06-10 13:29:40 by donkey
I agree that it's not the cleanest way to do it :grin: but adding your app's icon to all these dialog boxes could be desired as well (or might not matter for very small apps).

Leaving a window open for the entire run of the program is not always bad, it could be your main window ;)

All in all I guess it depends heavily on what kind of program you're writing. :)
Posted on 2004-06-11 17:22:25 by QvasiModo
Hi QvasiModo


It works on Win2K, I see your icon on both the main window, and the messagebox !
Both are of the class #32770.


I thought that while I didn't have any real window created with CreateWindowEx (only a messagebox),
I could use a instance handle (hInstance).

But i sure was wrong about that :(


Well, we all learn something new all the time ;)


Nice work QvasiModo :alright:


Well donkey
next time I'll fill out the hIconSm member of the WNDCLASSEX
register the class, and then CreateWindowEx, that the correct
way (normal way) of making an Icon ;)
Posted on 2004-06-12 06:28:09 by The SharK