Menu Icons (The easy way! Vista+)
Posted: Wed May 05, 2010 3:22 am
There are a few menu icon sources on the forums, all of them are owner drawn. (only way to get nice looking icons in front of menu items)
PureBasic's native icon menu is nice, but I never liked the color stripe, and the highlight color clashes a little with the text color etc.
And it does not match the system menu visual style, there may be some usability issues with it too. (after all it's ownerdrawn, meaning the coder need to do most of the work)
I began thinking... I want the Windows OS menu, but with icons in front of items.
Can't be THAT hard can it? Erm.. yeah it can...
Unless you use the source below and use it on Windows 6.0+ (Vista+), in which case it's pretty easy.
AddImageToMenuItem() will copy the current image, creating a new one.
If the icon was copied/created/added to the menu sucessfully then AddImageToMenuItem() will return a handle to a image, otherwise it returns #Null.
When you are done with the menu (and the icon) just use FreeImage() to free it.
You must also use FreeImage() if you plan to replace the menu icon, if you do not then you will end up with a memory leak.
Maybe Fred will support this type of icons in the future on Vista+, but until then this is as good as it gets. (unless someone here can improve on this further)
Why this messing around with copying and freeing?
Well it's because (and I have no idea why really it has to be like this, seems silly if you ask me) is the Vista+ need the icons (or image rather) to be a 32bit image with alpha mask,
but the RGBA must actually be pre-multiplied alpha pixels.
If it wasn't for that little annoyance then this would have needed only a few lines, instead of half a page.
So how is this better than owner drawn? Well I pointed that out earlier. Let's just say that this lets you use the "normal" menu, it works with both the window menu and the popup menu, and looks best with the popup menu as you can display icons for the root items properly as well. (window menu has some issues with that but subitems/submenus are ok).
Vista, 2008, Windows 7, 2008R2 will show the proper theme/coloring just like normally, accelerator keys works, etc etc..
The real shame however is that Microsoft didn't get a chance to add the 32bit RGBA image icon feature in W2K and XP and W2K3. Then again, XP is about 10 years old now so...*shrug*
And in the hopes this gets really popular I place this in the Public Domain, have fun folks!
If you need a good consistent and free set of menu icons etc.
Check out http://tango.freedesktop.org/Tango_Desktop_Project the icons are public domain, but I still advise that you credit the project in your program or documentation somewhere.
Best of all is that these icons come in 16x16 and 32x32 and they are 32bit Alpha PNG's, so they can be used with the code below (sorry, still need pre-multiply the alpha though)
and they look damn great.
PureBasic's native icon menu is nice, but I never liked the color stripe, and the highlight color clashes a little with the text color etc.
And it does not match the system menu visual style, there may be some usability issues with it too. (after all it's ownerdrawn, meaning the coder need to do most of the work)
I began thinking... I want the Windows OS menu, but with icons in front of items.
Can't be THAT hard can it? Erm.. yeah it can...
Unless you use the source below and use it on Windows 6.0+ (Vista+), in which case it's pretty easy.
AddImageToMenuItem() will copy the current image, creating a new one.
If the icon was copied/created/added to the menu sucessfully then AddImageToMenuItem() will return a handle to a image, otherwise it returns #Null.
When you are done with the menu (and the icon) just use FreeImage() to free it.
You must also use FreeImage() if you plan to replace the menu icon, if you do not then you will end up with a memory leak.
Maybe Fred will support this type of icons in the future on Vista+, but until then this is as good as it gets. (unless someone here can improve on this further)
Why this messing around with copying and freeing?
Well it's because (and I have no idea why really it has to be like this, seems silly if you ask me) is the Vista+ need the icons (or image rather) to be a 32bit image with alpha mask,
but the RGBA must actually be pre-multiplied alpha pixels.
If it wasn't for that little annoyance then this would have needed only a few lines, instead of half a page.
So how is this better than owner drawn? Well I pointed that out earlier. Let's just say that this lets you use the "normal" menu, it works with both the window menu and the popup menu, and looks best with the popup menu as you can display icons for the root items properly as well. (window menu has some issues with that but subitems/submenus are ok).
Vista, 2008, Windows 7, 2008R2 will show the proper theme/coloring just like normally, accelerator keys works, etc etc..
The real shame however is that Microsoft didn't get a chance to add the 32bit RGBA image icon feature in W2K and XP and W2K3. Then again, XP is about 10 years old now so...*shrug*
And in the hopes this gets really popular I place this in the Public Domain, have fun folks!
If you need a good consistent and free set of menu icons etc.
Check out http://tango.freedesktop.org/Tango_Desktop_Project the icons are public domain, but I still advise that you credit the project in your program or documentation somewhere.
Best of all is that these icons come in 16x16 and 32x32 and they are 32bit Alpha PNG's, so they can be used with the code below (sorry, still need pre-multiply the alpha though)
and they look damn great.
Code: Select all
Structure BM_RGBA
r.a
g.a
b.a
a.a
EndStructure
Procedure.i AddImageToMenuItem(menu.i,item.i,image.i)
Define result.i=#Null,mii.MENUITEMINFO,hmenu.i,imageid.i,bmp.BITMAP,*bm.BM_RGBA,*bmend,i.i,ii.i,imagepargb.i
Static Dim rgbalpha_lookup.a(255,255)
If OSVersion()>=#PB_OS_Windows_Vista ;Windows 6.0+ (Vista+)
If rgbalpha_lookup(255,255)<>255
For i=0 To 255
For ii=0 To 255
rgbalpha_lookup(i,ii)=Round(i*(ii/255.0),#PB_Round_Nearest)
Next
Next
EndIf
If IsMenu(menu) And IsImage(image)
hmenu=MenuID(menu)
imagepargb=CopyImage(image,#PB_Any)
If IsImage(imagepargb)
imageid=ImageID(imagepargb)
GetObject_(imageid,SizeOf(BITMAP),bmp)
If bmp And (bmp\bmWidth+bmp\bmWidth)>0 And bmp\bmBits
*bm=bmp\bmBits
*bmend=*bm+((bmp\bmWidth*bmp\bmHeight)<<2)
Repeat
*bm\r=rgbalpha_lookup(*bm\r,*bm\a)
*bm\g=rgbalpha_lookup(*bm\g,*bm\a)
*bm\b=rgbalpha_lookup(*bm\b,*bm\a)
*bm+SizeOf(BM_RGBA)
Until *bm>=*bmend
mii\cbSize=SizeOf(mii)
mii\fMask=#MIIM_BITMAP
mii\hbmpItem=imageid
If SetMenuItemInfo_(hmenu,item,#False,mii)
result=imagepargb
EndIf
Else
result=#Null
EndIf
If result=#Null
FreeImage(imagepargb)
EndIf
EndIf
EndIf
EndIf
Procedurereturn result
EndProcedure