首页 > 代码库 > 控制台基础概念实例

控制台基础概念实例

上一篇文章 控制台基础概念 介绍了控制的基本构成,以及一些操作处理。这一部分以实际代码为主,给出控制台使用的几个例子。

以main函数作为入口函数的程序都是控制台程序,最简单的控制台程序就是Hello World的程序。这里不给出了。

GUI程序可以使用以下几种方式使用控制台:

  • 在调用CreateProcess时使用CREATE_NEW_CONSOLE标志。(默认情况下,待启动进程为控制台程序时不推荐使用该参数,因为无法确定用户输入是有哪个控制台处理的)
  • 通过 AttachConsole函数附加到一个已经存在的控制台。
  • 未附加到控制台的程序可通过AllocConsole函数创建控制台。(GUI进程默认不会和控制台关联。若使用DETACHED_PROCESS参数调用CreateProcess启动一个控制台进程,则会创建一个无控制台的控制台进程。)

GUI程序可使用FreeConsole函数来释放控制台。一个控制台程序可以通过GetConsoleProcessList函数获取所有与其关联的进程列表。

控制台程序提供以下函数,用于改变控制台属性:

GetConsoleScreenBufferInfo获得窗口大小、屏幕缓冲大小和颜色属性
SetConsoleWindowInfo设置控制台窗口大小
SetConsoleScreenBufferSize设置控制台屏幕缓冲大小
SetConsoleTextAttribute设置控制台字符属性
SetConsoleTitle设置控制台标题
GetConsoleTitle获取控制台标题

实例a 控制台参数获取及设置

本实例说明如何获取和设置控制台相关参数,例如设置和获取标题栏、设置和获取控制台显示窗口位置等。

代码如下: 

// 显示及设置控制台相关参数// 1. 设置及获取控制台标题栏// 2. 获取屏幕输出缓冲的参数// 3. 设置控制台窗口大小// 4. 设置控制台屏幕缓冲大小// 建议使用visual studio 2005以上版本编译,使用unicode编码#include <windows.h>#include <iostream>using std::wcout;using std::endl;int _tmain(int argc, _TCHAR* argv[]){    std::wcout.imbue(std::locale("chs"));    // 获取和设置控制台标题栏    DWORD title_need_size = 1024; // 64k    TCHAR * console_title = new TCHAR[title_need_size+1];    memset(console_title, 0, (title_need_size+1)*sizeof(TCHAR));    DWORD title_size = GetConsoleTitle(console_title, title_need_size);    if (0 == title_size)    {        wcout << "调用GetConsoleTitle异常,错误码"<< GetLastError() << endl;        delete [] console_title;        return 0;    }    wcout << _T("控制台标题栏") << console_title << endl;    SetConsoleTitle(_T("ShowConsoleInfo"));    wcout << endl << endl;    HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);    if (INVALID_HANDLE_VALUE =http://www.mamicode.com/= stdOutHandle)    {        wcout << "调用GetStdHandle失败,错误码" << GetLastError() << endl;        return 0;    }    // 获取屏幕缓冲信息    CONSOLE_SCREEN_BUFFER_INFO console_screen_buff_info;    memset(&console_screen_buff_info, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));    if (GetConsoleScreenBufferInfo(stdOutHandle, &console_screen_buff_info))    {        wcout << _T("屏幕缓冲大小:列数x行数") << console_screen_buff_info.dwSize.X            << _T("x") << console_screen_buff_info.dwSize.Y << endl;        wcout << _T("控制台光标位置(x,y):(") << console_screen_buff_info.dwCursorPosition.X            << _T(",") << console_screen_buff_info.dwCursorPosition.Y << _T(")") << endl;        wcout << _T("屏幕缓冲字符属性: ") << std::hex << console_screen_buff_info.wAttributes << endl;        wcout << _T("屏幕缓冲显示窗口位置left:") << console_screen_buff_info.srWindow.Left             << _T(" Right:") << console_screen_buff_info.srWindow.Right             << _T(" Top:") << console_screen_buff_info.srWindow.Top            << _T(" Bottom:") << console_screen_buff_info.srWindow.Bottom <<endl;        wcout << _T("最大显示窗口大小:") << console_screen_buff_info.dwMaximumWindowSize.X            << _T("x") << console_screen_buff_info.dwMaximumWindowSize.Y << endl;    }    // 下面设置需要将控制台屏幕缓冲窗口下移三行,用于移除关于设置控制台标题提示    SMALL_RECT sRect;    sRect.Left = 0;    sRect.Right = 0;    sRect.Top = 3;    sRect.Bottom = 3;    if (!SetConsoleWindowInfo(stdOutHandle, FALSE, &sRect))    {        wcout << "调用SetConsoleWindowInfo失败,错误码" << GetLastError() << endl;        return 0;    }    // 以上代码是控制台滚屏的一种实现方式,可考虑扩展下    // msdn上的例子    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms685118(v=vs.85).aspx    // 可使用SetConsoleScreenBufferSize来设置屏幕缓冲大小    return 0;}
View Code

实例b GUI程序创建控制台及销毁

可以使用本实例的方法,在GUI程序中使用控制台调试跟踪相关问题。

最终运行效果如下图,GUI程序界面+后台的Console界面

代码如下:

// GUI程序创建控制台示例代码,1_bGuiAllocConsole// GUI程序可以使用AttachConsole函数与某个已经存在的控制台关联,需要预先知道该进程pid// 本demo展示了如何使用Alloc创建控制台,主要代码位于WM_CREATE、WM_DESTORY消息处理中// 编译建议使用visual studio 2010 类型win32,使用unicode编码#include <iostream>// 全局变量:HINSTANCE hInst;                                // 当前实例TCHAR szTitle[] = _T("win32Test");// 标题栏文本TCHAR szWindowClass[]= _T("WIN32TEST");// 主窗口类名// 此代码模块中包含的函数的前向声明:ATOM                MyRegisterClass(HINSTANCE hInstance);BOOL                InitInstance(HINSTANCE, int);LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPTSTR    lpCmdLine,                     int       nCmdShow){    UNREFERENCED_PARAMETER(hPrevInstance);    UNREFERENCED_PARAMETER(lpCmdLine);    std::wcout.imbue(std::locale("chs"));    MyRegisterClass(hInstance);    // 执行应用程序初始化:    if (!InitInstance (hInstance, nCmdShow))    {        return FALSE;    }    MSG msg;    // 主消息循环:    while (GetMessage(&msg, NULL, 0, 0))    {        TranslateMessage(&msg);        DispatchMessage(&msg);    }    return (int) msg.wParam;}////  函数: MyRegisterClass()////  目的: 注册窗口类。////  注释:////    仅当希望//    此代码与添加到 Windows 95 中的“RegisterClassEx”//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,//    这样应用程序就可以获得关联的//    “格式正确的”小图标。//ATOM MyRegisterClass(HINSTANCE hInstance){    WNDCLASSEX wcex;    wcex.cbSize = sizeof(WNDCLASSEX);    wcex.style            = CS_HREDRAW | CS_VREDRAW;    wcex.lpfnWndProc    = WndProc;    wcex.cbClsExtra        = 0;    wcex.cbWndExtra        = 0;    wcex.hInstance        = hInstance;    wcex.hIcon            = NULL;    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);    wcex.lpszMenuName    = NULL;    wcex.lpszClassName    = szWindowClass;    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));    return RegisterClassEx(&wcex);}////   函数: InitInstance(HINSTANCE, int)////   目的: 保存实例句柄并创建主窗口////   注释:////        在此函数中,我们在全局变量中保存实例句柄并//        创建和显示主程序窗口。//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){   HWND hWnd;   hInst = hInstance; // 将实例句柄存储在全局变量中   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);   if (!hWnd)   {      return FALSE;   }   ShowWindow(hWnd, nCmdShow);   UpdateWindow(hWnd);   return TRUE;}////  函数: WndProc(HWND, UINT, WPARAM, LPARAM)////  目的: 处理主窗口的消息。////  WM_COMMAND    - 处理应用程序菜单//  WM_PAINT    - 绘制主窗口//  WM_DESTROY    - 发送退出消息并返回////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    PAINTSTRUCT ps;    HDC hdc;    static RECT rcText = {10,10,300,100};    switch (message)    {    case WM_PAINT:        hdc = BeginPaint(hWnd, &ps);        // TODO: 在此添加任意绘图代码...        DrawText(hdc, _T("这是一个Win32测试程序!"), -1, &rcText, DT_CENTER);        EndPaint(hWnd, &ps);        break;    case WM_CREATE:        if (!AllocConsole())        {            MessageBox(hWnd, _T("创建控制台失败"), _T("初始化错误"), MB_OK);        }        SetConsoleTitle(_T("win32AllocConsoleTest"));        // 这里重定向标准输出到控制台上        // 如果不做重定向就需要使用WriteConsole或者_cprintf函数        freopen( "CONOUT$", "w+t", stdout );// 申请写        //freopen( "CONIN$", "r+t", stdin ); // 申请读        std::wcout << _T("创建控制台并成功初始化") << std::endl;        break;    case WM_DESTROY:        FreeConsole();        PostQuitMessage(0);        break;    default:        return DefWindowProc(hWnd, message, wParam, lParam);    }    return 0;}
View Code

  实例c 控制台字符属性详细用法介绍

 函数SetConsoleTextAttribute可设置控制台显示的字符属性。支持一下设置:

AttributeMeaning
FOREGROUND_BLUE前景色,包含蓝色
FOREGROUND_GREEN前景色,包含绿色
FOREGROUND_RED前景色,包含红色
FOREGROUND_INTENSITY前景色,加亮
BACKGROUND_BLUE背景色,包含蓝色
BACKGROUND_GREEN背景色,包含绿色
BACKGROUND_RED背景色,包含红色
BACKGROUND_INTENSITY背景色,加亮
COMMON_LVB_LEADING_BYTE多字节码的Leading byte.
COMMON_LVB_TRAILING_BYTE多字节码的Trailing byte.
COMMON_LVB_GRID_HORIZONTAL顶部水平网格(上划线)
COMMON_LVB_GRID_LVERTICAL左竖直网格
COMMON_LVB_GRID_RVERTICAL右竖直网格
COMMON_LVB_REVERSE_VIDEO前景色背景色反转
COMMON_LVB_UNDERSCORE下划线

示例代码如下: 

// 控制台字体属性设置示例 ChangeTextAttrDemo// 设置前景色、背景色、unicode下划线、删除线等// 建议使用vs2005以上版本编译,unicode编码#include <windows.h>#include <iostream>using std::wcout;using std::endl;int _tmain(int argc, _TCHAR* argv[]){    // 输出中文    std::wcout.imbue(std::locale("chs"));    // 设置控制台标题栏    SetConsoleTitle(_T("ChangeTextAttrDemo"));    HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);    if (INVALID_HANDLE_VALUE =http://www.mamicode.com/= stdOutHandle)    {        wcout << L"调用GetStdHandle失败,错误码" << GetLastError() << endl;        return 0;    }    // 默认背景色黑色,前景色白色    wcout << _T("默认背景色,ABCabc123*&@!") << endl << endl;    // 红色前景色,绿色背景色    SetConsoleTextAttribute(stdOutHandle, FOREGROUND_RED|BACKGROUND_GREEN);    wcout << _T("设置红色前景色,绿色背景色") << endl;    wcout << _T("测试字符串,ABCabc123*&@!") << endl << endl;    // 前景色加亮对比    SetConsoleTextAttribute(stdOutHandle,         FOREGROUND_RED|BACKGROUND_GREEN|FOREGROUND_INTENSITY);    wcout << _T("设置红色前景色,绿色背景色,前景色加亮对比") << endl;    wcout << _T("测试字符串,ABCabc123*&@!") << endl << endl;    // 设置为默认字体属性+上划线    SetConsoleTextAttribute(stdOutHandle,         FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|COMMON_LVB_GRID_HORIZONTAL);    wcout << _T("设置为默认字体属性+顶部水平网格") << endl;    wcout << _T("测试字符串,ABCabc123*&@!") << endl << endl;    // 设置为蓝色前景+下划线    SetConsoleTextAttribute(stdOutHandle,         FOREGROUND_BLUE|COMMON_LVB_UNDERSCORE);    wcout << _T("设置为蓝色前景+下划线") << endl;    wcout << _T("测试字符串,ABCabc123*&@!") << endl << endl;    // 设置为绿色前景+左划线    SetConsoleTextAttribute(stdOutHandle,         FOREGROUND_GREEN|COMMON_LVB_GRID_LVERTICAL);    wcout << _T("设置为绿色前景+左竖网格") << endl;    wcout << _T("  测试字符串,ABCabc123*&@!") << endl << endl;    // 设置为绿色背景+右划线    SetConsoleTextAttribute(stdOutHandle,         BACKGROUND_GREEN|COMMON_LVB_GRID_RVERTICAL);    wcout << _T("设置为绿色背景+右竖网格") << endl;    wcout << _T("  测试字符串,ABCabc123*&@!") << endl << endl;    SetConsoleTextAttribute(stdOutHandle,         FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);    return 0;}
View Code

如果需要彩色的控制台,建议关注下代码中的各种效果。上述宏可组合使用,支持8种前景色和背景色,输出效果如下图:

 

实例d 控制台光标位置、样式及位置

本实例介绍控制台下光标的样式获取及设置,光标位置的设置等。

代码如下。(具体效果需要自己编译代码查看) 

// 控制台光标样式获取、设置,CursorAttrDemo// 1. 光标属性获取及设置// 2. 光标位置获取及设置// 建议使用vs2005以上版本编译,unicode编码#include <windows.h>#include <iostream>using std::wcout;using std::endl;int _tmain(int argc, _TCHAR* argv[]){    // 输出中文    std::wcout.imbue(std::locale("chs"));    // 设置控制台标题栏    SetConsoleTitle(_T("CursorAttrDemo"));    HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);    if (INVALID_HANDLE_VALUE =http://www.mamicode.com/= stdOutHandle)    {        wcout << L"调用GetStdHandle失败,错误码" << GetLastError() << endl;        return 0;    }    CONSOLE_CURSOR_INFO cursor_info;    memset(&cursor_info, 0, sizeof(cursor_info));    if (GetConsoleCursorInfo(stdOutHandle, &cursor_info))    {        wcout << _T("光标可见:") << (cursor_info.bVisible ? _T("") : _T("")) << endl;        wcout << _T("光标占位比例 :") << cursor_info.dwSize << _T("%") << endl;        cursor_info.bVisible = TRUE;        cursor_info.dwSize = 100;        SetConsoleCursorInfo(stdOutHandle, &cursor_info);        wcout << _T("设置100%光标占比") << endl;        int x;        std::cin >> x;        cursor_info.dwSize = 50;        SetConsoleCursorInfo(stdOutHandle, &cursor_info);        wcout << _T("设置50%光标占比") << endl;    }    // 获取光标位置使用GetConsoleScreenBufferInfo函数    // 直接输出定位到第二行    COORD cursor_pos = {0, 8};    SetConsoleCursorPosition(stdOutHandle, cursor_pos);        return 0;}
View Code

注:本文涉及所有代码可使用Git直接下载:https://git.oschina.net/Tocy/SampleCode.git。实际代码位于Console目录下,以1_开头的cpp文件。

 

本文作者:Tocy

版权所有,请勿用于商业用途,转载请注明原文地址。本人保留所有权利。

控制台基础概念实例