VC实现图片移动(动画效果)

VC实现图片移动(动画效果)

更新日期:2010-12-15
代码下载:demo.zip (请不要直接使用迅雷下载)

测试环境:VC6.0+WinXP
图片预览:

━━━━━━━━━━━━━━━━━━━━━━━━


以下代码演示如何实现透明图片(或者一般图片)在背景图上移动效果。

一、原理简介:
    1.我们把所以图画到一个内存DC里,然后在Blt到屏幕,就是所谓的双缓冲了。
    2.在内存DC里画图时,先把背景图画到内存DC,再画上前景需要移动的图片就可以了

二、具体到我们下面的例子:
    1.定义2个CDrawBitmap对象,分别加载背景位图和前景移动的小飞机。
        CDrawBitmap g_bmp1("4244123431.bmp");
        CDrawBitmap g_bmp2("plane.bmp");

    2.鼠标按下移动,或者接收到时钟消息时就实现双缓冲。
        虽然代码有点“繁琐”,但记得我们关心的
        主要是下面代码中hMemDC。所有绘图代码都在这里进行。

        你经常不是这样调用的吗:
            //屏幕上打印字体,画矩形
            HDC hdc=::GetDC(m_hWnd);
            ::TextOut(hdc.......);
            ::RectangleRect(hdc......);
            ::ReleaseDC(m_hWnd,hdc) ;

        而在双缓冲里,只需把所有需要用到屏幕hdc的函数中的hdc替换成hMemDC,如:
            //屏幕上打印字体,画矩形
            ::TextOut(hMemDC.......);
            ::RectangleRect(hMemDC......);

        具体到我们这里的动画,就是:
            g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC
            g_bmp2.DrawTransparent(hMemDC,point.x-50,point.y-100); //画移动的前进小图片

        画好后再调用BitBlt把内存hMemDC所有画好的东西拷贝到屏幕hScrDC
            BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY);

希望对你有所帮助,谢谢!愿一切吉祥,阿弥陀佛!

 


/****************************************************************************
CDrawBitmap封装了一些画图片的函数。

调用如下:
    CDrawBitmap g_bmp1("D://My Documents//My Pictures//风景图片//4244123431.bmp");
    g_bmp1.Draw(m_hWnd);
    
    CDrawBitmap g_bmp2("D://My Documents//My Pictures//风景图片//plane.bmp");
    g_bmp2.DrawTransparent(m_hWnd);

    CDrawBitmap g_bmp3("D://My Documents//My Pictures//风景图片//jzg2.bmp");
    g_bmp3.DrawTransparent(m_hWnd);

****************************************************************************/

//使用TransparentBlt需要添加 #pragma comment(lib,"msimg32.lib")
#pragma comment(lib,"msimg32.lib")

class CDrawBitmap
{
private:
    HBITMAP m_bitmap;
    int m_bitmap_cx;
    int m_bitmap_cy;
public:    
    CDrawBitmap()    {} 
    CDrawBitmap(TCHAR * PicturePath)    {    LoadPicture(PicturePath);    } 
    CDrawBitmap(WORD ResourceID)        {    LoadResource(ResourceID);    } 

    ~CDrawBitmap()    { ::DeleteObject(m_bitmap);}    

    bool LoadPicture(TCHAR * PicturePath)
    {
        m_bitmap=(HBITMAP)LoadImage(NULL,        //应用程序实例            
            PicturePath,                    //路径
            IMAGE_BITMAP,                
            0,                                //如果不置0,则此参数指定m_bitmap的宽(位图被拉伸)        
            0,                                //如果不置0,则此参数指定m_bitmap的高(位图被拉伸)        
            LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);
        
        if (!m_bitmap)
            return false;

        BITMAP bmp;   
        GetObject(m_bitmap,sizeof(BITMAP),(LPSTR)&bmp);  
        m_bitmap_cx=bmp.bmWidth;
        m_bitmap_cy=bmp.bmHeight;

        return true;
    }

    bool LoadResource(WORD ResourceID)
    {
        m_bitmap=LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE (ResourceID) );    

        if (!m_bitmap)
            return false;

        BITMAP bmp;   
        GetObject(m_bitmap,sizeof(BITMAP),(LPSTR)&bmp);  
        m_bitmap_cx=bmp.bmWidth;
        m_bitmap_cy=bmp.bmHeight;

        return true;
    }

    void Draw(HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100)
    {
        HDC hScrDC=GetDC(hWnd);                                //创建屏幕DC
        Draw(hScrDC,x,y,width,height);
        ::ReleaseDC(hWnd,hScrDC) ;                            //释放屏幕DC
    }

    void Draw(HDC hScrDC,int x=0,int y=0,int width=100,int height=100)
    {
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        ::SelectObject(hMemDC,m_bitmap);                        //把位图选进内存DC
        BitBlt(hScrDC,x,y,width,height,hMemDC,0,0,SRCCOPY);    //内存DC映射到屏幕DC
        ::DeleteDC(hMemDC) ;                                //删除内存DC
    }


    void DrawTransparent(HWND hWnd=NULL,int x=0,int y=0)
    {
        HDC hScrDC=GetDC(hWnd);                                //创建屏幕DC
        DrawTransparent(hScrDC,x,y);
        ::ReleaseDC(hWnd,hScrDC) ;                            //释放屏幕DC
    }

    //不进行拉伸处理,如需要,请自行修改代码TransparentBlt中的参数
    //使用TransparentBlt需要添加 #pragma comment(lib,"msimg32.lib")
    void DrawTransparent(HDC hScrDC,int x=0,int y=0,UINT crTransparent=RGB(255,255,255))
    {
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        ::SelectObject(hMemDC,m_bitmap);                        //把位图选进内存DC
        ::TransparentBlt(hScrDC,x,y,m_bitmap_cx,m_bitmap_cy,hMemDC,0,0,m_bitmap_cx,m_bitmap_cy,crTransparent);
        ::DeleteDC(hMemDC) ;                                //删除内存DC
    }


    void DrawStretch(HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100)
    {
        HDC hScrDC=GetDC(hWnd);                                //创建屏幕DC
        DrawStretch(hScrDC,x,y,width,height);
        ::ReleaseDC(hWnd,hScrDC) ;                            //释放屏幕DC
    }

    void DrawStretch(HDC hScrDC=NULL,int x=0,int y=0,int width=100,int height=100)
    {
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        ::SelectObject(hMemDC,m_bitmap);                        //把位图选进内存DC
        SetStretchBltMode(hScrDC,COLORONCOLOR);        //一定要先调用这个
        StretchBlt(hScrDC,x,y,width,height,hMemDC,0,0,m_bitmap_cx,m_bitmap_cy,SRCCOPY);    //内存DC映射到屏幕DC
        ::DeleteDC(hMemDC) ;                                //删除内存DC
    }
};


void DrawBitmap(HBITMAP m_bitmap,HDC hScrDC,int x=0,int y=0,int width=100,int height=100)
{
    HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
    ::SelectObject(hMemDC,m_bitmap);                        //把位图选进内存DC
    BitBlt(hScrDC,x,y,width,height,hMemDC,0,0,SRCCOPY);    //内存DC映射到屏幕DC
    ::DeleteDC(hMemDC) ;                                //删除内存DC
}

void DrawBitmap(HBITMAP m_bitmap,HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100)
{
    HDC hScrDC=GetDC(hWnd);                                //创建屏幕DC
    DrawBitmap(m_bitmap,hScrDC,x,y,width,height);
    ::ReleaseDC(hWnd,hScrDC) ;                            //释放屏幕DC
}



CDrawBitmap g_bmp1("4244123431.bmp");
CDrawBitmap g_bmp2("plane.bmp");


//stop timer
void CDemoDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
    KillTimer(1);
    CDialog::OnLButtonDown(nFlags, point);
}

//begin timer;
void CDemoDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
    SetTimer(1,10,NULL);
    CDialog::OnLButtonUp(nFlags, point);
}

void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
    if (nFlags&MK_LBUTTON)
    {
        /***************************************************
        步骤一:创建。
        1.主要关心的是CreateCompatibleBitmap的后两个参数,
        你往内存hMemDC里画的东东就在这个这个范围内
        2.如果你已经有一个屏幕dc了,就去掉
        HDC hScrDC=::GetDC(m_hWnd)和::ReleaseDC(m_hWnd,hScrDC) 这两行代码,
        直接使用已有的屏幕dc代替下面代码中的所有hScrDC
        **************************************************/
        HDC hScrDC=::GetDC(m_hWnd);                            //创建屏幕DC
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,600,600); //创建兼容位图
        HBITMAP OldBitmap=(HBITMAP)::SelectObject(hMemDC,bitmap);    //把位图选进内存DC
        
        
        /***************************************************
        步骤二:绘图。
        使用hMemDC绘图,就像你平时绘图一样操作
        绘图代码主要在这里完成
        **************************************************/
        
        
        g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC
        g_bmp2.DrawTransparent(hMemDC,point.x-50,point.y-100); //画移动的前进小图片
        
        
        /***************************************************
        步骤三:将内存DC图拷贝到屏幕DC上进行显示。
        1.BitBlt前4个参数nXDest,nYDest,nWidth,nHeight.确定屏幕DC上的一个矩形区域。
        将来要显示在屏幕上的图形范围就在这4个参数所决定的矩形区域内。
        2.BitBlt后面2个坐标参数x,y指定从内存hMemDC的哪个位置开始拷贝到屏幕DC上
        **************************************************/
        BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY);    
        
        
        /***************************************************
        步骤四:最后的收尾工作(删除或释放资源)
        **************************************************/
        ::SelectObject(hMemDC,OldBitmap); 
        ::DeleteObject(bitmap);    //释放位图所占Memory,不释放也可以(The system automatically deletes these resources when the process that created them terminates)    
        ::DeleteDC(hMemDC) ;            //删除内存DC
        ::ReleaseDC(m_hWnd,hScrDC) ;    //释放屏幕DC
    }

    CDialog::OnMouseMove(nFlags, point);
}

void CDemoDlg::OnTimer(UINT nIDEvent) 
{
    
        /***************************************************
        步骤一:创建。
        1.主要关心的是CreateCompatibleBitmap的后两个参数,
        你往内存hMemDC里画的东东就在这个这个范围内
        2.如果你已经有一个屏幕dc了,就去掉
        HDC hScrDC=::GetDC(m_hWnd)和::ReleaseDC(m_hWnd,hScrDC) 这两行代码,
        直接使用已有的屏幕dc代替下面代码中的所有hScrDC
        **************************************************/
        HDC hScrDC=::GetDC(m_hWnd);                            //创建屏幕DC
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,600,600); //创建兼容位图
        HBITMAP OldBitmap=(HBITMAP)::SelectObject(hMemDC,bitmap);    //把位图选进内存DC
        
        
        /***************************************************
        步骤二:绘图。
        使用hMemDC绘图,就像你平时绘图一样操作
        绘图代码主要在这里完成
        **************************************************/
        
        static int x=0;
        x+=1;
        if (x>400)
            x=0;

        g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC
        g_bmp2.DrawTransparent(hMemDC,x,100); //画移动的前进小图片
        
        
        /***************************************************
        步骤三:将内存DC图拷贝到屏幕DC上进行显示。
        1.BitBlt前4个参数nXDest,nYDest,nWidth,nHeight.确定屏幕DC上的一个矩形区域。
        将来要显示在屏幕上的图形范围就在这4个参数所决定的矩形区域内。
        2.BitBlt后面2个坐标参数x,y指定从内存hMemDC的哪个位置开始拷贝到屏幕DC上
        **************************************************/
        BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY);    
        
        
        /***************************************************
        步骤四:最后的收尾工作(删除或释放资源)
        **************************************************/
        ::SelectObject(hMemDC,OldBitmap); 
        ::DeleteObject(bitmap);    //释放位图所占Memory,不释放也可以(The system automatically deletes these resources when the process that created them terminates)    
        ::DeleteDC(hMemDC) ;            //删除内存DC
        ::ReleaseDC(m_hWnd,hScrDC) ;    //释放屏幕DC

    CDialog::OnTimer(nIDEvent);
}



━━━━━━━━━━━━━━━━━━━━━━━━

推荐:

谈老师的BLOG (佛教大德)
狮姐的博客(狮子窝,学佛与灵魂之探究) 
大方广(学习传统文化)
慈善点击(轻松一点,行善积德,何乐不为) 
电影《地球公民》(揭示不为人知的一面)  
心向光明 远离邪淫(现世警钟,不可不看) 
戒淫(上篇)(正淫节欲,戒除邪淫) 
戒淫(中篇)(纵欲之乐,忧患随之) 
公民教育——命由我造

 

 


你可能感兴趣的:(VC实现图片移动(动画效果))