Create 'disabled' icons!
Posted: Sun Jun 28, 2009 1:18 pm
Whilst creating a new toolbar library, I was in need of a simple way of creating suitable looking 'disabled' icons for those instances when the user requested a default disabled image for a toolbar button etc. (Windows refuses to create 'em for us if we attach a disabled image-list to the toolbar in question! *astard!
)
Long story suddenly cut short; the following code (tested on Vista, XP and Win 2000) takes an icon handle and, if successful, returns a new icon which I would claim is suitable for use as a disabled version of the original icon!
Reading through the code you will note that I apply a simple alpha-blending manually by trawling through the pixel data. This was done to ensure the code would run on all versions of Windows (an alternative was to use the AlphaBlend_() api function which is available only on Win 2000 and beyond). Unfortunately, PB's DrawAlphaImage() would not behave itself in this instance!
My thanks to Netmaestro for his work on gray-scaling images and to Kinglestat for testing on Win 2000.

Long story suddenly cut short; the following code (tested on Vista, XP and Win 2000) takes an icon handle and, if successful, returns a new icon which I would claim is suitable for use as a disabled version of the original icon!

Reading through the code you will note that I apply a simple alpha-blending manually by trawling through the pixel data. This was done to ensure the code would run on all versions of Windows (an alternative was to use the AlphaBlend_() api function which is available only on Win 2000 and beyond). Unfortunately, PB's DrawAlphaImage() would not behave itself in this instance!
My thanks to Netmaestro for his work on gray-scaling images and to Kinglestat for testing on Win 2000.
Code: Select all
;/////////////////////////////////////////////////////////////////////////////////
;***Create disabled icon*** - version 1.0.0.
;*=========================
;*
;*©nxSoftWare (www.nxSoftware.com) 2009.
;*======================================
;* Stephen Rodriguez (srod) with thanks to Netmaestro for his work on creating 8-bit gray-scale images
;* and to Michael Vogel for a heads up on solving a 'dithering' problem.
;* Created with Purebasic 4.31 for Windows.
;*
;* Platforms: Windows - all versions. (Tested on Vista, XP and Win 2000 only!)
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;*NOTES.
;* i) Call the function CreateDisabledIcon() passing a handle to an existing icon and this function will, if successful,
;* return the handle of a new icon suitable for use as a 'disabled' version of the original icon.
;* Set the optional parameter 'backColor' to match the anticipated back color of the image/window to which the resulting icon is to
;* be applied. This is needed to remedy a 'dithering' problems resulting from the icon's alpha/transparency channels.
;* Set the optional 'alpha' parameter to a value between 1 and 255 to give the new icon a constant alpha-blended mix (XP onwards).
;*
;* ii) The function works by creating a gray-scale version of the color image and then applying a 50% blending with a white background.
;* This new image is then combined with the original icon mask to create a new icon.
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;The following function takes an icon and creates another icon suitable for use as a disabled image etc.
;Returns a hIcon if successful.
Procedure.i CreateDisabledIcon(hIcon, backColor = -1, alpha=$7f)
Protected newIcon, icInfo.ICONINFO, width, height, bmp.BITMAP, hdc
Protected MaskBmp, ColorBmp, i, j, color
Protected *px.LONG, bmpMask.BITMAP, *rgbQuad.RGBQUAD
If hIcon
If GetIconInfo_(hIcon, icInfo)
GetObject_(icInfo\hbmMask, SizeOf(BITMAP), bmp)
width = bmp\bmWidth
height = bmp\bmHeight
;The height needs halving if the mask bitmap contains the color one.
If icInfo\hbmColor = 0
height>>1
EndIf
;Create images for the color and mask bitmaps. We cannot simply use the bitmaps pointed to by the ICONINFO structure as both images
;may be combined into the mask (if the icon is a black and white monochrome icon).
ColorBmp = CreateImage(#PB_Any, width, height, 32)
If ColorBmp
MaskBmp = CreateImage(#PB_Any, width, height, 32)
If MaskBmp
hdc = StartDrawing(ImageOutput(ColorBmp))
If hdc
If backColor = -1
backColor = GetSysColor_(#COLOR_3DFACE)
EndIf
Box(0, 0, width, height, backColor)
backColor = RGB(Blue(backColor), Green(backColor), Red(backColor))
DrawIconEx_(hdc, 0, 0, hIcon, width, height, 0, 0, #DI_NORMAL)
StopDrawing()
hdc = StartDrawing(ImageOutput(MaskBmp))
If hdc
DrawIconEx_(hdc, 0, 0, hIcon, width, height, 0, 0, #DI_MASK)
StopDrawing()
GetObject_(ImageID(ColorBmp), SizeOf(BITMAP), bmp) : *px = bmp\bmBits
For i=0 To height-1
For j=0 To width-1
If *px\l&$ffffff <> backColor ;Gray-scale and blend 50% with white.
*rgbQuad = *px
color = (*px\l&$ff + (*px\l>>8)&$ff + (*px\l>>16)&$ff)/6 + $7f
*rgbQuad\rgbBlue = color
*rgbQuad\rgbGreen = color
*rgbQuad\rgbRed = color
*rgbQuad\rgbReserved = alpha
EndIf
*px + SizeOf(LONG)
Next
Next
With icInfo
\hbmMask = ImageID(MaskBmp)
\hbmColor = ImageID(ColorBmp)
EndWith
newIcon = CreateIconIndirect_(icInfo)
EndIf
EndIf
FreeImage(MaskBmp)
EndIf
FreeImage(ColorBmp)
EndIf
EndIf
EndIf
ProcedureReturn newIcon
EndProcedure
;/////////////////////////////////////////////////////////////////////////////////