Visual C++2013从入门到精通(视频教学版)
上QQ阅读APP看书,第一时间看更新

2.11 控制台编程

DOS的时代已经离我们远去,现在只能去控制台程序中寻找以往的情怀。但,图形界面大行其道的今天,为何还要了解控制台编程?为了在控制台下进行多线程编程,以及在图形界面程序中调用控制台,这样我们可以把调试语句写在控制台窗口中!当然,多线程编程是后面章节的事情了。这里只谈控制台!

以前学C语言的时候,要在控制台窗口中输出信息,最常用的就是使用CRT库函数printf了,现在Visual C++提供了很多控制台函数,也可以用于在控制台窗口中输出信息,这样就不必使用CRT库函数printf了,有人说了,这样代替有什么意义呢?意义很大,这是因为创建线程的函数CreateThread所创建的线程函数中是不能使用CRT库函数的(会造成内存泄漏),所以如果要在CreateThread所创建的线程函数中输出信息到控制台,我们就可以使用控制台函数来替换printf了。

Visual C++提供了很多控制台API函数,如果在控制台程序中使用这些函数,需要包含windows.h。常用的控制台函数有:

(1)GetStdHandle函数

该函数从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄,也就是获取这些标准设备的缓冲区句柄,以便用户可以进行输入输出。函数声明如下:

        HANDLE GetStdHandle( DWORD  nStdHandle );

其中参数nStdHandle用来标识标准输入、标准输出或标准错误,取值分别为STD_INPUT_HANDLE(标准输入)、STD_OUTPUT_HANDLE(标准输出)、STD_ERROR_HANDLE(标准错误)。如果函数成功,返回特定设备的句柄;如果函数失败,返回INVALID_HANDLE_VALUE。

比如我们获得当前标准输出设备的句柄:

        HANDLE  hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

(2)SetConsoleTextAttribute函数

该函数用来设置输出到控制台屏幕(或窗口)的字符属性,比如前景色和背景色。函数声明如下:

        BOOL  SetConsoleTextAttribute( HANDLE hConsoleOutput, WORD    wAttributes);

其中参数hConsoleOutput是控制台屏幕缓冲区的句柄;wAttributes为要设置给字符的属性,比如取值FOREGROUND_BLUE表示字体颜色为蓝色,取值为BACKGROUND_GREEN表示背景颜色为绿色。如果函数成功返回非零,否则返回零。

(3)WriteConsole函数

该函数向控制台屏幕或窗口的缓冲区写入一段字符串,输出位置始于当前光标处。函数声明如下:

        BOOL    WriteConsole(  HANDLE hConsoleOutput,  const VOID* lpBuffer,
        DWORD    nNumberOfCharsToWrite,    LPDWORD    lpNumberOfCharsWritten,    LPVOID
    lpReserved);

其中参数hConsoleOutput是控制台屏幕缓冲区的句柄;lpBuffer指向字符缓冲区;


【例2.48】 向控制台窗口输出有颜色的字符串

(1)新建一个控制台工程。

(2)在Test.cpp中输入代码如下:

        #include "stdafx.h"
        #include <windows.h>
        void  SetConsoleColor(unsigned  short  ForeColor  =  FOREGROUND_RED,  unsigned short BackGroundColor = 0)
        {
            HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台输出缓冲区的句柄
            SetConsoleTextAttribute(hCon, ForeColor | BackGroundColor); //设置前景色和背景色
        }
        int main()
        {
            SetConsoleColor();
            printf("你好世界\n");
            SetConsoleColor(FOREGROUND_BLUE, BACKGROUND_GREEN);
            printf("同志们好!\n");
            return 0;
        }

(3)保存工程并运行,运行结果如图2-102所示。

图2-102

【例2.49】 使用WriteConsole函数输出字符串

(1)新建一个控制台工程。

(2)在Test.cpp中输入代码如下:

        #include "stdafx.h"
        #include "windows.h"
        int _tmain(int argc, _TCHAR* argv[])
        {
            HANDLE hStdout;
            DWORD dwChars;
            TCHAR msgBuf[] = _T("你好,世界,Hello world! \n");
            int len = lstrlen(msgBuf);
            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); //得到标准输出设备的句柄,为了打印
            if (hStdout == INVALID_HANDLE_VALUE)
                return -1;
            WriteConsole(hStdout, msgBuf, len, &dwChars, NULL); //在终端窗口输出字符串
        }

(3)保存工程并运行,运行结果如图2-103所示。

图2-103

【例2.50】 在对话框程序中显示控制台窗口

(1)新建一个MFC对话框工程。

(2)切换资源视图,打开对话框编辑器,删除上面所有控件,并放一个按钮,为其添加事件处理函数,代码如下:

        void CTestDlg::OnBnClickedButton1()
        {
            // TODO:  在此添加控件通知处理程序代码
            InitConsoleWindow();
            printf("你好,世界!\n ");
        }

其中,InitConsoleWindow是一个自定义的全局函数,代码如下:

        void InitConsoleWindow()
        {
            int nCrt = 0;
            FILE* fp;
            AllocConsole();
            nCrt  =  _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),  _O_TEXT);
            fp = _fdopen(nCrt, "w");
            *stdout = *fp;
            setvbuf(stdout, NULL, _IONBF, 0);
        }

在TestDlg.cpp的文件开头添加头文件包含:

        #include <io.h>
        #include <fcntl.h> //for _O_TEXT

(3)保存工程并运行,运行结果如图2-104所示。

图2-104