平滑,3D,iTunes风格的 图像列表控件CListCtrl-CAlbumCtrl类

来源:互联网 发布:知乎为什么封号 编辑:程序博客网 时间:2024/06/03 08:31

翻译来源:https://www.codeproject.com/Articles/21006/Not-just-a-image-list-control-Neat-D-iTunes-style

作者:Ashok Jaiswal

图像列表控件显示3D中的所有图像,选择时动画化项目,并控制项目大小,透明度,位置和动画速度


下载AlbumViewerReleaseDemo.zip - 2,803.1 KB

下载AlbumViewerSrc.zip - 408.7 KB

截图 -  AlbumViewer.gif

介绍

灵感来自iTunes专辑列表控制。此图像列表控件允许您以新的3D方式显示图像。没有更无聊的图像一个接一个地显示,但附带一个很酷的动画。未选择项目的缩放级别可以是控件,也可以是阴影的高度,每个未选择项目的透明度,其位置和动画速度。

这对于在GUI丰富的应用程序中显示图像非常有用。控件是从CListCtrl类派生的,所以它可以被扩展,以支持传统的列表控件视图或者冷却动画3D视图。

背景

正如我提到的灵感是iTunes专辑控制。在这些变得越来越酷的周末之中,欣赏音乐,我想知道如何使用iTunes来平滑整洁的动画来显示图像,并采取了很好的控制,从而迎接挑战,发现它只需要大约10个代数方程,并且很好地利用了GDI +实现它。


此控件加载完整大小的图像,在演示中它使用的图像大到800x600,并通过高效使用GDI +,您可以动画,缩放和控制alpha,没有任何闪烁和非常顺利的方式。

这篇文章对于寻求有关使用GDI +绘画的更多信息的开发人员来说最有用。即使GDI +几乎需要所有的东西,但无法像iTunes一样绘制图像。它允许剪切图像,但不允许使图像的两侧的高度不同。我没有真正尝试使用矩阵变换,但我认为图像的动画和定位可以更好地使用它们。

使用代码

要在项目中使用控件,请添加AlubumCtrl.h和AlbumCtrl.cpp,在表单/对话框中添加列表控件,为类型为CAlbumCtrl的此列表控件创建一个成员变量,并在OnInitDialog或其他任何地方添加以下代码您要添加新项目到列表控件:
m_ctlAlbum.AddItem(L"images\\Water lilies.jpg");m_ctlAlbum.AddItem(L"images\\Sunset.jpg");m_ctlAlbum.AddItem(L"images\\Winter.jpg");m_ctlAlbum.AddItem(L"images\\Blue hills.jpg");m_ctlAlbum.SetCurrentItem(2);m_sldAlpha.SetRange(0,100);m_sldAnim.SetRange(0,100);m_sldShadow.SetRange(0,100);m_sldZoom.SetRange(0,100);m_sldElevation.SetRange(-300,100);m_sldElevation.SetPos(m_ctlAlbum.GetItemElevation());m_sldAlpha.SetPos(m_ctlAlbum.GetItemAlpha());m_sldAnim.SetPos(m_ctlAlbum.GetAnimSpeed());m_sldShadow.SetPos(m_ctlAlbum.GetItemShadow());m_sldZoom.SetPos(m_ctlAlbum.GetItemZoom());

计算项目位置

以下功能是放置控件和令人惊讶的最小代码部分的大多数导入功能。那么在它来到这之前,它确实需要大约4次迭代代码和代码的微调

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);}

绘图项目

这是控制中第二重要的功能。这将拾取项目图像,计算阴影宽度,将alpha应用于图像,并将alpha减少到阴影,如果需要,将文本放置在所选图像上。

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 )        return;    Bitmap bitmap(m_vecItems[nItem].wszItem.c_str());    CRect r;    GetClientRect(&r);    RectF rcWnd(r.left, r.top, r.Width(), r.Height());    if(!rcWnd.IntersectsWith(rc))        return;    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                            };    imgAttrb.SetColorMatrix(&bmpAlpha);    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);          colorTemp.SetValue(color.MakeARGB(             //(BYTE)(5*(iHeight/nRef-(iHeight-iRow))),              (BYTE)dAlpha,             color.GetRed(),             color.GetGreen(),             color.GetBlue()));          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)));     }}

幕后涉及数学

控制最感兴趣的部分是涉及定位和动画项目的数学。因为在中心选择项目的左侧和右侧放置/动画物品时存在不同的代数。

将项目置于控件中

计算任何项目的宽度

n = W  r / 100 n

计算任何物品的高度

n = H  r / 100 n

计算任何项目的Y位置

n = Y -Ñ 
Σ
 1
H / e  r / 100 

计算所选项目左侧项目的X位置

n = X -的n + 1 
Σ
 2
 r / 100 

计算所选项目右侧项目的X位置

n = X + W +n-1个
Σ
 1
 r / 100 i -的n + 1 
Σ
 1
 1-r / 100  r / 100 

哪里

H =所选项目的高度

W =所选项目的宽度

X =所选项目的X位置

Y =所选项目的Y位置

r =当前缩放级别,以%

e = Y的当前高程


动画控件中的项目

动画向左的项目

动画左侧的项目

ΔX= c  X n + 1 -X n / l 
n = X n +ΔXΔY 

= c  Y n + 1 -Y n / l 

n = Y n + 


ΔYΔW= c  W n + 1 -W n / 1 
n = W n +ΔWΔH 

= c  H n + 1 -H n / 1 
n = H n +ΔH

动画右侧的物品

ΔX= c  X n + 1 -X n / 1 
n-1 = X n +ΔXΔY 

= c  Y n + 1 -Y n / 1 
n-1 = Y n -ΔY 

ΔW= c  W n + 1 -W n / l 
n = W n -ΔWΔH 

= c  H n + 1 -H n / 1 
n = H n -ΔH

动画物品向右移动

动画左侧的项目



ΔX= c  X n + 1 -X n / l 
n = X n +ΔXΔY 

= c  Y n + 1 -Y n / l 

n = Y n + 


ΔYΔW= c  W n + 1 -W n / 1 
n = W n +ΔWΔH 

= c  H n + 1 -H n / 1 
n = H n +ΔH

动画右侧的物品


ΔX= c  X n + 1 -X n / I 
n = X n +ΔXΔY 

= c  Y n + 1 -Y n / 1 
n = Y n - 

ΔYΔW= c  W n-1 -W n / 1 
n = W n -ΔWΔH 

= c  H n-1 -H n / 1 
n = H n -ΔH

哪里

c =当前动画步骤

l =总动画步数计数



未来特点

计划添加视图切换按钮,以便用户可以切换到图标视图/列表视图/报告视图/相册视图


原创粉丝点击