News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Cann't load icon via LoadImage

Started by Rockphorr, August 01, 2022, 06:57:12 AM

Previous topic - Next topic

NoCforMe

Yes, JJ (although you got off on quite a tangent there in your criticism! even though I happen to agree with you: Just use INVOKE (fn), fer chrissakes!).

I just tried this (in Olly debug, didn't actually display it) and it worked (under Windows 7)--came back with a non-zero result, which must be a handle to the icon:


; Test LoadIcon():
INVOKE LoadIcon, NULL, IDI_WINLOGO


Try it.
Assembly language programming should be fun. That's why I do it.

jj2007

invoke DrawIcon, hdc, 10, 10, rv(LoadIcon, hInstance, IDI_APPLICATION)
invoke DrawIcon, hdc, 50, 10, rv(LoadImage, hInstance, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_SHARED)


Works perfect, but I doubt that you see these icons when using 0 instead of hInstance. Here on Win7 it just shows then a boring default icon :cool:

Btw the use of NULL instead of hInstance makes also the WinMain LoadIcon fail:

invoke LoadIcon, hInst, 123   ; with NULL, you only get the boring grey default icon
mov   wc.hIcon,eax
mov   wc.hIconSm,eax


NoCforMe

Wellll, you can't use your module's instance handle with LoadIcon() when loading standard icons as you wrote above; throws an error. Proven with the attached li'l app.

Doing the recommended thing (passing NULL for the instance handle) works fine.
Assembly language programming should be fun. That's why I do it.

jj2007

Missing:
- the rc file
- the icon files
- my_masm32rt.inc


*** LoadIcon test.rc not found, will try rsrc.rc ***

*** Assemble, link and run LoadIcon test ***

*** Assemble using UAsm64  ***
Tmp_File.asm(7) : Error A2106: Cannot open file: "\masm32\include\my_masm32rt.inc" [ENOENT]
Tmp_File.asm(14) : Error A2091: Language type must be specified
Tmp_File.asm(67) : Error A2210: Syntax error: WC
Tmp_File.asm(70) : Error A2082: Must be in segment block
Tmp_File.asm(72) : Error A2082: Must be in segment block
Tmp_File.asm(74) : Error A2082: Must be in segment block
Tmp_File.asm(75) : Error A2082: Must be in segment block
Tmp_File.asm(77) : Error A2082: Must be in segment block
Tmp_File.asm(79) : Error A2082: Must be in segment block
Tmp_File.asm(80) : Error A2082: Must be in segment block
Tmp_File.asm(88) : Error A2210: Syntax error: MainWinHandle
Tmp_File.asm(90) : Error A2210: Syntax error: StatusHandle
Tmp_File.asm(91) : Error A2082: Must be in segment block
Tmp_File.asm(93) : Error A2210: Syntax error: S1Handle
Tmp_File.asm(94) : Error A2210: Syntax error: S2Handle
Tmp_File.asm(96) : Error A2210: Syntax error: NullInstIconHandle
Tmp_File.asm(97) : Error A2210: Syntax error: InstIconHandle
Tmp_File.asm(106) : Error A2082: Must be in segment block
Tmp_File.asm(107) : Error A2082: Must be in segment block
Tmp_File.asm(109) : Error A2178: Too many arguments to INVOKE
Tmp_File.asm(110) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(117) : Error A2082: Must be in segment block
Tmp_File.asm(118) : Error A2092: PROC, MACRO or macro loop directive must precede LOCAL
Tmp_File.asm(122) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(123) : Error A2082: Must be in segment block
Tmp_File.asm(126) : Error A2082: Must be in segment block
Tmp_File.asm(127) : Error A2082: Must be in segment block
Tmp_File.asm(128) : Error A2082: Must be in segment block
Tmp_File.asm(129) : Error A2082: Must be in segment block
Tmp_File.asm(132) : Error A2082: Must be in segment block
Tmp_File.asm(133) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(134) : Error A2082: Must be in segment block
Tmp_File.asm(135) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(137) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(138) : Error A2082: Must be in segment block
Tmp_File.asm(139) : Error A2082: Must be in segment block
Tmp_File.asm(140) : Error A2082: Must be in segment block
Tmp_File.asm(141) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(142) : Error A2082: Must be in segment block
Tmp_File.asm(143) : Error A2082: Must be in segment block
Tmp_File.asm(144) : Error A2082: Must be in segment block
Tmp_File.asm(149) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(150) : Error A2082: Must be in segment block
Tmp_File.asm(153) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(154) : Error A2082: Must be in segment block
Tmp_File.asm(155) : Error A2082: Must be in segment block
Tmp_File.asm(157) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(158) : Error A2082: Must be in segment block
Tmp_File.asm(159) : Error A2082: Must be in segment block
Tmp_File.asm(160) : Error A2082: Must be in segment block
Tmp_File.asm(163) : Error A2160: INVOKE requires prototype for procedure
Tmp_File.asm(163) : Fatal error A1113: Too many errors
*** Assembly error ***

NoCforMe

Damnit. Sorry 'bout that. I keep forgetting to change my personal include file ("my_masm32rt.inc") to the generic one everyone else here uses. Attachment above fixed.

So JJ, what's with those .asc files in your zips? Is that the source file as used by your editor? Why would we want that file, when we have the .asm file?

No resources needed loading by that program; just uses LoadIcon, NULL, IDI_WINLOGO. Works.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on August 02, 2022, 11:13:14 AM
Damnit. Sorry 'bout that. I keep forgetting to change my personal include file ("my_masm32rt.inc") to the generic one everyone else here uses. Attachment above fixed.

OK, now it assembles :thumbsup:

QuoteSo JJ, what's with those .asc files in your zips? Is that the source file as used by your editor? Why would we want that file, when we have the .asm file?

You can open them in WordPad (C:\Windows\System32\write.exe).

QuoteNo resources needed loading by that program; just uses LoadIcon, NULL, IDI_WINLOGO. Works.

It "works" because Windows gives you that ugly grey default icon that dates back to MS DOS times. Below you can see the difference. Hint: no luck with LoadIcon, NULL...

Mikl__

Rockphorr, the solution to your problem on the site wasm.in
jj2007, la tua soluzione รจ ottima!

NoCforMe

Quote from: jj2007 on August 02, 2022, 12:20:42 PM
QuoteNo resources needed loading by that program; just uses LoadIcon, NULL, IDI_WINLOGO. Works.

It "works" because Windows gives you that ugly grey default icon that dates back to MS DOS times. Below you can see the difference. Hint: no luck with LoadIcon, NULL...

Wait, I'm confused. That picture you posted shows exactly the icon I got with

INVOKE LoadIcon, NULL, IDI_WINLOGO


Not the "ugly grey default icon that dates back to MS-DOS times". I loaded no resources. Just the code I gave here.
Assembly language programming should be fun. That's why I do it.

TimoVJL

#38
NirSoft icon viewer:
https://www.nirsoft.net/utils/iconsext.html

shell32.dll and imageres.dll names are in iconcache.db database.

hIcon1 = LoadIcon(NULL, IDI_WINLOGO);
hIcon2 = LoadImage(NULL, MAKEINTRESOURCE(OIC_WINLOGO), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
May the source be with you

jj2007

Quote from: NoCforMe on August 02, 2022, 01:18:28 PM
Wait, I'm confused. That picture you posted shows exactly the icon I got with

INVOKE LoadIcon, NULL, IDI_WINLOGO


Not the "ugly grey default icon that dates back to MS-DOS times". I loaded no resources. Just the code I gave here.

I know it's confusing. There are two locations in a standard Windows program where to load icons:
A. in WinMain: mov wc.hIcon, rv(LoadIcon, ...
B. in the WM_PAINT handler: invoke DrawIcon, hdc, 10, 10, rv(LoadIcon, ...

The two locations behave differently. In WinMain, if you load an invalid icon, you get this:



This is the ugly default icon for executables, and it dates back to the 20th Century - see also below the AltTab screenshot.

If you load an invalid icon in the WM_PAINT handler, you just see nothing.

If you use LoadIcon, hInstance..., Windows checks in this instance, i.e. in the resources of this exe, for a matching ICON.
If you use LoadIcon, NULL..., Windows checks elsewhere, and finds, in most cases, the crappy grey default icon.

I attach a testbed for playing, 48 lines only - the absolute minimum for a Windows program. Pure Masm32 SDK ;-)

TimoVJL

May the source be with you

Rockphorr

Thanks to Mikl, I found that i forget
push hIcon
call GetLastError
pop hIcon


so i lost handle when it was.

this is working code

   ;---------------------------
mov EAX,LR_SHARED
push EAX ;fuLoad
mov EAX,32 ;y height
push EAX ;cyDesired
mov EAX,32 ;x width
push EAX ;cxDesired
mov EAX,IMAGE_ICON
push EAX ;uType
;xor EAX,EAX
mov EAX,OIC_WINLOGO
push EAX ;lpszName
xor EAX,EAX
;mov EAX,hInstance
push EAX ;hinst
call LoadImage
;---------------------------
push EAX
mov EAX,100;Y
push EAX
mov EAX,1;X
push EAX
push [EBP+@HDC]
call DrawIcon
;---------------------------

jj2007

Quote from: Rockphorr on August 03, 2022, 02:05:04 AM
   mov   EAX,LR_SHARED
   push   EAX   ;fuLoad
   mov   EAX,32 ;y height
   push   EAX   ;cyDesired

Can you explain, in a few words, the logic of your approach? Why don't you use

push LR_SHARED  ; fuLoad
push 32  ; cyDesired

?

NoCforMe

Quote from: jj2007 on August 03, 2022, 02:29:48 AM
Quote from: Rockphorr on August 03, 2022, 02:05:04 AM
   mov   EAX,LR_SHARED
   push   EAX   ;fuLoad
   mov   EAX,32 ;y height
   push   EAX   ;cyDesired

Can you explain, in a few words, the logic of your approach? Why don't you use

push LR_SHARED  ; fuLoad
push 32  ; cyDesired

?

Or better yet, as you suggested earlier, just dispense with all this push-push-call crap and use INVOKE as [insert name of deity here] intended:


INVOKE LoadImage, 0, OIC_WINLOGO, IMAGE_ICON, 32, 32, LR_SHARED


It does exactly the same thing as the mess you have and is much more readable, understandable and maintainable.
Assembly language programming should be fun. That's why I do it.

Rockphorr

Quote from: NoCforMe on August 03, 2022, 03:37:35 AM
Quote from: jj2007 on August 03, 2022, 02:29:48 AM
Quote from: Rockphorr on August 03, 2022, 02:05:04 AM
   mov   EAX,LR_SHARED
   push   EAX   ;fuLoad
   mov   EAX,32 ;y height
   push   EAX   ;cyDesired

Can you explain, in a few words, the logic of your approach? Why don't you use

push LR_SHARED  ; fuLoad
push 32  ; cyDesired

?

Or better yet, as you suggested earlier, just dispense with all this push-push-call crap and use INVOKE as [insert name of deity here] intended:


INVOKE LoadImage, 0, OIC_WINLOGO, IMAGE_ICON, 32, 32, LR_SHARED


It does exactly the same thing as the mess you have and is much more readable, understandable and maintainable.

I prefer a code style look like inside the debugger.  For more readable, understandable and maintainable are C++.