【C语言】Win 32 API------一部分内容详解!!!
- 前言
- [一、Win 32 API介绍](#一、Win 32 API介绍)
- 二、控制台程序
-
- [1. 定义](#1. 定义)
- 2.system函数------操作控制台程序
- 三、GetStdHandle函数
- 四、CONSOLE_CURSOR_INFO结构体
- 五、GetConsoleCursorInfo函数
- 六、SetConsoleCursorInfo函数
- [七 控制台屏幕上的坐标(COORD结构体)](#七 控制台屏幕上的坐标(COORD结构体))
- [八 SetConsoleCursorPosition函数](#八 SetConsoleCursorPosition函数)
- 九、GetAsyncKeyState函数
- 结语
前言
在我们学完了C语言的基础知识后,现在可以开始着手写一些简单的小游戏了
但是,要想通过键盘来控制人物的移动,我们该怎么办呢?
好像我们之前的学习中没有涉猎
所以在讲制作小游戏前,我们先要学习一个新的东西
它就是Win 32 API
一、Win 32 API介绍
Win32 API(也称为 Windows API)是 Windows 应用的本机平台。
Windows系统除了协调应用程序的执行、分配内存、管理资源之外的同时也是一个很大的服务中心,这个服务中心提供了各种各样的服务(每一种服务就是一个函数),这些函数可以帮助应用程序开启视窗、描绘图形、使用周边设备等目的,因为这些函数服务的对象是应用程序(Application),因此被称为Application Programming Interface,简称API。此 API 最适合需要直接访问系统功能和硬件的桌面应用,可用于所有桌面应用,并且 32 位和 64 位 Windows 通常支持相同的功能。
WIN 32 API就是Microsoft Windows32平台的应用程序编程接口。
上面的介绍一句话就是:
Win 32 APL 里面有很多函数,调用他们我们就可以实现游戏人物的移动等等东西
但注意:
调用时要加头文件<Windows.h>
下面我们会讲解一部分关于Win 32 API的知识来帮助大家完成一些简易的小游戏
二、控制台程序
1. 定义
定义:在Windows中运行的黑框程序(命令提示符窗口)
这个就是我们电脑上的cmd,在搜索中搜cmd就可以出来了

我们可以用命令来进行窗口设置:
使用
mode con cols=100 lines=30命令设置窗口大小(设置为100列×30行)
使用title 贪吃蛇命令设置窗口标题
这样就可以简易地创建一个游戏窗口啦
结果:

但是我们想要在VS2022编译器中用代码来操作控制台程序怎么办呢?
2.system函数------操作控制台程序
在我们的编译器中,可以用sysytem函数来操作控制台程序
头文件:
system函数头文件------<Windows.h>
语法:
system(" 要实现的命令 ");
代码演示:(内有注释,不懂就看)
c
#include <stdio.h>
#include<Windows.h>
int main()
{
//设置窗口大小
system("mode con cols=100 lines=30");
//设置标题
system("title ZORE_C 的贪吃蛇");
//将程序进行暂停以免程序结束
//方便观察结果
system("pause");
return 0;
}
运行结果:

下面我们就要在控制台程序上进行操作
三、GetStdHandle函数
1.简介
功能:
获取标准设备的句柄(输入/输出/错误)
语法:
HANDLE WINAPI GetStdHandle( _In_ DWORD nStdHandle );
2.句柄
那什么是句柄呢?
句柄,可以理解为是一个指针,可以将标准设备的地址存起来
当下次你要操作这个标准设备时就调用该句柄
该句柄就可以找到标准设备并进行操作
3.参数
其中,GetStdHandle函数参数为标准设备
参数_In_ DWORD nStdHandle的取值可为下列值之一:

4.返回值
返回值:
HANDLE类型(本质是void指针)
5.演示
下面我们就用函数来获取STD_OUTPUT_HANDLE标准输出的句柄
其中houtput就是句柄
代码演示:
c
//获取句柄
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//获取STD_OUTPUT_HANDLE标准输出的句柄
四、CONSOLE_CURSOR_INFO结构体
1.简介
功能:
一个结构体,里面包含有关控制台游标的信息。
语法:
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
2.游标
那游标是什么呢?
在控制台上,可以看到一闪一闪的类似光标的东西,这就是游标
如下图:

3.结构体成员
dwSize
由游标填充的字符单元格的百分比。 此值介于 1 和 100 之间
光标外观各不相同,范围从完全填充单元格到显示为单元格底部的水平线
bVisible
游标的可见性
如果游标可见,则此成员为TRUE。
如果游标不可见,则此成员为FALSE。
4.演示
如下图:
在控制台上,默认游标的大小是25%(左边游标),而100%的游标(右边游标)
默认的可见性当然也是TRUE(可见)

五、GetConsoleCursorInfo函数
1.简介
功能:
检索有关指定控制台屏幕缓冲区的游标大小和可见性的信息
语法:
BOOL WINAPI GetConsoleCursorInfo(
_In_ HANDLE hConsoleOutput,
_Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
2. 参数
_In_ HANDLE hConsoleOutput
控制台屏幕缓冲区的句柄(就是我们刚刚讲的句柄)
_Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
指向 CONSOLE_CURSOR_INFO 结构体的指针
该结构体接收有关控制台游标的信息。(就是我们刚刚讲的游标信息的结构体)
3.返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。
4.演示
现在,我们先创建一个
CONSOLE_CURSOR_INFO结构体变量用于存放默认的游标信息
然后,用GetConsoleCursorInfo函数检索有关指定控制台屏幕缓冲区的游标大小和可见性的信息
最后打印在屏幕上
代码演示:(内有注释,不懂就看)
c
#include <stdio.h>
#include<Windows.h>
int main()
{
//获取句柄
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//获取STD_OUTPUT_HANDLE标准输出的句柄
//定义一个包含游标信息的结构体
CONSOLE_CURSOR_INFO cursor_info = { 0 };
//检索句柄指定控制台屏幕缓冲区的游标大小和可见性的信息
GetConsoleCursorInfo(houtput, &cursor_info);
//打印出大小的值
printf("游标大小为%d%%\n\n", cursor_info.dwSize);
//将程序进行暂停以免程序结束
//方便观察结果
system("pause");
return 0;
}
运行结果:

可以看到,由于游标默认的值是25%,故打印出25
六、SetConsoleCursorInfo函数
1.简介
功能:
为指定的控制台屏幕缓冲区设置光标的大小和可见性。
语法:
BOOL WINAPI SetConsoleCursorInfo(
_In_ HANDLE hConsoleOutput,
_In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);
2. 参数
_In_ HANDLE hConsoleOutput
控制台屏幕缓冲区的句柄 (前面讲的)
_In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
指向 CONSOLE_CURSOR_INFO 结构的指针 (前面讲的)
该结构为控制台屏幕缓冲区的光标提供新的规范。
3.返回值
如果该函数成功,则返回值为非零值
如果函数失败,则返回值为零
4.演示
现在,我们先创建一个
CONSOLE_CURSOR_INFO结构体变量用于存放默认的游标信息
然后,用GetConsoleCursorInfo函数检索有关指定控制台屏幕缓冲区的游标大小和可见性的信息
接着,修改CONSOLE_CURSOR_INFO结构体变量中的值
再用SetConsoleCursorInfo函数设置有关指定控制台屏幕缓冲区的游标大小和可见性的信息
最后打印在屏幕上
=代码演示:(内有注释,不懂就看)
c
#include <stdio.h>
#include<Windows.h>
int main()
{
//获取句柄
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//获取STD_OUTPUT_HANDLE标准输出的句柄
//定义一个包含游标信息的结构体
CONSOLE_CURSOR_INFO cursor_info = { 0 };
//检索句柄指定控制台屏幕缓冲区的游标大小和可见性的信息
GetConsoleCursorInfo(houtput, &cursor_info);
//将结构体中光标大小改为60%
cursor_info.dwSize = 60;
//设置有关指定控制台屏幕缓冲区的游标大小和可见性的信息
SetConsoleCursorInfo(houtput, &cursor_info);
//打印出新大小的值
printf("游标的新大小为%d%%\n\n", cursor_info.dwSize);
//将程序进行暂停以免程序结束
//方便观察结果
system("pause");
return 0;
}
运行结果:

可以看到,我们修改成功,游标大小被修改为了60%
另外,这个还可以修改游标的可见性,大家可自行尝试
七 控制台屏幕上的坐标(COORD结构体)
1.控制台的坐标系
要注意:
在我们的控制台上的坐标系,与我们数学上的传统坐标系不一样
如图:

2.不一样的坐标系(注意!!!)
在我们的控制台上的坐标系中,有一个很重要的点:
X轴的每个单位长度为1个普通字符的长度
而Y轴的每个单位长度为2个普通字符的长度
如图:

3.COORD结构体
功能:
定义控制台屏幕缓冲区中字符单元的坐标。 坐标系 (0,0) 的原点位于缓冲区的顶部左侧单元格。
语法:
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
成员:
X:水平坐标或列值
Y:垂直坐标或行值
演示:
定义并初始化一个COORD结构体
COORD pos = { 30,10 };
八 SetConsoleCursorPosition函数
1.简介
功能:
设置指定控制台屏幕缓冲区中的光标位置。
语法:
BOOL WINAPI SetConsoleCursorPosition(
_In_ HANDLE hConsoleOutput,
_In_ COORD dwCursorPosition
);
2. 参数
_In_ HANDLE hConsoleOutput
控制台屏幕缓冲区的句柄 (前面讲的)
_In_ COORD dwCursorPosition
指定新光标位置(以字符为单位)的 COORD 结构 (前面讲的)
坐标是屏幕缓冲区字符单元的列和行
坐标必须位于控制台屏幕缓冲区的边界以内
3.返回值
如果该函数成功,则返回值为非零值
如果函数失败,则返回值为零
4.演示
现在,我们可以先在
COODR结构体中存放要设置的光标
然后调用SetConsoleCursorPosition函数设置光标位置
代码演示:(内有注释,不懂就看)
c
#include <stdio.h>
#include<Windows.h>
int main()
{
//获取句柄
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//获取STD_OUTPUT_HANDLE标准输出的句柄
//在`COODR结构体`中存放要设置的光标
COORD pos = { 20,10 };
//调用`SetConsoleCursorPosition`函数设置光标位置
SetConsoleCursorPosition(houtput, pos);
//将程序进行暂停以免程序结束
//方便观察结果
system("pause");
return 0;
}
运行结果:
可以见得,光标先是定位到了(20,10)处,然后再打印接下来的东西

九、GetAsyncKeyState函数
1.简介
功能:
确定调用函数时按键是是否按下
以及上次调用GetAsyncKeyState后是否按下了该键。
语法:
SHORT GetAsyncKeyState( [in] int vKey );
2.参数
[in] int vKey
类型:int
一个虚拟密钥代码
3.虚拟密钥代码
Virtual-Key 代码
在键盘上,每个键都有一个对应的虚拟值
将这个虚拟值传给函数,该函数可以通过返回值来分辨该按键的状态
例如:(一部分)
下表显示了系统使用的虚拟键代码的符号常量名称、十六进制值和鼠标或键盘等效项,这些代码按数字顺序列出。
由于虚拟密钥代码有很多,大家可以自行查看,下面是链接:
https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
4.返回值
类型: SHORT
1 . 若返回的数据中,最高位为1,则说明该键现在的状态是按下
2 . 若返回的数据中,最高位为0,则说明该键现在的状态是没按下
3 . 若返回的数据中,最低位为1,则说明该键之前被按下过
4 . 若返回的数据中,最低位为0,则说明该键之前没被按下过
(二进制中) (特别注意按下和按下过)
5. 演示
现在,我们写一段代码来判断空格键是否被按下过
若返回的数据中,最低位为1,则说明该键之前被按下过
为了判断最低为是什么,我们可以将返回值 按位与1(&1)
结果是1最低位就是1;否则是0
(并且,为了方便按键,我们给系统Sleep休眠100ms)
运行代码:(内有注释,不懂就看)
c
#include <stdio.h>
#include<Windows.h>
int main()
{
//为了方便按键,我们给系统休眠100ms
Sleep(100);
//传入空格的虚拟值码,判断空格是否被按下
short ret = GetAsyncKeyState(VK_SPACE);
while (1)
{
if ((ret & 1) == 1)
{
printf("空格被按下过\n");
}
else
{
printf("空格没被按下过\n");
}
}
return 0;
}
运行结果:
(在Sleep代码运行完前按下空格)

可以看到,代码持续打印,说明空格之前被按下过
看到这里,我们已经学会了Win 32 API的一小部分知识
之后我们就可以开始着手设计一些简易游戏的代码了
当然,如果你想要了解更多更全的 Win 32 API 知识
可以去微软的官网(小编也是在那里查找的资料哦)
链接: https://learn.microsoft.com/zh-cn/windows/win32/api/
结语
OK,本期Win 32 API的一部分内容详解到这里就结束了
下一期我会手把手教你完成贪吃蛇游戏,请敬请期待
本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!!
新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!!
支持一下(三连必回QwQ)
本期资料来自于:

以及:
