1.最常见的点号提示等待的动态效果图:
2.横杠原地旋转的等待动态效果图:
3.数字序号的不断提示循环的步骤动态效果图:
动态等待的效果图,是用于提高用户体验而产生的。如果一个提示始终不变,会让人感觉程序是不是卡死了。毕竟windows中这种卡死是很常见的,用动态循环提示用户,表示“我还活着!千万不要以为我死了哦!”。这样用户就心里有底,即使等待的时间长点也是可以的,因为用户知道,程序正在运行。
现在各种等待提示层出不穷,基本都是用图片的循环播放形式实现的。那么这样就需要图片显示和循环播放的支持。如果只是一个可选的提示,而你的环境下实现图片循环播放提示比较难的话,更多偏向于实用字符的循环输出实现动态等待提示效果。而且在DOS环境下,更别想用图片输出提示了。
即使是现在软件开发中,图片的动态提示很常见,然而字符的循环输出提示更简单更方便实现,效果也挺好,占用的资源也少。
我们这里是在Win32环境下实现的动态循环提示,所以是用TextOut来输出文字,用wsprintf来格式化文字到字符数组中,通过取模来实现循环输出不同的字符来实现动态的效果。
我们在WM_PAINT中来模拟实现。也就是说,我们要保证不停的触发WM_PAINT消息。当然我们会想到用计时器来不停的触发,这是很合适的。在计时器消息WM_TIMER中,我们只需要调用如下代码即可:
InvalidateRect(hwnd,NULL,TRUE);//让客户区重绘,并且要先擦除背景
擦除背景就是因为之前的输出不能还在本次输出中出现,因为那样留下的痕迹,会干扰本次输出的效果。点的输出方式是不断的增加点数,然而之前如果都输出了所有的点,然后后面的循环就始终看不到动态的增加点的效果。因为背景没有被擦除,你看到的点是之前已经输出来的。所以需要重绘将之前输出的东西都擦掉。对于InvalidateRect的背景擦除的详细讲述,请阅读《InvalidateRect无效矩形的图文分析和在字符串中移动光标》和《InvalidateRect是否删除背景效果分析以及实现下划线删除线》。
那么我们在WM_CREATE消息就开始启动计时器,这样计时器可以不断的产生WM_PAINT消息,输出的次数不断的累加,然后通过取模不断的循环,进而就选择了输出字符数组的不同的字符串,从而达到动态输出的效果。
你要实现自己的动态变化的效果,可以自己改变字符串数组的字符串,同时改变定义的COUNT宏,字符串数和宏的数字要一致哦。
下面是完整的计时器实现的完整代码:
#include "windows.h"
#include <tchar.h>
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
SetTimer(hwnd,0,100,NULL);
return 0;
case WM_PAINT:
{
#define COUNT 9
static int iCount=0;
static TCHAR Dot[COUNT][10]={_T("."),_T(".."),_T("..."),_T("...."),_T("....."),_T("......"),_T("......."),_T("........"),_T("........")};
//static TCHAR Dot[COUNT][10]={_T("-"),_T("/"),_T("|"),_T("\\")};
//static TCHAR Dot[COUNT][10]={_T("╱"),_T("┊"),_T("╲"),_T("┈")};
//static TCHAR Dot[COUNT][10]={_T("①"),_T("②"),_T("③"),_T("④"),_T("⑤"),_T("⑥")};
//static TCHAR Dot[COUNT][10]={_T("┹"),_T("┩"),_T("┱"),_T("┢")};
//static TCHAR Dot[COUNT][10]={_T("卍"),_T("卐")};
//输出提示
HDC hdc = BeginPaint(hwnd,&ps);
SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT));
TCHAR Tip[100]=_T("");
wsprintf(Tip,_T("正在扫描病毒%s"),Dot[iCount++%COUNT]);
TextOut(hdc,10,20,Tip,lstrlen(Tip));
EndPaint(hwnd,&ps);
}
return 0;
case WM_TIMER:
InvalidateRect(hwnd,NULL,TRUE);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
if(!RegisterClass(&wndClass)) return 0;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,0,0,600,500,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (TRUE)
{
if(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}