Windows程序设计之简单的动画效果(小球弹一弹)
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,构造一个矩形位图,位图内有一个带有阴影和紫色间隙的小球,程序使用定时器来控制小球的动作,实际上是每当接收到定时器消息时将位图通过BitBlt函数复制到客户区,每当小球碰撞到客户区上下左右四边时就反弹回
千家信息网最后更新 2025年01月25日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安全错误
数据库的锁怎样保障安全
php网站搭建数据库
高一网络安全征文
东兴软件开发系统
功能安全和软件开发
华为网络技术基础知识
如何找到数据库
接收数据服务器端口
北京网络安全宣传周
91连接服务器连接不上
vba数据库查询系统
药易通数据库安装
留言板入数据库
服务器为备份
pyqt5调用服务器api
网络安全和信息化 法律
我的世界蛋白的服务器
移动手机软件开发工程师
服务器访问本地sql数据库
我需要网络安全的画
数据库产品条码作为主键
数据库删除语句条件有变量
php网站搭建数据库
软件开发--面试笔试题集锦
网络安全中入侵
襄阳圈圈网络技术
测速服务器原理
唐山市软件开发
电力能源行业网络安全文章
晋中网络技术操作
网络安全学习实验室平台