简单的动画效果:BOUNCE程序代码分析

来源:互联网 发布:黑马校对软件下载 编辑:程序博客网 时间:2024/04/29 19:27
/*---------------------------------------------------
BOUNCE.C -- Bouncing Ball Program
---------------------------------------------------*/

#include<windows.h>
#define ID_TIMER 1

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int nCmdShow)
{
    static TCHAR szAppName[] = TEXT("Bounce");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndcls;

    wndcls.style = CS_HREDRAW | CS_VREDRAW;
    wndcls.lpfnWndProc = WndProc;
    wndcls.cbClsExtra = 0;
    wndcls.cbWndExtra = 0;
    wndcls.hInstance = hInstance;
    wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
    wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndcls.lpszMenuName = NULL;
    wndcls.lpszClassName = szAppName;

    RegisterClass(&wndcls);

    hwnd = CreateWindow(szAppName,TEXT("Bounce Ball"),
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,CW_USEDEFAULT,
                        CW_USEDEFAULT,CW_USEDEFAULT,
                        NULL,NULL,hInstance,NULL);

    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
    static HBITMAP hBitmap;
    static int    cxClient,cyClient,xCenter,yCenter,cxTotal,cyTotal,
                cxRadius,cyRadius,cxMove,cyMove,xPixel,yPixel;

    HBRUSH hBrush;
    HDC hdc,hdcMem;
    int iScale;

    switch(iMsg)
    {
    case WM_CREATE:
        hdc = GetDC(hwnd);

        //获取用于画线的设备像素的相对宽度和高度(计算机像素一般为正方形像素,宽高比为1:1)
        xPixel = GetDeviceCaps(hdc,ASPECTX);
        yPixel = GetDeviceCaps(hdc,ASPECTY);
        ReleaseDC(hwnd,hdc);
        
        //设置定时器定时间隔为50ms
        SetTimer(hwnd,ID_TIMER,50,NULL);
        return 0;

    case WM_SIZE:

        //获取客户区逻辑宽和高,并计算客户区的中心位置
        xCenter = (cxClient = LOWORD(lParam)) / 2;
        yCenter = (cyClient = HIWORD(lParam)) / 2;
        
        //小球直径为客户区宽高中较小的十六分之一
        iScale = min(cxClient * xPixel,cyClient * yPixel) / 16;

        //水平和竖直方向的半径(以像素为单位),相对尺寸/单个像素的相对尺寸 = 此方向上的像素个数
        cxRadius = iScale / xPixel;
        cyRadius = iScale / yPixel;

        //设定移动的步长,水平和竖直方向同步
        cxMove = max(1,cxRadius / 2);
        cyMove = max(1,cyRadius / 2);

        //所需所需创建的位图的宽和高,在小球的四边,位图的尺寸要比球多出半径的一半
        //(如果不这样,小球边界就有可能碰触不到客户区的边就要反弹回去)
        cxTotal = 2 * (cxRadius + cxMove);
        cyTotal = 2 * (cyRadius + cyMove);

        if(hBitmap)
            DeleteObject(hBitmap);  //尺寸变化后,重绘之前要删除原来的位图

        hdc = GetDC(hwnd);
        hdcMem = CreateCompatibleDC(hdc);  //创建内存设备环境
        hBitmap = CreateCompatibleBitmap(hdc,cxTotal,cyTotal);  //创建新的与设备兼容的位图
        ReleaseDC(hwnd,hdc);

        SelectObject(hdcMem,hBitmap);
        Rectangle(hdcMem,-1,-1,cxTotal + 1,cyTotal + 1);  //内存中创建矩形框以容纳位图

        hBrush = CreateHatchBrush(HS_DIAGCROSS,0L);  //创建有45度交叉阴影的画刷
        SelectObject(hdcMem,hBrush);
        SetBkColor(hdcMem,RGB(0,255,255));  //设置背景色
        Ellipse(hdcMem,cxMove,cyMove,cxTotal - cxMove,cyTotal - cyMove);  //绘制小球,用上面的画刷和背景色填充小球
        DeleteDC(hdcMem);
        DeleteObject(hBrush);
        return 0;

    case WM_TIMER:
        if(!hBitmap)
            break;

        hdc = GetDC(hwnd);
        hdcMem = CreateCompatibleDC(hdc);
        SelectObject(hdcMem,hBitmap);

        //在相应位置绘制小球,小球总是以当前的(xCenter,yCenter)为中心,程序一开始时小球必定在客户区中心
        BitBlt(hdc,xCenter - cxTotal / 2,yCenter - cyTotal / 2,cxTotal,cyTotal,hdcMem,0,0,SRCCOPY);

        ReleaseDC(hwnd,hdc);
        DeleteDC(hdcMem);

        //移动最初的客户区坐标中心(xCenter,yCenter),此坐标移动后,小球会跟着移动
        //“+”“-”号控制小球的初始移动方向
        xCenter -= cxMove;
        yCenter += cyMove;

        //遇到边界,小球就向相反方向移动
        if((xCenter + cxRadius >= cxClient) || (xCenter - cxRadius <= 0))
            cxMove = -cxMove;
        if((yCenter + cyRadius >= cyClient) || (yCenter - cyRadius <= 0))
            cyMove = -cyMove;

        return 0;
        
    case WM_DESTROY:
        if(hBitmap)
            DeleteObject(hBitmap);  //删除位图
        KillTimer(hwnd,ID_TIMER);  //移除定时器
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd,iMsg,wParam,lParam);
}
C语言

0 0
原创粉丝点击