控制台API函数----HANDLE、SetConsoleCursorPosition、SetConsoleTextAttribute
控制台API函数
调用相关文本界面控制的API函数,这些函数可分为三类。
一、用于控制台窗口控制的函数(包括窗口的缓冲区大小、窗口前景字符和背景颜色、窗口标题、大小和位置等);
二、用于控制台输入输出的函数(包括字符属性操作函数);
三、其他的函数并为最后一类。
(注意:当不需要使用句柄时需要调用CloseHandle()来关闭输入输出句柄,就像malloc申请的内存空间最后需要用free函数释放掉一样,后面会介绍CloseHandle的具体使用方法)
可以理解为句柄就是一种资源,就像内存一样,用完就得释放,一个程序创建的句柄数是有限制的,时间如果比较短可能看不出来什么问题,时间一旦长了,可能就会导致程序无法继续创建句柄(意思是系统的句柄资源用光了)
控制台窗口控制API函数(部分)
GetConsoleScreenBufferInfo 获取控制台窗口信息
GetConsoleTitle 获取控制台窗口标题
ScrollConsoleScreenBuffer 在缓冲区中移动数据块(更改指定缓冲区大小)
SetConsoleScreenBufferSize 更改指定缓冲区大小
SetConsoleTitle 设置控制台窗口标题
SetConsoleWindowInfo 设置控制台窗口信息
(函数前半部分很相似SetConsole(设置控制台)、GetConsole(获取控制台),只需要记后面就方便多了)
在程序中还必须包含头文件windows.h
1、HANDLE
本篇随笔主要内容是各个函数的使用,想了解句柄HANDLE的读者可以先看下这篇文章:深入了解Windows句柄到底是什么
HANDLE在WindNT.h中的声明为
typedef void *HANDLE;
从上面可以看出HANDLE是一种无类型指针,句柄是处理对象的一个接口,你可以通过句柄去操作程序中所涉及的对象。在windows中,句柄是和对象一一对应的32位无符号整数值,对象可以映射到唯一的句柄,
句柄也可以映射到唯一的对象windows需要向程序员提供必要地编程接口,在这些接口中,允许程序员访问,创建和销毁对象,但是,出于封装的考虑,windows并不想向程序员返回指针
如果作数据的话,句柄这种方式则允许你按自己的方式直接操作数据,但windows又不向你直接暴露数据。直接操作数据是程序员需要的,不暴露数据是windows所需要的,句柄封装方式实现了各取所需。
(很好的找到了满足双方需且的平衡点)
“句柄”是Windows最常用的概念。它通常用来标识Windows资源(如菜单、图标、窗口等)和设备等对象。虽然可以把句柄理解为是一个指针变量类型,但它不是对象所在的地址指针,而是作为Windows系统内部表的索引值来使用的。
代码示例:
HANDLE hOut;
2、GetStdHandle函数
函数功能:获取指定的标准设备的句柄,使用GetStdHandle需要一个参数,参数的取值有三种
STD_INPUT_HANDLE----标准输入句柄
STD_OUTPUT_HANDLE----标准输出句柄
STD_ERROR_HANDLE----标准错误句柄
先回顾一下文件操作中输入输出重定向的概念
在默认情况下:
标准输入(stdin)----键盘
标准输出(stdout)----显示器(屏幕)
标准错误(stderr)----显示器(屏幕)
(注意:标准输出句柄和标准错误句柄默认情况下都是对应的屏幕)
代码示例:
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */
HANDLE hOut可理解为:定义了一个变量名为hOut的变量,变量的类型为HANDLE(句柄)类型
3、COORD
COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标。其在头文件WinCon.h中的定义为:
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
从上面可以看出 COORD是一个结构体类型,结构体里面有两个短整形变量X、Y,用来表示光标的坐标
(注意:X是横坐标(horizontal coordinate),Y是纵坐标(vertical coordinate)不要与二维数组的坐标表示搞混了,二维数组第一维是纵坐标,第二维是横坐标)
代码示例:
COORD pos = {x, y};/* x是横坐标 y是纵坐标 */
4、CONSOLE_CURSOR_INFO
控制台光标信息,先去WinCon.h里面去瞧一瞧声明是什么样子的
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
从上面可以看出,CONSOLE_CURSOR_INFO是一个结构体,结构体里面有两个成员一个是dwSize表示光标的大小(取值范围1~100),第二个是成员是bVisible表示光标是否可见((TRUE)可见,(FALSE)不可见)
5、SetConsoleCursorInfo函数
函数功能:设置控制台光标信息,使用这个函数需要两个参数,第一个参数的类型HADNLE,第二个参数的类型CONSOLE_CURSOR_INFO *类型
代码示例:
#include <stdio.h>
#include <windows.h> void ConsoleCursor (); int main()
{ return ;
} void ConsoleCursor ()
{
HANDLE hOut;
CONSOLE_CURSOR_INFO cur; /* 定义了一个结构体变量 cur*/ cur.dwSize = ; /* 光标大小设置为100 */
hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */
SetConsoleCursorInfo(hOut, &cur); /* 设置控制台光标信息 */
}
上面的代码中,ConsoleCursor这个函数中没有设置光标是否可见(默认为可见),读者如果想设置为光标不可见将bVisible赋值为0就可以了(0(光标不可见)、非0(光标可见))
(注意:dwSize的取值范围是1~100,如果赋值的大小超过100则参数失效,光标大小为默认大小)
运行效果图:
在设置光标不可见时发现了一个有趣的现象,如果只把光标设置为不可见cur.bVisible = 0,而不对光标的大小赋值的话,用SetConsoleCursorInfo是不起作用的
代码如下:
#include <stdio.h>
#include <windows.h> void ConsoleCursor (); int main()
{
printf("***");
ConsoleCursor();
return ;
} void ConsoleCursor ()
{
HANDLE hOut;
CONSOLE_CURSOR_INFO cur; /* 定义了一个结构体变量 cur*/ //cur.dwSize = 100; /* 光标大小设置为100 */
cur.bVisible = ; /* 光标设置为不可见 */
hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */
SetConsoleCursorInfo(hOut, &cur); /* 设置控制台光标信息 */
}
运行效果如下:
光标并没有隐藏,想要隐藏光标需要给光标大小cur.dwSize赋值,赋值范围1~100(如果赋值大小超过1~100,那么赋值无效,光标还是无法隐藏---这也算个坑了 要注意一下)
给cur赋初值也可这样写
CONSOLE_CURSOR_INFO cur = {, };
6、SetConsoleCursorPosition函数
SetConsoleCursorPosition这个函数的功能是:设置控制台光标坐标(Set--设置、Console--控制台、Cursor--光标、Position--坐标,还算蛮好记的),使用这个函数需要两个参数:第一个参数类型为HANDLE,第二个参数类型为COORD
代码示例:
#include <stdio.h>
#include <windows.h> void gotoxy(int x, int y);
void ConsoleCursor (); int main()
{
printf("***");
gotoxy(,);
printf("***"); return ;
} void gotoxy(int x, int y)
{
COORD pos = {x, y};/* x是横坐标 y是纵坐标 */
HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */
SetConsoleCursorPosition(hOut,pos); /* 设置控制台光标坐标(设备句柄, 光标坐标) */
}
运行效果图:
7、CONSOLE_SCREEN_BUFFER_INFO
控制台窗口缓冲区信息,先到WinCon.h头文件中瞧一下声明部分
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO;
这个比上面CONSOLE_CURSOR_INFO(控制台光标信息)的成员多了一些,一个一个成员来看
第一个成员:
COORD dwSize;
dwSize缓冲区的宽度X和高度Y
第二个成员:
COORD dwCursorPosition;
dwCursorPosition当前光标在缓冲区中的坐标
第三个成员:
WORD wAttributes;
wAttributes文本的属性(前景色、背景色等信息)
第四个成员:
SMALL_RECT srWindow;
srWindow当前窗口显示的大小和位置
第五个成员:
COORD dwMaximumWindowSize;
dwMaximumWindowSize最大的窗口缓冲区大小
8、GetConsoleScreenBufferInfo函数
函数功能:获取控制台窗口缓冲区信息,使用这个函数需要两个参数,第一个参数HANDLE类型,第二参数CONSOLE_SCREEN_BUFFER_INFO*类型
使用这个函数就可以得到控制台缓冲区的一些有意思的信息了,下面来看一下可以得到哪些参数
代码示例:
#include <stdio.h>
#include <windows.h> void TextAttribute(); /* 设置前景色、后景色、获取控制台信息 */ int main()
{
printf("***");
TextAttribute();
return ;
}
/* Function: 设置前景色后景色和获取控制台信息 */
void TextAttribute ()
{
HANDLE hOut;
CONSOLE_SCREEN_BUFFER_INFO scr; hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标准输出句柄 */
GetConsoleScreenBufferInfo(hOut, &scr);
printf("当前光标:\n横坐标=%d 纵坐标=%d\n", scr.dwCursorPosition.X, scr.dwCursorPosition.Y);
printf("缓冲区最大:宽=%d,高=%d\n",scr.dwMaximumWindowSize.X, scr.dwMaximumWindowSize.Y);
printf("缓冲区 宽=%d 高=%d\n",scr.dwSize.X, scr.dwSize.Y);
printf("底部=%d 顶部=%d 左=%d 右=%d", scr.srWindow.Bottom, scr.srWindow.Top, scr.srWindow.Left, scr.srWindow.Right);
printf("",scr.wAttributes);
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE); /* 设置控制台颜色,前景色为蓝色*/
SetConsoleTextAttribute(hOut, BACKGROUND_RED); /* 背景色为红色 */
}
运行结果:
关于上面这些参数可以在控制台的默认值里面找到对应的值(底部和右的值需要在窗口最大的宽度下-1,这里跟数组的下标有点相似,窗口大小也是从0开始的)
9、SetConsoleTextAttribute函数
SetConsoleTextAttribute这个函数的功能是:设置控制台文本属性(颜色),可以设置前景色FOREGROUND(文本颜色)和背景色BACKGROUND(看厌了DOS控制台的黑白色,终于可以换个颜色了(┬_┬))
使用SetConsoleTextAttribute需要两个参数(句柄, 属性),第二个参数没写成颜色是因为SetConsoleTextAttribute还可以高亮显示,现在我们去WinCon.h头文件里面去瞧一瞧,看看第二个参数有哪些是可以用的
#define FOREGROUND_BLUE 0x0001 // text color contains blue.
#define FOREGROUND_GREEN 0x0002 // text color contains green.
#define FOREGROUND_RED 0x0004 // text color contains red.
#define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
#define BACKGROUND_BLUE 0x0010 // background color contains blue.
#define BACKGROUND_GREEN 0x0020 // background color contains green.
#define BACKGROUND_RED 0x0040 // background color contains red.
#define BACKGROUND_INTENSITY 0x0080 // background color is intensified.
#define COMMON_LVB_LEADING_BYTE 0x0100 // Leading Byte of DBCS
#define COMMON_LVB_TRAILING_BYTE 0x0200 // Trailing Byte of DBCS
#define COMMON_LVB_GRID_HORIZONTAL 0x0400 // DBCS: Grid attribute: top horizontal.
#define COMMON_LVB_GRID_LVERTICAL 0x0800 // DBCS: Grid attribute: left vertical.
#define COMMON_LVB_GRID_RVERTICAL 0x1000 // DBCS: Grid attribute: right vertical.
#define COMMON_LVB_REVERSE_VIDEO 0x4000 // DBCS: Reverse fore/back ground attribute.
#define COMMON_LVB_UNDERSCORE 0x8000 // DBCS: Underscore.
从上面的代码中可以看出前景色FOREGROUND和后景色BACKGROUND都只提供了三原色(红RED、绿GREEN、蓝BLUE)和颜色加强,后面的7个参数这里不再详述
代码示例:
#include <stdio.h>
#include <windows.h> void gotoxy(int x, int y);
void ConsoleCursor ();
void TextAttribute(); int main()
{
printf("***\n");
TextAttribute();
printf("***"); return ;
} void TextAttribute ()
{
HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE); /* 设置控制台颜色,前景色为蓝色*/
SetConsoleTextAttribute(hOut, BACKGROUND_RED); /* 背景色为红色 */
}
运行效果
也可在SetConsoleTextAttribute中同时设置前景色和后景色,代码如下,效果和上图相同
SetConsoleTextAttribute(hOut, FOREGROUND_BLUE|BACKGROUND_RED); /* 设置控制台颜色,前景色为蓝色,背景色为红色*/
10、GetConsoleTitle函数和GetConsoleTitleA函数
GetConsoleTitle函数功能是:获取控制台标题,使用这个函数需要两个参数,第一个是LTSPR类型,第二个是DWORD类型
GetConsoleTitleA函数功能和上面相同,使用时参数有点区别,第一个是LPSTR类型,第二个是DWORD类型
代码示例:
#include <stdio.h>
#include <windows.h> void ConsoleTitle(); /* 获取控制台标题 */
int main()
{
ConsoleTitle();
return ;
} /* Function: 获取控制台标题 */
void ConsoleTitle()
{
char Title[]; SetConsoleTitleA("My title");
GetConsoleTitleA(Title,);
puts(Title);
}
运行效果:
11、CloseHandle函数
这个函数和fclose很相似这里就不再赘述了
控制台API函数----HANDLE、SetConsoleCursorPosition、SetConsoleTextAttribute的更多相关文章
- mfc 调用Windows的API函数实现同步异步串口通信(源码)
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
- API函数ShellExecute与ShellExecuteEx用法
ShellExecute: 1.函数功能:你可以给它任何文件的名字,它都能识别出来并打开它.2.函数原型: HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpO ...
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- C#中导入Win32 API函数
C#中导入Win32 API的方法: 1.引用命名空间 using System.Net.Security; using System.Runtime.InteropServices; 2. [Dll ...
- 初识API函数
我之前是一个只会编写数值计算的程序的OIer,但我并不甘于这种现状,于是我编写了我的第一个使用API函数的C++程序,开发平台是VS2012: // ConsoleApplication.cpp : ...
- [转]SQLITE3 C语言接口 API 函数简介
SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...
- 替换应用程序exe图标,主要使用BeginUpdateResource,UpdateResource API函数
替换应用程序exe图标,主要使用的API函数是BeginUpdateResource(),UpdateResource(),EndUpdateResource()来使用自定义的ico文件类替换exe程 ...
- 用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle)完成文件拷贝程序(初级版)
文件拷贝程序 程序类型:Console 参数:源文件名 目的文件名 要求:1.只能使用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle ...
- API函数
1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同 ...
随机推荐
- OneZero第三周第五次站立会议(2016.4.8)
1. 时间: 15:10--15:25 共计15分钟. 2. 成员: X 夏一鸣 * 组长 (博客:http://www.cnblogs.com/xiaym896/), G 郭又铭 (博客:http ...
- centos6中搭建tomcat
一.安装jdk [root@tomcat ~]# yum -y list java* Loaded plugins: fastestmirror, security Loading mirror sp ...
- idea运行项目时报Error:java无效的源发行版:1.8
如果你安装的是JDK1.7,而在file->project structure中设置的是language level是8的话,就会出现这个错误提示:无效的源发行版:8. 解决办法:将语言级别改为 ...
- SQL错误
一.mybatis框架XML错误 1.ORA-00918: 未明确定义列:SQL语句中列明重复,或者定义不明确(关联查询时两张表都有要区分开列明) 2.无效的列类型: 1111 :a.传入数据漏传一 ...
- WEB应用支持RESTFUL风格方法
REST概念 Restful就是一个资源定位及资源操作的风格.不是标准也不是协议,只是一种风格.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. REST风格 资源:互联网所有的事物 ...
- c# devexpress 多个窗口
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Excel2007VBA数组和工作表及单元格的引用
动态数组使用: https://zhidao.baidu.com/question/1432222709706721499.html 使用Redim动态数组即可. 1 2 3 4 5 6 7 8 Su ...
- IntelliJ IDEA 2017版 spring-boot 2.0.3 邮件发送搭建,概念梳理 (二)
第二部分 邮件发送历史 一.第一封邮件 1.1969年10月,世界上的第一封电子邮件 1969年10月世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短 ...
- DDR中的一些知识点说明(ODT,ZQ校准,OCT,TDQS)
ODT ( On-DieTermination ,片内终结)ODT 也是 DDR2 相对于 DDR1 的关键技术突破,所谓的终结(端接),就是让信号被电路的终端吸 收掉,而不会在电路上形成反射, 造成 ...
- Ajax传数据到servlet
//jsp代码 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" ...