背景
时间[2018年07月23日 中午]
在写windows控制台应用程序的时候,我们希望修改一下控制台窗口的大小以及位置等信息。
方法
方法一:使用cmd命令mode
语法: MODE CON[:] [COLS=c] [LINES=n]
指定控制台行数及列数,行、列的单位为字符。
C/C++中使用system()调用该命令,例如:
system(“mode con: cols=120 lines=40”);
要使用控制台窗口全屏化,首先要得到屏幕的大小,分别使用GetSystemMetrics(SM_CXSCREEN)和GetSystemMetrics(SM_CYSCREEN)获取屏幕的宽度和高度,单位为像素。由于mode con的单位是字符,需要将屏幕大小信息进行转换,因此我们又需要得到每个字符的宽和高所占用的像素数,可以使用GetCurrentConsoleFont()和GetConsoleFontSize()来获取。
示例代码:
/*******************************************************************************
* 获取控制台当前字体大小
******************************************************************************/
COORD get_font_size()
{
COORD font_size;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
/* 字体信息 */
struct CONSOLE_FONT
{
DWORD index;
COORD dim;
} cfi;
typedef COORD (WINAPI *PROCGETCONSOLEFONTSIZE)(HANDLE, DWORD);
typedef BOOL (WINAPI *PROCGETCURRENTCONSOLEFONT)(HANDLE, BOOL, struct CONSOLE_FONT*);
HMODULE hKernel32 = GetModuleHandle("kernel32");
PROCGETCONSOLEFONTSIZE GetConsoleFontSize = (PROCGETCONSOLEFONTSIZE)GetProcAddress(hKernel32,"GetConsoleFontSize");
PROCGETCURRENTCONSOLEFONT GetCurrentConsoleFont = (PROCGETCURRENTCONSOLEFONT)GetProcAddress(hKernel32,"GetCurrentConsoleFont");
GetCurrentConsoleFont(handle, FALSE, &cfi); /* 获取当前字体索引信息 */
font_size = GetConsoleFontSize(handle, cfi.index); /* 获取当前字体宽高信息[字符宽度及高度所占像素数] */
return font_size;
}
/*******************************************************************************
* 最大化展示控制台窗口
******************************************************************************/
void full_screen()
{
HWND hwnd = GetForegroundWindow();
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); /* 标准输出缓冲区句柄 */
int cx = GetSystemMetrics(SM_CXSCREEN); /* 屏幕宽度 */
int cy = GetSystemMetrics(SM_CYSCREEN); /* 屏幕高度 */
COORD size = get_font_size();
char cmd[32] = { 0 };
sprintf(cmd, "MODE CON: COLS=%d LINES=%d", cx / size.X, cy / size.Y);
system(cmd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
到目前为止,代码可以运行了,但运行效果并不尽如人意,比如,我不想让控制台窗口的标题栏、状态栏、边框、滚动条等展示出来。在网上搜索了一翻,发现一种解决方案,是将屏幕的宽、高信息添加一个固定的数值,比如300,最后使用MoveWindow()函数设置窗口的左上角位置,即设置了一个大小为标题栏高度的偏移量,如-33,将标题栏放在了可视区之外。这种方法在win8.1上是可行的,但在win10中无效,只能另辟蹊径了。
方法二:使用windows api
相关函数:
GetWindowLong() 用于获取窗口信息
SetWindowLong() 用于设置窗口信息
SetWindowPos() 设置窗口起始位置及大小
要了解更详细的使用说明,可以查看官方文档。
示例代码:
/*******************************************************************************
* 全屏控制台窗口
* 取消标题栏及边框
******************************************************************************/
void full_screen()
{
HWND hwnd = GetForegroundWindow();
int cx = GetSystemMetrics(SM_CXSCREEN); /* 屏幕宽度 像素 */
int cy = GetSystemMetrics(SM_CYSCREEN); /* 屏幕高度 像素 */
LONG l_WinStyle = GetWindowLong(hwnd,GWL_STYLE); /* 获取窗口信息 */
/* 设置窗口信息 最大化 取消标题栏及边框 */
SetWindowLong(hwnd,GWL_STYLE,(l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
运行结果[win10 + vc6]:
附:
使用api修改控制台缓冲区大小
SetConsoleScreenBufferSize() 设置控制台缓冲区大小
示例代码
/*******************************************************************************
* 设置控制台窗口起始位置,缓冲区大小及窗口大小
* top : 左上角X坐标
* left : 左上角Y坐标
* width :宽度 单位 字符
* height: 高度 单位 字符
******************************************************************************/
void full_screen(int top, int left, SHORT width, SHORT height)
{
COORD size;
HWND hwnd = GetForegroundWindow();
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD font_size = get_font_size();
width = width > GetSystemMetrics(SM_CXMIN) ? width : GetSystemMetrics(SM_CXMIN);
height = height > GetSystemMetrics(SM_CYMIN) ? height : GetSystemMetrics(SM_CYMIN);
size.X = width;
size.Y = height;
SetConsoleScreenBufferSize(handle, size);
SetWindowPos(hwnd, HWND_TOP, top, left, size.X * font_size.X, size.Y * font_size.Y, 0);
}