Click here to Skip to main content
13,198,325 members (85,465 online)
Click here to Skip to main content
Add your own
alternative version


99 bookmarked
Posted 24 Oct 2007

Not just a image list control, Neat, 3D, iTunes style

, 29 Oct 2007
Rate this:
Please Sign up or sign in to vote.
The image list controls shows all imaes in 3D, animate the items when selected and let control item size, transparency, positions and animation speed

Download - 2,803.1 KB

Download - 408.7 KB

Screenshot - AlbumViewer.gif


The inspiration has been iTunes album list control. This image list control let you display your images in a new 3D manner. No more boring images shown one after another but comes with a cool animation. The zoom level of unselected items can be controls and also the height of shadow, transparency of each unselected item, their position and animation speed.

This is very useful control for displaying images in GUI rich applications. The control is derived from CListCtrl class so it can be extended so support conventional list control views or cool animated 3D view.


As I mentioned the inspiration was iTunes album control. Enjoying music over one of these getting cooler weekends I wondered what would it take to have cool control for showing images with smooth and neat animation as iTunes and hence took up the challenge and found out it only needed some 10 algebra equations and good use of GDI+ to achieve it.

This control loads full size images, in the demo it uses images as large as 800x600 and by using GDI+ efficiently you can animate, zoom and control alpha without any flicker and in a very smooth manner.

This article is most useful for developers looking for more information on using GDI+ painting. Even though GDI+ got almost everything needed but could not get the images to draw like iTunes. It allows to shear the images however doesn't allow to make height of both sides of images different. I did not really try to use matrix transformations however I think the animation and positioning of images could be done better using them.

Using the code

To use the control in your project add AlubumCtrl.h and AlbumCtrl.cpp, add a list control on your form/dialog box, create a member variable for this list control of type CAlbumCtrl and add the following code in your OnInitDialog or anywhere else where you want to add new items to the list control:
m_ctlAlbum.AddItem(L"images\\Water lilies.jpg");
m_ctlAlbum.AddItem(L"images\\Blue hills.jpg");





Calculating item positions

The following function is most import function in placing the control and suprisingly smallest portion of code. Well it did take some 4 iterations of fine tuning the algebra and code before it came to this :)

RectF CAlbumCtrl::CalcItemRect(const int n, const RectF rcBase, bool bLeft)
    float r = m_fRatio;
    float p = pow(r,n);
    int h = rcBase.Height;
    int w = rcBase.Width;
    int y = 0;
    int x = 0;

    for(int j=1;j<=n;j++)
        y += (m_nItemY*h*pow(r,j))/100;

    if( bLeft )

        int x = 0;
        for(int j=2;j<=n+1;j++)
            x += w*pow(r,j);

        return RectF(rcBase.X-x, rcBase.Y-y, w*p, h*p);
    x = rcBase.X + w;

    for(int j=1;j<n;j++)
        x += w*pow(r,j);

    for(int j=1;j<n+1;j++)
        x -= (1-r)*w*pow(r,j);

    return RectF(x, rcBase.Y-y, w*p, h*p);

Drawing items

This is second most important function in the control. This picks up the items image, calculates the shadow width, applies alpha to image and decreasing alpha to the shadow and if required places text over selected images.

void CAlbumCtrl::DrawItem(const int nItem, RectF rc, Graphics &grf, float fAlpha, bool bDrawText)
    // centre image
    // draw the items only if they are inside the visible area
    // to keep repainting fast

    if( nItem < 0 || nItem > m_vecItems.size()-1 )

    Bitmap bitmap(m_vecItems[nItem].wszItem.c_str());

    CRect r;

    RectF rcWnd(r.left,, r.Width(), r.Height());

    Bitmap     bmp(rc.Width, rc.Height, PixelFormat32bppARGB );

    Graphics graphic(&bmp);

    ImageAttributes imgAttrb;

    RectF rcDraw(0, 0, rc.Width, rc.Height);
    graphic.DrawImage(&bitmap, rcDraw, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), UnitPixel, &imgAttrb);

    graphic.DrawRectangle(&Pen(Color(80,80,80), 2),rcDraw);
    ColorMatrix bmpAlpha = {
                             1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                             0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                             0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                             0.0f, 0.0f, 0.0f, fAlpha, 0.0f,
                             0.0f, 0.0f, 0.0f, 0.0f, 1.0f

    grf.DrawImage(&bmp, rc, 0, 0, rc.Width, rc.Height, UnitPixel, &imgAttrb);

    int iHeight = bmp.GetHeight();
    int iWidth = bmp.GetWidth();

    // reflection percent

    if( !m_nItemShadow )
        m_nItemShadow = 1;

    float nRef = 100.0/m_nItemShadow;
    RectF rcRef = RectF(rc.X, rc.Y+rc.Height, rc.Width, rc.Height/nRef);
    Bitmap     bmpRef(rcDraw.Width, rcDraw.Height/nRef, PixelFormat32bppARGB );

    Color color, colorTemp;
    for(UINT iRow = iHeight; iRow > iHeight-iHeight/nRef; iRow--)
       for(UINT iColumn = 0; iColumn < iWidth; iColumn++)
           // decrease the alpha by 1 value for each line in bottom margin
           double dAlpha = (iHeight/nRef-(iHeight-iRow))*255/(iHeight/nRef);
          bmp.GetPixel(iColumn, iRow, &color);
          bmpRef.SetPixel(iColumn, iHeight-iRow, colorTemp);
    grf.DrawImage(&bmpRef, rcRef, 0, 0, rcRef.Width, rcRef.Height, 
    UnitPixel, &imgAttrb);
    if( bDrawText )
        //wstring wszText = m_vecItems[nItem].wszItem; 
        //Font myFont(L"Tahoma",12,FontStyleRegular,UnitPixel);
        //RectF rcText;
        //grf.MeasureString(wszText.c_str(), wszText.length(), &myFont, 
    // rcRef, &rcText);
        //grf.DrawString(wszText.c_str(),wszText.length(), &myFont, 
    // PointF(rcRef.X+rcRef.Width-rcText.Width-14, 
    // rcRef.Y+(rcRef.Height-rcText.Height)/2-rcText.Height), 
    // &SolidBrush(Color(255,255,255))); 
        //wchar_t temp[10];
        //wszText = _itow(nItem+1, temp, 10);
        //grf.DrawString(wszText.c_str(),wszText.length(), &myFont, 
    // PointF(rcRef.X+2, rcRef.Y+(rcRef.Height-rcText.Height)/2-rcText.Height), 
    // &SolidBrush(Color(255,255,255))); 
        //grf.DrawString(wszText.c_str(),wszText.length(), &myFont, 
    // PointF(rcRef.X, rcRef.Y), &SolidBrush(Color(255,255,255))); 

Behind the scenes involved maths

The most interested portion of the control is the maths involved in positioning and animating the items. In that there is different algebra involved in placing/animating the items on the left and right of the center selected item.

Position the items in the control

Calculating the width of any item

Wn = W (r/100)n

Calculating the height of any item

Hn = H (r/100)n

Calculating the Y position of any item

Yn = Y - n

i = 1

Calculating the X position of items on the left of selected item

Xn = X - n+1

i = 2

Calculating the X position of items on the right of selected item

Xn = X + W + n-1

i = 1
W(r/100)i - n+1

i = 1


H = Height of the selected item

W = Width of the selected item

X = X position of the selected item

Y = Y position of the selected item

r = Current zoom level in %

e = Current elevation of Y

Animating items in the control

Animating items towards the left

Animating items on the left side

∆X = c(Xn+1-Xn)/l
Xn = Xn + ∆X

∆Y = c(Yn+1-Yn)/l

Yn = Yn + ∆Y

∆W = c(Wn+1-Wn)/l
Wn = Wn + ∆W

∆H = c(Hn+1-Hn)/l
Hn = Hn + ∆H

Animating items on the right side

∆X = c(Xn+1-Xn)/l
Xn-1 = Xn + ∆X

∆Y = c(Yn+1-Yn)/l
Yn-1 = Yn - ∆Y

∆W = c(Wn+1-Wn)/l
Wn = Wn - ∆W

∆H = c(Hn+1-Hn)/l
Hn = Hn - ∆H

Animating items towards the right

Animating items on the left side

∆X = c(Xn+1-Xn)/l
Xn = Xn + ∆X

∆Y = c(Yn+1-Yn)/l

Yn = Yn + ∆Y

∆W = c(Wn+1-Wn)/l
Wn = Wn + ∆W

∆H = c(Hn+1-Hn)/l
Hn = Hn + ∆H

Animating items on the right side

∆X = c(Xn+1-Xn)/l
Xn = Xn + ∆X

∆Y = c(Yn+1-Yn)/l
Yn = Yn - ∆Y

∆W = c(Wn-1-Wn)/l
Wn = Wn - ∆W

∆H = c(Hn-1-Hn)/l
Hn = Hn - ∆H


c = Current animation step

l = Total animation steps count

Future Features

Planning to add view switch buttons so users can switch back/forth to Icon view/List View/Report View/Album View


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ashok Jaiswal
Web Developer
Hong Kong Hong Kong
innovating, managing and developing next generation media products and services

You may also be interested in...

Comments and Discussions

GeneralMy vote of 1 Pin
saravanan.rex@gmail.com6-Apr-09 19:59
membersaravanan.rex@gmail.com6-Apr-09 19:59 
Generalcool Pin
Dr.Luiji13-Nov-07 20:47
memberDr.Luiji13-Nov-07 20:47 
GeneralRe: cool Pin
Ashok Jaiswal14-Nov-07 16:50
memberAshok Jaiswal14-Nov-07 16:50 
GeneralRe: cool Pin
Dr.Luiji15-Nov-07 10:15
memberDr.Luiji15-Nov-07 10:15 
QuestionBarking up the wrong tree? Pin
azonenberg8-Nov-07 4:19
memberazonenberg8-Nov-07 4:19 
AnswerRe: Barking up the wrong tree? Pin
Ashok Jaiswal14-Nov-07 16:51
memberAshok Jaiswal14-Nov-07 16:51 
GeneralPretty much unusable Pin
Scope30-Oct-07 4:09
memberScope30-Oct-07 4:09 
GeneralRe: Pretty much unusable Pin
Ashok Jaiswal30-Oct-07 7:47
memberAshok Jaiswal30-Oct-07 7:47 
GeneralToo wide Pin
DavidCrow29-Oct-07 10:29
mvpDavidCrow29-Oct-07 10:29 
GeneralRe: Too wide Pin
Ashok Jaiswal29-Oct-07 10:34
memberAshok Jaiswal29-Oct-07 10:34 
QuestionWhat improvement!! Pin
John A. Johnson25-Oct-07 5:24
memberJohn A. Johnson25-Oct-07 5:24 
AnswerRe: What improvement!! Pin
Ashok Jaiswal25-Oct-07 7:46
memberAshok Jaiswal25-Oct-07 7:46 
GeneralExcellent Article Pin
rajantawate1(http// 5:19
memberrajantawate1(http// 5:19 
GeneralRe: Excellent Article Pin
Ashok Jaiswal24-Oct-07 7:19
memberAshok Jaiswal24-Oct-07 7:19 
GeneralRe: Excellent Article Pin
NarendraSinghJTV8-Oct-09 1:00
memberNarendraSinghJTV8-Oct-09 1:00 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171020.1 | Last Updated 29 Oct 2007
Article Copyright 2007 by Ashok Jaiswal
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid