C语言控制台窗口图形编程
设备句柄与窗口信息
用来标识Windows资源(如菜单、图标、窗口等)和设备等对象
在Windows操作系统下用C语言编写控制台的窗口界面首先
需要获取当前标准输入和标准输出设备的的句柄。通过调用函数
GetStdHandle可以获取当前标准输入以及输出设备的句柄。函数原型:
HANDLE GetStdHandle(DWORD nStdHandle);
/*
其中,nStdHandle可以是
STD_INPUT_HANDLE 标准输入设备句柄
STD_OUTPUT_HANDLE 标准输出设备句柄
STD_ERROR_HANDLE 标准错误设备句柄
*/
示例程序
#include <stdio.h>
#include <windows.h>
#include <conio.h>
int main(int argc,char *argv[])
{
HANDLE handle_out; //定义一个句柄
CONSOLE_SCREEN_BUFFER_INFO screen_info; //定义窗口缓冲区信息结构体
COORD pos = {0, 0}; //定义一个坐标结构体
handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
GetConsoleScreenBufferInfo(handle_out, &screen_info); //获取窗口信息
_getch(); //输入一个字符,不会显示到屏幕上
/*
向整个缓冲区填充字符'A'
其中填充的开始处为pos,坐标为{0, 0},也就是屏幕最左上角的字符处
填充个数为screen_info.dwSize.X(缓冲区宽度,也就是横坐标最大值加1) * screen_info.dwSize.Y(缓冲区高度,也就是纵坐标最大值加1)
因此可以达到向整个缓冲区填充字符'A'的效果
*/
FillConsoleOutputCharacter(handle_out, 'A', screen_info.dwSize.X * screen_info.dwSize.Y, pos, NULL);
CloseHandle(handle_out); //关闭标准输出设备句柄
return 0;
}
//程序中,COORD和CONSOLE_SCREEN_BUFFER_ INFO是wincon.h定义的控制台结构体类型
//原型如下
//坐标结构体
typedef struct _COORD
{
SHORT X;
SHORT Y;
}COORD;
//控制台窗口信息结构体
typedef struct _CONSOLE_SCREEN_BUFFER_INFO
{
COORD dwSize; //缓冲区大小
COORD dwCursorPosition; //当前光标位置
WORD wAttributes; //字符属性
SMALL_RECT srWindow; //当前窗口显示的大小和位置
COORD dwMaximumWindowSize; // 最大的窗口缓冲区大小
}CONSOLE_SCREEN_BUFFER_INFO;
窗口缓冲区的设置
几个控制台窗口操作的API函数,如下:
//获取控制台窗口信息
GetConsoleScreenBufferInfo();
//获取控制台窗口标题
GetConsoleTitle();
//更改指定缓冲区大小
SetConsoleScreenBufferSize();
//设置控制台窗口标题
SetConsoleTitle();
//设置控制台窗口信息
SetConsoleWindowInfo();
示例程序
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h>
#define N 255
int main()
{
HANDLE handle_out; //定义一个句柄
CONSOLE_SCREEN_BUFFER_INFO scbi; //定义一个窗口缓冲区信息结构体
COORD size = {80, 25}; //定义一个坐标结构体
char strtitle[N];
handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
GetConsoleScreenBufferInfo(handle_out, &scbi); //获得窗口缓冲区信息
GetConsoleTitle(strtitle, N); //获得当前窗口标题
printf("当前窗口标题为:%s\n", strtitle);
_getch();
SetConsoleTitle("控制台窗口操作"); //设置窗口标题为“控制台窗口操作”
GetConsoleTitle(strtitle, N); //获得当前窗口标题
printf("当前窗口标题为:%s\n", strtitle);
_getch();
SetConsoleScreenBufferSize(handle_out, size); // 重新设置缓冲区大小
_getch();
SMALL_RECT rc = {0, 0, 80-1, 25-1}; // 重置窗口位置和大小
SetConsoleWindowInfo(handle_out, 1, &rc);
CloseHandle(handle_out); //关闭标准输出设备句柄
return 0;
}
文本属性
设置文本属性的函数,原型如下
BOOL SetConsoleTextAttribute( // 设置WriteConsole等函数的字符属性
HANDLE hConsoleOutput, // 句柄
WORD wAttributes // 文本属性
);
示例程序
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
/*
基本文本属性
FOREGROUND_BLUE 蓝色
FOREGROUND_GREEN 绿色
FOREGROUND_RED 红色
FOREGROUND_INTENSITY 加强
BACKGROUND_BLUE 蓝色背景
BACKGROUND_GREEN 绿色背景
BACKGROUND_RED 红色背景
BACKGROUND_INTENSITY 背景色加强
COMMON_LVB_REVERSE_VIDEO 反色
*/
const WORD FORE_BLUE = FOREGROUND_BLUE; //蓝色文本属性
const WORD FORE_GREEN = FOREGROUND_GREEN; //绿色文本属性
const WORD FORE_RED = FOREGROUND_RED; //红色文本属性
const WORD FORE_PURPLE = FORE_BLUE | FORE_RED; //紫色文本属性
const WORD FORE_CYAN = FORE_BLUE | FORE_GREEN; //青色文本属性
const WORD FORE_YELLOW = FORE_RED | FORE_GREEN; //黄色文本属性
const WORD FORE_GRAY = FOREGROUND_INTENSITY; //灰色文本属性
const WORD BACK_BLUE = BACKGROUND_BLUE; //蓝色背景属性
const WORD BACK_GREEN = BACKGROUND_GREEN; //绿色背景属性
const WORD BACK_RED = BACKGROUND_RED; //绿色背景属性
const WORD BACK_PURPLE = BACK_BLUE | BACK_RED; //紫色背景属性
const WORD BACK_CYAN = BACK_BLUE | BACK_GREEN; //青色背景属性
const WORD BACK_YELLOW = BACK_RED | BACK_GREEN; //黄色背景属性
const WORD BACK_GRAY = BACKGROUND_INTENSITY; //灰色背景属性
int main()
{
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
SetConsoleTextAttribute(handle_out, FORE_BLUE);
printf("蓝色字符\n");
SetConsoleTextAttribute(handle_out, FORE_RED);
printf("红色字符\n");
SetConsoleTextAttribute(handle_out, FORE_GREEN);
printf("绿色字符\n");
SetConsoleTextAttribute(handle_out, FORE_PURPLE);
printf("紫色字符\n");
SetConsoleTextAttribute(handle_out, FORE_CYAN);
printf("青色字符\n");
SetConsoleTextAttribute(handle_out, FORE_YELLOW);
printf("黄色字符\n");
SetConsoleTextAttribute(handle_out, FORE_GRAY);
printf("灰色字符\n");
SetConsoleTextAttribute(handle_out, FORE_GREEN | FORE_BLUE | FORE_RED);
printf("白色字符\n");
SetConsoleTextAttribute(handle_out, BACK_BLUE);
printf("蓝色背景\n");
SetConsoleTextAttribute(handle_out, BACK_RED);
printf("红色背景\n");
SetConsoleTextAttribute(handle_out, BACK_GREEN);
printf("绿色背景\n");
SetConsoleTextAttribute(handle_out, BACK_PURPLE);
printf("紫色背景\n");
SetConsoleTextAttribute(handle_out, BACK_CYAN);
printf("青色背景\n");
SetConsoleTextAttribute(handle_out, BACK_YELLOW);
printf("黄色背景\n");
SetConsoleTextAttribute(handle_out, BACK_GRAY);
printf("灰色背景\n");
SetConsoleTextAttribute(handle_out, BACK_BLUE | BACK_RED | BACK_GREEN);
printf("白色背景\n");
SetConsoleTextAttribute(handle_out, BACK_GREEN | FORE_RED); //示例:绿色背景红色字符
printf("绿色背景与红色字符的混合\n");
SetConsoleTextAttribute(handle_out, FOREGROUND_INTENSITY | FORE_RED); //示例:亮红色字符
printf("亮色的生成,与加强色融合\n");
return 0;
}
文本输出
文本输出函数:
BOOL FillConsoleOutputAttribute( // 填充字符属性
HANDLE hConsoleOutput, // 句柄
WORD wAttribute, // 文本属性
DWORD nLength, // 个数
COORD dwWriteCoord, // 开始位置
LPDWORD lpNumberOfAttrsWritten // 返回填充的个数
);
BOOL FillConsoleOutputCharacter( // 填充指定数据的字符
HANDLE hConsoleOutput, // 句柄
TCHAR cCharacter, // 字符
DWORD nLength, // 字符个数
COORD dwWriteCoord, // 起始位置
LPDWORD lpNumberOfCharsWritten // 已写个数
);
BOOL WriteConsoleOutputCharacter( // 在指定位置处写指定数量的字符
HANDLE hConsoleOutput, // 句柄
LPCTSTR lpCharacter, // 字符串
DWORD nLength, // 字符个数
COORD dwWriteCoord, // 起始位置
LPDWORD lpNumberOfCharsWritten // 已写个数
);
表示区域的结构体
typedef struct _SMALL_RECT //表示矩形区域的结构体
{
SHORT Left; //左边界
SHORT Top; //上边界
SHORT Right; //右边界
SHORT Bottom; //下边界
} SMALL_RECT;
/*
微软官方的说法是
Left 区域的左上顶点的X坐标
Top 区域的左上顶点的Y坐标
Right 区域的右下顶点的X坐标
Bottom 区域的右下顶点的Y坐标
*/
示例程序
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h>
int main()
{
char *str = "Hello World!"; //定义输出信息
int len = strlen(str), i;
WORD shadow = BACKGROUND_INTENSITY; //阴影属性
WORD text = BACKGROUND_GREEN | BACKGROUND_INTENSITY; //文本属性
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
SMALL_RECT rc; //定义一个文本框输出区域
COORD posText; //定义文本框的起始坐标
COORD posShadow; //定义阴影框的起始坐标
//确定区域的边界
rc.Top = 8; //上边界
rc.Bottom = rc.Top + 4; //下边界
rc.Left = (csbi.dwSize.X - len) / 2 - 2; //左边界,为了让输出的字符串居中
rc.Right = rc.Left + len + 4; //右边界
//确定文本框起始坐标
posText.X = rc.Left;
posText.Y = rc.Top;
//确定阴影框的起始坐标
posShadow.X = posText.X + 1;
posShadow.Y = posText.Y + 1;
for (i=0; i<5; ++i) //先输出阴影框
{
FillConsoleOutputAttribute(handle_out, shadow, len + 4, posShadow, NULL);
posShadow.Y++;
}
for (i=0; i<5; ++i) //在输出文本框,其中与阴影框重合的部分会被覆盖掉
{
FillConsoleOutputAttribute(handle_out, text, len + 4, posText, NULL);
posText.Y++;
}
//设置文本输出处的坐标
posText.X = rc.Left + 2;
posText.Y = rc.Top + 2;
WriteConsoleOutputCharacter(handle_out, str, len, posText, NULL); //输出字符串
SetConsoleTextAttribute(handle_out, csbi.wAttributes); // 恢复原来的属性
CloseHandle(handle_out);
return 0;
}
文本移动
控制文本移动的函数
BOOL ScrollConsoleScreenBuffer( //文本移动函数
HANDLE hConsoleOutput, //句柄
const SMALL_RECT *lpScrollRectangle, //移动区域
const SMALL_RECT *lpClipRectangle, //裁剪区域,如果为NULL,那么将代表整个屏幕缓冲区
COORD dwDestinationOrigin, //移动到的位置,这个点将成为移动区域的左上顶点
const CHAR_INFO *lpFill //空出区域的填充字符
);
示例函数
#include <stdio.h>
#include <conio.h>
#include <Windows.h>
#include <stdlib.h>
int main()
{
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
CONSOLE_SCREEN_BUFFER_INFO csbi; //定义窗口缓冲区信息结构体
SMALL_RECT scroll; //定义移动区域
COORD pos = {0, 5}; //移动位置
CHAR_INFO chFill; //定义填充字符
GetConsoleScreenBufferInfo(handle_out, &csbi); //获得窗口缓冲区信息
//定义填充字符的各个参数及属性
chFill.Char.AsciiChar = ' ';
chFill.Attributes = csbi.wAttributes;
//输出文本
printf("00000000000000000000000000000\n");
printf("11111111111111111111111111111\n");
printf("22222222222222222222222222222\n");
printf("33333333333333333333333333333\n");
//确定区域
scroll.Left = 1;
scroll.Top = 1;
scroll.Right = 10;
scroll.Bottom = 2;
ScrollConsoleScreenBuffer(handle_out, &scroll, NULL, pos, &chFill); //移动文本
return 0;
}
光标操作
控制光标位置的函数
BOOL SetConsoleCursorPosition( //设置光标位置
HANDLE hConsoleOutput, //句柄
COORD dwCursorPosition //坐标
); //若函数调用成功则返回非0值
光标结构体原型、获得与设置光标信息的函数
typedef struct _CONSOLE_CURSOR_INFO //光标信息结构体
{
DWORD dwSize; //光标尺寸大小,范围是1~100
BOOL bVisible; //表示光标是否可见,true表示可见
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
BOOL GetConsoleCursorInfo( //获得光标信息
HANDLE hConsoleOutput, //句柄
PCONSOLE_CURSOR_INFO lpConsoleCursorInfo //光标信息,注意这是个指针类型
);
BOOL SetConsoleCursorInfo( //设置光标信息
HANDLE hConsoleOutput, //句柄
const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo //光标信息
);
示例程序
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <stdlib.h>
int main()
{
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); //获得标准输出设备句柄
CONSOLE_CURSOR_INFO cci; //定义光标信息结构体
GetConsoleCursorInfo(handle_out, &cci); //获得当前光标信息
_getch();
cci.dwSize = 1; //设置光标尺寸为1
SetConsoleCursorInfo(handle_out, &cci);
_getch();
cci.dwSize = 50; //设置光标尺寸为50
SetConsoleCursorInfo(handle_out, &cci);
_getch();
cci.dwSize = 100; //设置光标尺寸为100
SetConsoleCursorInfo(handle_out, &cci);
_getch();
cci.bVisible = false; //设置光标为不可见
SetConsoleCursorInfo(handle_out, &cci);
_getch();
return 0;
}