Click here to Skip to main content
15,890,897 members
Articles / Multimedia / GDI+
Article

Iconits

Rate me:
Please Sign up or sign in to vote.
4.69/5 (75 votes)
12 Apr 20062 min read 218.5K   3.6K   209   49
An icon control that zooms and fades-in when your mouse hovers over it, which creates interesting visual effects if your application uses icons instead of buttons.

Sample Image

Introduction

For an application that uses icons instead of buttons, perhaps there might be a need to add some fancy effects rather than only showing a rising icon (when hovering). This control gives you an interesting visual effect, which makes an icon to zoom when the mouse hovers over it. Also, there is a Blur property that will cause the icon to be rendered transparent (without a single line of code!); of course, you may turn it off.

Usage

You can start using this control by following these two simple steps:

  1. Add the control to the toolbox (if you don't know how to do it, right click on the Toolbox, choose Add/Remove items, find Iconits.dll, and press OK).
  2. Now that you have seen the control on the toolbox (Iconits), you can start using it. However, these properties are essential:
    Property nameTypeDescription
    BlurBooleanSet to true if you want the transparency effect, set to false otherwise.
    IconBitmapSet the icon from any available image.
    IconSizeSizeIcon initial size.
    SizeSizeIcon actual size when mouse hovers over it.
    TooltipTextStringIcon's tooltip text which pops up when the mouse hovers over it for some seconds.

Alpha class

The trick on how the image becomes slightly transparent is done by creating three additional bitmaps instead of the original image. These additional bitmaps, with different opacity (0.25, 0.5, 0.75), will make the effect of the icon slightly fading.

The idea of generating bitmaps instead of direct rendering is, of course, speed. Another reason is, only three images are necessary and that is not too much. So, we develop a class which generates a new bitmap with a different opacity level from the available image:

C#
public static Bitmap returnAlpha(Bitmap bmp, int alpha)
{
    Color col; 
    Bitmap bmp2=new Bitmap(bmp);
    
    for (int i=0;i<bmp.Width;i++)
          for (int j=0;j<bmp.Height;j++) 
          {
            col=bmp.GetPixel(i,j); 
            if (col.A>0)
                bmp2.SetPixel(i,j,Color.FromArgb(min(
                       col.A-alpha),col.R,col.G,col.B)); 
          } 
      return bmp2;
}

It simply iterates through the image and redraws the image with a new transparency level, and, of course, you don't need to redraw the pixel which is already transparent (Alpha=0).

Optimization Issues

Optimization is a critical issue when you develop such controls that employ heavy computations. In this case, the problems are speed and image flickering since GDI+'s DrawImage is used. Double buffering is implemented so that the animation will displayed smoothly. Another issue, slow speed, only occurs if you do a direct rendering of the transparent image. We build additional bitmaps for this reason, which causes another drawback, the use of additional memory.

History

  • v0.1 (9 April 2006): Initial release.

    Implemented alpha transparency, and zoom on mouse-hover.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Indonesia Indonesia
Yojana Hanif was love to code, he is just graduated from Institut Teknologi Sepuluh Nopember Surabaya Indonesia.

Comments and Discussions

 
GeneralMy vote of 5 Pin
keritingNZ18-Aug-12 6:37
keritingNZ18-Aug-12 6:37 
Generalprofblem if transparent Pin
jinfrics23-Sep-09 18:51
jinfrics23-Sep-09 18:51 
Generalvery good job [modified] Pin
iowhfojfljLEJFSFLJafa11-Sep-07 23:45
iowhfojfljLEJFSFLJafa11-Sep-07 23:45 
GeneralFurther simplification Pin
blackholeat17-Jan-07 17:50
blackholeat17-Jan-07 17:50 
GeneralRe: Further simplification Pin
sly59623-Apr-07 15:18
sly59623-Apr-07 15:18 
QuestionWhat kind of icon does one want to import Pin
gordingin19-Nov-06 4:02
gordingin19-Nov-06 4:02 
GeneralResource Question Pin
gordingin19-Nov-06 3:52
gordingin19-Nov-06 3:52 
Generalso cool Pin
amin keshani12-Oct-06 1:05
amin keshani12-Oct-06 1:05 
General[LONG] Big update with everybody contributions Pin
Lelhu18-Sep-06 7:05
Lelhu18-Sep-06 7:05 
GeneralRe: [LONG] Big update with everybody contributions Pin
femme8-Mar-07 10:42
femme8-Mar-07 10:42 
QuestionMemory Problem fixed? Pin
K32118-Aug-06 0:31
K32118-Aug-06 0:31 
QuestionRe: Memory Problem fixed? Pin
swtechno18-Aug-06 4:23
swtechno18-Aug-06 4:23 
GeneralExcellent!! But maybe an addition.... Pin
K32117-Aug-06 20:30
K32117-Aug-06 20:30 
GeneralBug + Fix: Iconit after visibility change Pin
Kel_24-Jul-06 22:37
Kel_24-Jul-06 22:37 
GeneralBug + Fix: BackColor problem Pin
Pink Floyd10-May-06 12:07
Pink Floyd10-May-06 12:07 
GeneralA question Pin
MengChih24-Apr-06 23:20
MengChih24-Apr-06 23:20 
AnswerRe: A question Pin
Pink Floyd10-May-06 12:08
Pink Floyd10-May-06 12:08 
GeneralRe: A question Pin
MengChih14-May-06 23:08
MengChih14-May-06 23:08 
Generalvery creative work ! Pin
BillWoodruff24-Apr-06 15:25
professionalBillWoodruff24-Apr-06 15:25 
Generaltooltip behavior Pin
agarcian21-Apr-06 7:25
agarcian21-Apr-06 7:25 
GeneralRe: tooltip behavior Pin
jayoscar23-Apr-06 20:48
professionaljayoscar23-Apr-06 20:48 
GeneralRe: tooltip behavior Pin
Pink Floyd11-May-06 4:04
Pink Floyd11-May-06 4:04 
GeneralA more efficient alpha routeen... Pin
Jon Rista20-Apr-06 17:21
Jon Rista20-Apr-06 17:21 
I noticed your routeen to update the alpha of the bitmap is using a slower method (actually, about the slowest there is). Here is a significantly faster version of your routeen. It uses an unsafe code function, which allows the use of pointers. This function will adjust the original alpha by the input alpha amount. Since it uses pointers to directly edit the memory of the copied bitmap, it is hundreds of times faster than using the GetPixel/SetPixel method of GDI+. In fact, GDI+ essentially does the first and last parts of my function (locking pixels, finding the pixel in memory, reading/writing it, and unlocking), every time you call GetPixel or SetPixel. By using an unsafe function with pointers, you eliminate the repetitive locking/seeking/unlocking of pixel data in memory, which greatly improves performance.

/// <summary>
/// Adjusts the alpha level of the given bitmap
/// by a given amount.
/// </summary>
/// <param name="bmp">The bitmap to adjust alpha of.</param>
/// <param name="alpha">The alpha level to adjust by.</param>
/// <returns>A new bitmap, copied from the original, but with adjusted alpha.</returns>
/// <remarks>The alpha parameter can be positive or negative, by the amount
/// of adjustment desired. The value should be in the range of -255 to 255.</remarks>
public unsafe Bitmap returnAlpha(Bitmap bmp, int alpha)
{
    // Don't process bitmaps that don't have an alpha channel
    if (bmp.PixelFormat != PixelFormat.Format24bppRgb 
      && bmp.PixelFormat != PixelFormat.Format32bppArgb)
      throw new ArgumentException();

    // Copy the bitmap
    Bitmap bmpCopy = new Bitmap(bmp.Width, bmp.Height, PixelFormat.32bppArgb);

    // Lock the original bitmap and get its data
    GraphicsUnit gu = GraphicsUnit.Pixel;
    RectangleF rectF = bmp.GetBounds(ref gu);
    Rectangle rect = Rectangle.Round(rectF);
    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.Read, bmp.PixelFormat);

    // Lock the copy bitmap and get its data
    rectF = bmpCopy.GetBounds(ref gu);
    rect = Rectangle.Round(rectF);
    BitmapData copyData = bmpCopy.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

    // Create pointers for reading and writing the bitmaps
    byte* oPx = (byte*)bmpData.Scan0;
    byte* cPx = (byte*)copyData.Scan0;
    uint black = 255;
    byte b, a;

    for (int y=0; y<bmpData.Height; y++)
    {
        for (int x=0; x<bmpData.Width; x++)
        {
            // NOTE: Scanlines in a .NET bitmap usually order pixels in 
            // little-endian order, or "reverse" from the common way of
            // thinking about them. That means, instead of ARGB, its BGRA.

            // Copy color values from original to copy
            *cPx = *oPx;		// Blue
            *(cPx+1) = *(oPx+1);	// Green
            *(cPx+2) = *(oPx+2);	// Red


            // Retrieve base alpha value from original bitmap
            if (bmpData.PixelFormat == PixelFormat.Format32bppArgb)
            {
                // Get alpha component if original bitmap is 32bit
	        b = *(oPx+3);
            }
            else
            {
                // Get the color average if the original bitmap is 24bit
                b = (byte)((*cPx + *(cPx+1) + *(cPx+2)) / 3);
            }

            // Set the alpha value for the bitmap copy
            a = 0;
            if (b > 0)
            {
              a = (byte)Math.Min(255, Math.Max(0, b-alpha));  // Get alpha value clamped in range 0-255
              
              // NOTE: To directly set the alpha value of each pixel, rather than adjust. This
              // requires that the alpha parameter have a range of 0 to 255, rather than -255 to 255.
              // a = (byte)Math.Min(255, Math.Max(0, alpha)); // Clamp alpha value, 0-255
            }               

            // Record the alpha value in the bitmap copy
            *(cPx+3) = a;

            // Advance pointers to the next pixel
            cPx += 4;

            if (bmpData.PixelFormat == PixelFormat.Format24bppRgb)
              oPx += 3;
            else
              oPx += 4;
        }

        // NOTE: A .NET Bitmap always uses up the same amount of memory,
        // regardless of its bit depth (8bit images are a little different).
        // Each row of pixels in a bitmap will always use up 'width*4' bytes,
        // so a 24bit bitmap will have an extra 'width' bytes of unused space
        // for each row. A 16bit bitmap will have an extra 'width*2' bytes 
        // of unused space. This must be taken into account when advancing
        // pointers while doing operations on image pixels.

        // Advance the original bitmap pointer by any leftover 
        // bytes for the current row if the bitmap is 24 bits.
        if (bmpData.PixelFormat == PixelFormat.Format24bppRgb)
          oPx += bmpData.Width;
    }

    // Unlock the bitmap data in memory, allowing the GC to properly
    // collect their memory when they are no longer used
    copyBmp.UnlockBits(copyData);
    bmp.UnlockBits(bmpData);

    // Return the alpha-adjusted image
    return copyBmp;
}


-- modified at 23:23 Thursday 20th April, 2006
GeneralRe: A more efficient alpha routeen... Pin
Jon Rista20-Apr-06 17:38
Jon Rista20-Apr-06 17:38 
GeneralRe: A more efficient alpha routeen... Pin
jayoscar21-Apr-06 0:30
professionaljayoscar21-Apr-06 0:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.