【C语言】Win 32 API——一部分内容详解!!!

【C语言】Win 32 API------一部分内容详解!!!

前言

在我们学完了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)

本期资料来自于:

https://legacy.cplusplus.com/

以及:

https://learn.microsoft.com/zh-cn/windows/win32/api/

相关推荐
郑州光合科技余经理6 小时前
定制开发实战:海外版外卖系统PHP全栈解决方案
java·服务器·开发语言·javascript·git·uni-app·php
郝学胜-神的一滴6 小时前
Linux线程编程:从原理到实践
linux·服务器·开发语言·c++·程序人生·设计模式·软件工程
重生之我在番茄自学网安拯救世界6 小时前
网络安全中级阶段学习笔记(七):Web 安全之文件上传漏洞笔记1(包含upload-labs-master靶场前三关实战)
笔记·学习·web安全·文件上传漏洞·网安基础
走在路上的菜鸟6 小时前
Android学Dart学习笔记第十五节 类
android·笔记·学习·flutter
..空空的人6 小时前
C++基于protobuf实现仿RabbitMQ消息队列---技术认识2
服务器·数据库·c++·网络协议·gtest·异步·protobuf
Chen--Xing6 小时前
LeetCode 11.盛最多水的容器
c++·python·算法·leetcode·rust·双指针
DeltaTime6 小时前
二 线性变换, 齐次坐标, 变换组合, 变换分解, 3D变换
c++·3d·图形渲染
良木生香6 小时前
【数据结构-初阶】详解线性表(3)---双链表
c语言·数据结构·蓝桥杯
XiaoHu02076 小时前
C++的IO流
开发语言·c++