Windows程序设计之简单的动画效果(小球弹一弹)
发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,构造一个矩形位图,位图内有一个带有阴影和紫色间隙的小球,程序使用定时器来控制小球的动作,实际上是每当接收到定时器消息时将位图通过BitBlt函数复制到客户区,每当小球碰撞到客户区上下左右四边时就反弹回
千家信息网最后更新 2025年12月03日Windows程序设计之简单的动画效果(小球弹一弹)
构造一个矩形位图,位图内有一个带有阴影和紫色间隙的小球,程序使用定时器来控制小球的动作,实际上是每当接收到定时器消息时将位图通过BitBlt函数复制到客户区,每当小球碰撞到客户区上下左右四边时就反弹回来。下面代码有本人的理解注释可供参考,本人才疏学浅,不妥请见谅。效果图如下:
刚开始(初始其实是在客户区中心开始的,难截图就随便找张了,但理解就OK了,不碍事):
移动后:
#include#define ID_TIMER 1LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdline, int iCmdShow){ static TCHAR szAppName[] = TEXT("Bounce"); HWND hWnd;//窗口句柄 MSG mSg;//消息结构体 //创建窗口类 WNDCLASSEX wndClass; //设置窗口类各类属性 wndClass.cbSize = sizeof(WNDCLASSEX);//设置窗口类结构体大小 wndClass.cbClsExtra = 0;//窗口类尾部的一部分额外的空间 wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance;//应用程序当前的实例句柄 wndClass.hCursor = LoadCursor(NULL, IDC_HELP); wndClass.hIcon = NULL; wndClass.hIconSm = NULL; wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.lpfnWndProc = WndProc;//回调函数的地址(窗口消息处理程序) wndClass.lpszClassName = szAppName;//窗口类的名字,也就是窗口的标识,后面用于创建窗口函数的参数。 wndClass.lpszMenuName = NULL;//菜单的名字,没有为NULL。 wndClass.style = CS_HREDRAW | CS_VREDRAW;//窗口类的样式,它的值可以是窗口样式值的任意组合。CS_HREDRAW CS_VREDRAW,这个是垂直刷新和水平刷新,窗口尺寸改变,重画活动区域。 //注册对话框类 if (!RegisterClassEx(&wndClass)) { DWORD error_code = GetLastError(); MessageBox(NULL, TEXT("This program requires Windows NT!"), TEXT("NumRain"), MB_ICONERROR | MB_OKCANCEL); return 0; } hWnd = CreateWindow(szAppName, TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW, 200, 200, 800, 500, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); while (GetMessage(&mSg, NULL, 0, 0)) { TranslateMessage(&mSg); DispatchMessage(&mSg); } return (int)mSg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc,hdcMem; HBRUSH hBrush; int iScale; static HBITMAP hBitmap; static int cxClient, cyClient,xCenter,yCenter,cxTotal,cyTotal,cxRadius,cyRadius,cxMove,cyMove,xPixel,yPixel; switch (message) { case WM_CREATE: //初始化数据 hdc = GetDC(hwnd); xPixel = GetDeviceCaps(hdc, ASPECTX);//36 yPixel = GetDeviceCaps(hdc, ASPECTY);//36 ReleaseDC(hwnd, hdc); SetTimer(hwnd, ID_TIMER, 50, NULL); return 0; case WM_SIZE: //客户区中心的坐标 xCenter = (cxClient = LOWORD(lParam)) / 2;//392 yCenter = (cyClient = HIWORD(lParam)) / 2;//230 iScale = min(cxClient*xPixel, cyClient*yPixel) / 16;//1037 //球水平的半径和垂直的半径 cxRadius = iScale / xPixel;//28 cyRadius = iScale / yPixel;//28 //球水平的半径的一半和垂直的半径的一半 cxMove = max(1, cxRadius / 2);//14 cyMove = max(1, cyRadius / 2);//14 //位图宽和高 cxTotal = 2 * (cxRadius + cxMove);//84 cyTotal = 2 * (cyRadius + cyMove);//84 if (hBitmap) { DeleteObject(hBitmap); } hdc = GetDC(hwnd); //创建内存设备环境 hdcMem = CreateCompatibleDC(hdc); //创建与客户区兼容的GDI位图对象,该位图宽为cxTotal,高为cyTotal hBitmap = CreateCompatibleBitmap(hdc, cxTotal, cyTotal); ReleaseDC(hwnd, hdc); //将GDI位图对象选入内存设备环境,扩大了显示表面 SelectObject(hdcMem, hBitmap); //矩形的边框被绘制在位图之外 Rectangle(hdcMem, -1, -1, cxTotal + 1, cyTotal + 1); //创建阴影画刷 hBrush = CreateHatchBrush(HS_DIAGCROSS, 0L); SelectObject(hdcMem, hBrush); //设置阴影画刷间隔的空白处为紫色 SetBkColor(hdcMem, RGB(255, 0, 255)); /* 将小球绘制在位图的中心 值得注意的是,阴影画刷和阴影间隙的紫色效果都是在Rectangle函数之后,说明只有球才有阴影画刷和紫色间隙,而球外面的边空还是白色的。 */ 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); //如果画图细心分析,会发现位图中心,水平和垂直每移动cxMove个像素,都会有新的位图覆盖上一个位图的球,这就不会出现球的残影了 BitBlt(hdc, xCenter - cxTotal / 2, yCenter - cyTotal / 2, cxTotal, cyTotal, hdcMem, 0, 0, SRCCOPY); ReleaseDC(hwnd, hdc); DeleteDC(hdcMem); 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_CLOSE: if (IDOK == MessageBox(hwnd, TEXT("是否退出?"), TEXT("对话框"), MB_OKCANCEL | MB_DEFBUTTON1 | MB_ICONQUESTION)) { DestroyWindow(hwnd); } else { return 0; } case WM_DESTROY: if (hBitmap) { DeleteObject(hBitmap); } KillTimer(hwnd, ID_TIMER); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam);}
位图
客户
阴影
小球
内存
函数
半径
水平
环境
紫色
设备
程序
对象
消息
间隙
效果
句柄
名字
定时器
对话框
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
火元素网络技术公司招聘
麻友圈安全服务器
百分百网络技术有限公司
康耐得串口设备联网服务器接线
无锡环保网络技术销售厂家
网络安全法的重点是什么
计算机网络应用软件开发
网络安全文章宣传
mfc ado 数据库
威联通 登录失败 服务器无响应
数据库服务器最多带几个应用
数据库 慢查询
有关网络安全课件免费
自己搭建机房和云服务器
今穗北京网络技术有限公司
服务器如何自动获取ip
棋牌游戏用什么软件开发的
网络安全知识讲座活动方案
软件开发示例视频
OA协同软件开发
网络安全通信协议陈性元
东方道迩软件开发面试
网络安全基础期末试卷
面对网络安全威胁和风险
亿鹰科技是互联网公司吗
校园网络安全书籍
网络安全手抄报第一奖
互联网科技智能化
网络安全进展的四个意识
话务员招聘软件开发