Task icon in Windows

BlitzMax Forums/BlitzMax Programming/Task icon in Windows

Eikon(Posted 2005) [#1]
Has anyone been able to set their program's task icon yet?
Import "-lshell32"

Extern
	Function LoadIcon%(hWnd%, file$z, index%) = "ExtractIconA@12"
End Extern

Extern "win32"
	Function GetActiveWindow%()
	Function GetDesktopWindow%()
	Function GetWindowRect%(hWnd%, lpRect:Byte Ptr)
	Function SetWindowPos%(hWnd%, after%, x%, y%, w%, h%, flags%)
	Function SetClassLong%(hWnd%, nIndex%, dwNewLong%) = "SetClassLongA@12"
End Extern

Type lpRECT
	Field l%, t%, r%, b%
End Type

Const GFX_WIDTH = 320, GFX_HEIGHT = 200, BIT_DEPTH = 0, HERTZ = -1
Graphics GFX_WIDTH, GFX_HEIGHT, BIT_DEPTH, HERTZ
Local hWnd% = GetActiveWindow()
Local icon% = LoadIcon(hWnd, "icon.ico", 0); Print icon
SetClassLong hWnd, -14, icon
Local desk_hWnd% = GetDesktopWindow(), l:lpRect = New lpRECT
GetWindowRect desk_hWnd, l:lpRECT 

SetWindowPos hWnd, -2, (l.r / 2) - (GFX_WIDTH / 2), (l.b / 2) - (GFX_HEIGHT / 2), 0, 0, 1
Repeat; FlushMem; Flip; Until KeyDown(KEY_ESCAPE)
Why doesn't this work?


Eikon(Posted 2005) [#2]
So no one knows how to assign an icon to their program? This is a pretty important function :/


Regular K(Posted 2005) [#3]
Well, if you badly need it, could you resource hack the exe?


Eikon(Posted 2005) [#4]
That's the program icon. I'm talking about the task icon that appears in the upper left corner, beside the window title.


Sarge(Posted 2005) [#5]
Function LoadIcon_( instance:Int, icon:Byte Ptr ) = "LoadIconA@8"

hope it helps.


Eikon(Posted 2005) [#6]
Hi, Sarge. I assume that's for User32's LoadIcon function. Unfortunately, it doesn't seem to work either. Both of the LoadIcon functions are returning 0. The above code, which uses the shell32 function, works fine in B+/B3D with userlibs, so I can't understand why it's not working in Max. Thanks anyway.

* Update *
If I use the full path to the icon in the original code, it now returns a handle to the icon, but it still doesn't appear on the window. Now it's SetClassLong that's returning 0. GetLastError returns a 6, which means 'Invalid Handle'.




ziggy(Posted 2005) [#7]
Are you sure you have to pass short ints to the API? in XP most of the apis have been updated and they spect LONG integers


Sarge(Posted 2005) [#8]
i dont understand your code you are not even getting the handle for the tray to add something to it.


Eikon(Posted 2005) [#9]
i dont understand your code you are not even getting the handle for the tray to add something to it.
This is for the task icon, not anything to do with the system tray.

Are you sure you have to pass short ints to the API? in XP most of the apis have been updated and they spect LONG integers
I thought % was an integer, not a short integer. Integers were interchangeable with longs in past blitzes. I forgot that all that has changed now, but using longs instead doesn't solve the problem.

Function LoadIcon:Long(hWnd:Long, file$z, index:Long) = "ExtractIconA@12"
Function SetClassLong:Long(hWnd:Long, nIndex:Long, dwNewLong:Long) = "SetClassLongA@12"
Now the program closes as soon as you run it.


ziggy(Posted 2005) [#10]
I suposuse you have to pass the memory address of the long variable, not the value itself. It may be interpretating the value of the LONG as an address to a unsigned long value. Use pointers or even the memory address of your LONG variable when calling the API.


Eikon(Posted 2005) [#11]
I suposuse you have to pass the memory address of the long variable, not the value itself. Use pointers or even the memory address of your LONG variable when calling the API.

Would you mind showing me how to do that? If you could run the code and try to debug it, I would really appreciate it.

* Update *
Here is the updated code. For some reason, changing my Ints to Longs for calls like GetActiveWindow makes them stop working, so I've left them alone. Also, if Local Icon is cast as a Long instead of an Int, it returns 0.



GetLastError is returning 1414, which means "Invalid Icon Handle". Sounds like we're getting closer.


Sarge(Posted 2005) [#12]
Eikon look in the blitzmax samples folder somebody has made a win32 mod so look at the LoadIcon in that and try and use program's task icon a default icon like _
IDI_APPLICATION

hope it helps.


Eikon(Posted 2005) [#13]
Well, I'm giving up on it for now. The following code works to an extent. The icon is visible in the task bar, but not on the window itself. If anyone knows how to make it appear in both places, please let me know. Thanks to everyone who offered help.

Import "-lkernel32"
Import "-lshell32"

Extern "win32"
	Function GetActiveWindow() = "GetActiveWindow@0"
	Function SetClassLong(hWnd, nIndex, dwNewLong) = "SetClassLongA@12"
	Function GetLastError() = "GetLastError@0"
	Function LoadIcon(hWnd, file:Byte Ptr, index) = "ExtractIconA@12"
End Extern

Graphics 320, 240, 0

Local hWnd = GetActiveWindow()
Print "hWnd: " + hWnd

Local icon = LoadIcon(hWnd, "icon.ico", 0)
Print "icon: " + icon

Local ret = SetClassLong(hWnd, -14, icon)
Print "ret: " + ret
'If Not ret Then Notify GetLastError()

Repeat; FlushMem; Flip; Until KeyDown(KEY_ESCAPE)



Sarge(Posted 2005) [#14]
ok just reinstalled blitzmax and tested your code well i think it looks ok. But i just remembered, the blitzmax window is set to _

no: minimize button
no: maximize button
no: icon

so even if it does work you wont get the icon to show unless you change the windows setting using SetWindowLong.


Eikon(Posted 2005) [#15]
Thanks Sarge, that got me going on the right track. I can get it to appear now, but the window title isn't offset by it, it appears underneath it. That's easy enough to fix, I'll just add spaces to the title when I set it with SetWindowText. Thanks again :)

* Update *
Added it to the Code Archives
http://www.blitzbasic.com/codearcs/codearcs.php?code=1345


Sarge(Posted 2005) [#16]
No Problems. Feel free to wrap some of these commands and make a nice module out of it. Say you created them if you like.

http://www.blitzbasic.com/Community/posts.php?topic=45068

Happy to have helped.