现在的位置: 首页 > 综合 > 正文

windows动画窗体

2013年06月16日 ⁄ 综合 ⁄ 共 3977字 ⁄ 字号 评论关闭

文章转自:http://www.cppblog.com/shly/archive/2011/10/16/158412.html 

同往常一样,先放一章效果图,这鸭子是会飞的哦。

效果类似常见的QQ宠物、360精灵之类的。

不说废话了,还是说重点。

==================================================
   要实现这种效果,我的第一想法便是通过SetWindowRGN设置不规则窗体,然后更新。
显然,这样是最容易想到的,但是也不由的有点担心效率,最终我也通过这种方式,实现了一个,
正如担心的一样,每秒6帧的速度偶尔会出现闪烁(当然我的本本可能不是很给力- -。)。
   这种方式就是通过载入的位图,获取每个像素点,并生成相应的HRGN,每帧动画一个。
然后通过计时器切换,由于效果不是很好,在此就不贴代码了。

   既然不能通过SetWindowRGN,那还能怎么做呢?其实windows自身已经给了我们一个
处理这种位图窗口的API,而且还可以实现透明,一说到透明很多人都应该知道是那个API了。

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

-->Syntax

BOOL SetLayeredWindowAttributes(          HWND hwnd,
    COLORREF crKey,
    BYTE bAlpha,
    DWORD dwFlags
);
Parameters

hwnd
[
in] Handle to the layered window. A layered window is created by specifying WS_EX_LAYERED when creating the window with the CreateWindowEx function or by setting WS_EX_LAYERED via SetWindowLong after the window has been created.
crKey
[
in] COLORREF structure that specifies the transparency color key to be used when composing the layered window. All pixels painted by the window in this color will be transparent. To generate a COLORREF, use the RGB macro.
bAlpha
[
in] Alpha value used to describe the opacity of the layered window. Similar to the SourceConstantAlpha member of the BLENDFUNCTION structure. When bAlpha is 0, the window is completely transparent. When bAlpha is 255, the window is opaque.
dwFlags
[
in] Specifies an action to take. This parameter can be one or more of the following values.
LWA_COLORKEY
Use crKey 
as the transparency color.
LWA_ALPHA
Use bAlpha to determine the opacity of the layered window.
Return Value

If the function succeeds, the 
return value is nonzero. 
If the function fails, the 
return value is zero. To get extended error information, call GetLastError.


其实这个函数在以前也经常用到,但主要是用它来实现透明,根本没想到它还可以实现不规则窗体。
看了MSDN你应该知道了吧,其实通过设置第二个颜色属性便可过滤掉窗体中指定的某种颜色,达到
不规则窗体的效果。

设置透明色的代码如下:再此将白色设置为透明。

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

-->HINSTANCE hInstance=(HINSTANCE)LoadLibrary("user32.dll");
        
if (hInstance)
        
{
            typedef BOOL(WINAPI 
*pFun)(HWND,COLORREF,BYTE,DWORD);     
            pFun  fun  
=  NULL;       
            fun
=(pFun)GetProcAddress(hInstance, "SetLayeredWindowAttributes");   
            SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) 
| 0x80000);
            
if (fun)
            
{
                fun(hWnd, RGB(
255255255), 00x1);
            }

            FreeLibrary(hInstance);
        }

知道如何处理不规则窗体后剩下的就简单了,在此我用的一半游戏中的(4*4)行走图做的。
只需要在绘制的时候通过改变绘制区域坐标来控制显示的位置达到动画的效果。
其中m_nX,m_nY分别是横向帧数 和 竖向的帧数 在此为 4 * 4

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

-->void OnPaint(CDCHandle /**//*dc*/)
    
{
        CPaintDC dc(
*this);
        CDC bmpDC;
        CBitmapHandle bmpOld;
        CRect rtClient;

        GetClientRect(
&rtClient);
        
        bmpDC.CreateCompatibleDC(dc);
        bmpOld 
= bmpDC.SelectBitmap(m_bmpBox);

        
int nSubX = m_nWidth / m_nX;
        
int nSubY = m_nHeight / m_nY;

        dc.BitBlt(
00, nSubX, nSubY, bmpDC, m_nCurX * nSubX, 
            m_nCurY 
* nSubY, SRCCOPY);

        bmpDC.SelectBitmap(bmpOld);
    }

剩下就是一些辅助的功能了:m_nCurX m_nCurY 分别只是当前横向第几帧 和 纵向的第几帧

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

--> /**//**
     * 实现移动窗口
     
*/

    UINT OnNcHitTest(CPoint point)
    {

        
return HTCAPTION;
    }


    
/**//**
     * 更新动画
     
*/

    
void OnTimer(UINT_PTR nIDEvent)
    
{
        
if (nIDEvent == ANIMA_TIMER)
        
{
            m_nCurX 
= (++m_nCurX) % m_nX;
            RedrawWindow();
        }

    }


    
/**//**
     * 改变方向
     
*/

    
void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    
{
        
switch (nChar)
        
{
        
case VK_LEFT: m_nCurY = 1break;
        
case VK_RIGHT: m_nCurY = 2break;
        
case VK_UP: m_nCurY = 3break;
        
case VK_DOWN: m_nCurY = 0break;
        
case VK_ESCAPE:OnClose();break;
        }

    }

好了,结束,虽然没啥技术含量,但也可以打发下无聊的时间。
以后有好玩的东西我也会更新在此。

抱歉!评论已关闭.