导语
这个想法是在初学C语言时出现的,当时想要实现动态的过程,用来优化程序的运行界面,奈何不了解Windows句柄,一直无法实现,直到学习了一些相关知识,成功把它实现出来了。不过发现实际意义并不大,仅仅是设计过程的有趣,因此将这个小功能模块分享出来,同时也作为自己学习过程的记录。
效果图
所需头文件
C++:
#include <iostream>
#include <Windows.h>
#include <time.h>
C语言请把iostream改成stdio.h,并更改函数中的输出部分
源代码
获取光标位置:
COORD getXY() //通过WindowsAPI函数获取光标的位置
{
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
//利用标准输出句柄获得光标坐标信息
return COORD{ pBuffer.dwCursorPosition.X, pBuffer.dwCursorPosition.Y };
//封装为表示坐标的COORD结构
}
获取缓冲区大小:
COORD getScrnInfo() //获取控制台窗口缓冲区大小
{
HANDLE hStd = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
CONSOLE_SCREEN_BUFFER_INFO scBufInf; //定义一个窗口缓冲区信息结构体
GetConsoleScreenBufferInfo(hStd, &scBufInf); //获取窗口缓冲区信息
return scBufInf.dwSize; //返回窗口缓冲区大小
}
移动光标位置:
void moveXY(COORD pstn)
{
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pstn);
//通过标准输出句柄控制光标的位置
}
清除部分屏幕内容:(C语言请自行改动输出部分)即:更改std::cout部分
void clearDisplay(COORD firstPst, COORD lastPst) //清除部分屏幕内容,从firstPst坐标到lastPst坐标之间的内容
{
int yDValue(lastPst.Y - firstPst.Y); //记录首末位置纵坐标差值,控制迭代次数
COORD size(getScrnInfo()); //记录目前控制台缓冲区大小
moveXY(firstPst); //移动光标到首位置
for (int y(0); y <= yDValue; y++) //一层循环控制清除行数
{
for (int x(firstPst.X); x <= size.X; x++) //二层循环避免重复清除
{
std::cout << ' '; //输出一个空格来覆盖原内容,达到清除效果
int px; //记录光标当前位置的横坐标
if (x != size.X)
px = x + 1;
else
px = 0;
if (y == yDValue&&px == lastPst.X) //与光标末位置作对比,达到末位置即退出循环
break;
}
}
moveXY(firstPst);
}
进度条图像显示:(C语言请自行改动输出部分)
void loading() //等待界面,模拟动态进度条过程
{
COORD headPst(getXY()); //记录最初位置,便于结束后清除进度条内容
HANDLE hStd(GetStdHandle(STD_OUTPUT_HANDLE));
CONSOLE_CURSOR_INFO cInfo;
GetConsoleCursorInfo(hStd, &cInfo); //获取光标信息的句柄
cInfo.bVisible = false; //修改光标可见性
SetConsoleCursorInfo(hStd, &cInfo); //设置光标不可见
std::cout << "请等待";
COORD firstPst; //存储光标坐标,为清除做铺垫
COORD lastPst;
int n(0); //模拟进度条数字
int m(0); //记录进度条方块总数
srand((unsigned)time(NULL)); //取时间作为随机数种子,避免伪随机数
while (n < 100) //达到较好的动态效果
{
m = n / 5;
n += rand() % 14 + 1;
if (n < 100)
{
for (int i(n / 5 - m); i>0; i--)
std::cout << "█";
firstPst = getXY(); //获取输出前坐标
std::cout << n << "%"; //输出百分比进度条
lastPst = getXY(); //获取输出之后的光标位置
}
else
{
n = 100; //最大值为100,达到则退出操作
std::cout << "█";
std::cout << n << "%";
lastPst = getXY();
break;
}
Sleep(80);
clearDisplay(firstPst, lastPst); //清除现有图形,重新绘制
}
clearDisplay(headPst, lastPst); //清除进度条图形
cInfo.bVisible = true; //光标可见性改为可见
SetConsoleCursorInfo(hStd, &cInfo);
}
总结
此小部件是本人学习过程中的一点小玩意,希望能对其他初学者有一点启发。
代码中所出现的Windows API函数或结构,请自行搜索,此处不做过多赘述。
学海无涯,力争上游 |