MFC和GDI+制作蝴蝶苍蝇飞舞小程序

   看到网上有个老外写的蝴蝶飞舞程序,一时兴起,开发个功能相似的小程序。
   实现功能:屏幕上有蝴蝶或苍蝇飞舞。素材是通过提取工具提取出来的。老外程序的网址记不清了。
   程序原理比较简单,本文仅供新手学习参考用。

先看效果:


下面来说说程序原理吧:

工程:VS2005,MFC(对话框)工程。
窗口:每个飞舞的元素(蝴蝶/苍蝇)各是一个窗口,这些窗口的父窗口是Desktop,这些窗口具有透明异形的属性,这些窗口的大小与元素大小相同,这些窗口随着元素的形状改变而变化。
元素:蝴蝶/苍蝇 随着动作的变化,GDI+也跟着绘制新的资源图片到窗口上。
动作:动作有2种,一种是元素自身的动作,即摆动翅膀飞舞、原地休息、原地摆动翅膀等动作。另一种动作是元素的移动,即元素在屏幕上任意方向飞舞移动。
动作原理:每个元素窗口都有一个定时器Timer,两种动作会根据自己的随机时间来选择随机的动作与运动方向。
元素动作类型:蝴蝶18种走法,苍蝇16种走法。分别是:不同的方向动作、原地动作。


用到的技术点:

窗口透明:
SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^0x80000);
窗口异形:
UpdateLayeredWindow(pDC, &ptWinPos, &sizeWindow, &m_dcBack, &ptSrc, 0, &m_Blend, 2);
GDI+:graphics.DrawImage、CDC 等。
托盘:Shell_NotifyIcon
菜单:TrackPopupMenu


关键代码与实现:

窗口透明设置:

    ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,0);
    //变窗口为透明类型
    DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE);
    if((dwExStyle&0x80000)!=0x80000)
        SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^0x80000);

创建画刷:

void CFlyWnd::MakeBkgndDC()
{
    CRect rtClient;
    GetClientRect(&rtClient);
    CDC *pDC = GetDC();

    CBitmap hBackground;
    hBackground.CreateCompatibleBitmap(pDC,rtClient.Width(),rtClient.Height());

    if(m_dcBack.m_hDC == NULL)
    {
        m_dcBack.CreateCompatibleDC(pDC);
    }
    CBitmap *pOldBmp = m_dcBack.SelectObject(&hBackground);
    pOldBmp->DeleteObject();

    hBackground.DeleteObject();
    ReleaseDC(pDC);
}

动作产生后,更新画刷:

void CFlyWnd::UpdateMemoDC()
{
    MakeBkgndDC();
    CRect rcClient;
    GetWindowRect(&rcClient);

    CDC * pDC = GetDC();
    if(m_dcBack.GetSafeHdc() == NULL)
        return;

    Gdiplus::Graphics graphics(m_dcBack.GetSafeHdc());

    if(m_nInectType == 0)
    {
        RectF rtGdiplus(0,0,m_InectSize.cx, m_InectSize.cy);
        //画刷新图标
        graphics.DrawImage(g_pFly[m_nIndex[0]][m_nIndex[1]], rtGdiplus, 0, 0, m_InectSize.cx, m_InectSize.cy, UnitPixel);

        POINT ptWinPos = {rcClient.left, rcClient.top};
        SIZE sizeWindow={m_InectSize.cx, m_InectSize.cy};//图片尺寸
        POINT ptSrc={0,0};
        UpdateLayeredWindow(pDC, &ptWinPos, &sizeWindow, &m_dcBack, &ptSrc, 0, &m_Blend, 2);
    }else if(m_nInectType ==1)
    {
        RectF rtGdiplus(0,0,m_InectSize.cx, m_InectSize.cy);
        //画刷新图标
        graphics.DrawImage(g_pButterFly[m_nIndex[0]][m_nIndex[1]], rtGdiplus, 0, 0, m_InectSize.cx, m_InectSize.cy, UnitPixel);

        POINT ptWinPos = {rcClient.left, rcClient.top};
        SIZE sizeWindow={m_InectSize.cx, m_InectSize.cy};//图片尺寸
        POINT ptSrc={0,0};
        UpdateLayeredWindow(pDC, &ptWinPos, &sizeWindow, &m_dcBack, &ptSrc, 0, &m_Blend, 2);
    }

    ReleaseDC(pDC);
}

动作的控制:

//由于此部分代码量比较大,请下载源程序参阅
SetTimer(1, m_nElapse, NULL);
....
void CFlyWnd::OnTimer(UINT nIDEvent) 
{
    if(m_nInectType == 0)
    {//苍蝇
      Step();
    }else if(m_nInectType == 1)
    {//蝴蝶
      ButterflyStep();
    }
}

void CFlyWnd::UpdateFlyPos(CRect rcNewPos)
{
    MoveWindow(&rcNewPos, FALSE);
}

源程序下载链接:

http://download.csdn.net/detail/xinsuiyishunjian/9561944

你可能感兴趣的:(C/C++/MFC,GDI+,mfc,透明窗口,异形窗口,GDI+,蝴蝶-苍蝇飞舞)