zoukankan      html  css  js  c++  java
  • GUI程序如何使用控制台输出调试信息[zz][MFC调用win32窗口显示调试信息,使用AllocConsole 函数 ]

    地址:http://blog.csdn.net/huiyouyongdeyu2011/article/details/6556168

    AllocConsole Function 为主调进程分配一个新的控制台。

        语法 C++ :
        BOOL WINAPI AllocConsole(void);
        参数:   无
        返回值:如果函数成功,返回值是非零值;如果函数失败,返回值是零值。
        备注:   一个进程仅能关联一个控制台,所以该函数在主调进程已经具有控制台时将会失败。
     
        一个进程可以使用 FreeConsole 函数来释放与之关联的控制台,之后它就可以调用该函数来创建一个新的控制台或使用 AttachConsole 函数来关联另一个控制台。
     
        如果主调进程创建了一个子进程,则子进程也将继承这个新创建的控制台。
        该函数为新的控制台初始化标准输入、输出、错误句柄等。
     
        标准输入句柄是一个控制台输入缓冲的句柄,标准输出和标准错误句柄则是控制台屏幕缓冲的句柄。为了获得这些句柄,可以使用 GetStdHandle 函数。 该函数主要用于GUI应用程序来创建一个控制台窗口。
     
        GUI应用程序初始化时时没有控制台的,而控制台应用程序则以控制台来初始化的。
     
        要求 : Minimum supported client Windows 2000 Professional
                Minimum supported server Windows 2000 Server
                Header:  Wincon.h (include Windows.h)
                Library: Kernel32.lib DLL Kernel32.dll

    ----------------------------------------------------------------------------------------


        虽然WIN32时代是图形界面时代,但偶尔程序中还需要用到命令行模式,比如批处理,这时再搞个图形界面出来显得似乎就不那么专业 了。但客户还需要在正常状态下(对于命令行模式,我认为用户是非正常状态,比如脑子进水。)使用图形界面,这决定我们不能开一个控制台工程,而需要使用 MFC exe程序。

       OK,理所当然的,通过条件控制,命令行下我关掉对话框界面的调用代码,再使用

    cout << "Hello world!" << endl; 来向这个友好的世界打个招呼,并坚持认为这句问候应该显示在CMD那个漆黑的窗口里。

       很沮丧地说,事实给我与痛击。cmd窗口里仍然漆黑一片,系统完全不理会我的友好。

       邓爷爷说,改革开放好!也许,我也需要个改革。

       在同事mr. zhang的指导下,我找到一组API:Console Functions!正是这组API,最终让我的友好得以正当地表达。

      一。创建一个Console,AllocConsole

      直接使用 AllocConsole(); 马上,若是进程内第一次调用这个函数,一个空的cmd窗口会蹦出来。需要注意,一个进程只能创建一个console,多次调用会返回FALSE;而且,这个窗口是个独立的控制台窗口。

      MSDN的解释:A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console.  还有段:If the calling process creates a child process, the child inherits the new console.

       二。显示Hello World,WriteConsole

       有了console,我们还需要获取它的句柄HANDLE,然后才能在上面显示。方法是 GetStdHandle,它会获取前面我们AllocConsole得到的cmd窗口的句柄;若未调用AllocConsole,将获取标准的输入输出窗口句柄。

       MSDN的解释:The GetStdHandle function returns a handle for the standard input, standard output, or standard error device.

    HANDLE hdlWrite = GetStdHandle(STD_OUTPUT_HANDLE); //这里也可以使用STD_ERROR_HANDLE
        
    TCHAR c[] = {"Hello world!"};
    WriteConsole(hdlWrite, c, sizeof(c), NULL, NULL);
       得到Console的句柄后直接使用 WriteConsole 函数即可在屏幕上显示啦。这个函数有5个参数:第一个是console的句柄,第二个是写出内容的地址,第三个参数是预计写出长度,第四个参数是实际写出 长度,可为NULL,但不建议,若使用NULL,boundchecker会在这提示错误用法,第五参数系统保留,必须使用NULL。

       MSDN里说也可以使用WriteFile来向console的handle输出。

       三。获取用户输入, ReadConsole

        光显示是不够的,用户还需要操作啊,当然,是键盘输入。

        前面我们已经创建了一个Console,输入也需要使用这个console,但若还用上面的OUTPUT句柄就不行了,我们会发现,程序在下面这句会直接跳过。

    ReadConsole(hdlWrite, c, 2, NULL, NULL);
        这里,我们还需要一个STD_INPUT_HANDLE;如下:

    TCHAR Buffer[100]; //开缓存
    memset(Buffer, 0, 100);

    DWORD dwCount = 0;//已输入数

    HANDLE hdlRead = GetStdHandle(STD_INPUT_HANDLE);
    ReadConsole(hdlRead, Buffer, 100, &dwCount, NULL);
       这个函数和WriteConsole类似,但需要注意的是,第四个参数必须指定,否则会无法读取。

       MSDN里还提到,若需要获取其它键盘外的输入信息,如鼠标信息,只能使用ReadConsoleInput函数:

    If the input buffer contains input events other than keyboard events (such as mouse events or window-resizing events), they are discarded. Those events can only be read by using the ReadConsoleInput function.

        四。关闭Console

        最后用完记得使用CloseHandle释放句柄,如:

     CloseHandle(hdlRead);
     CloseHandle(hdlWrite);

       若想关闭Console,可以使用FreeConsole();  需要注意的是,若用户直接点击cmd窗口的关闭按钮,整个程序(Application)将退出!

       五。其他函数

       这组函数还提供了其他有趣的功能,比如修改console的背景色,前景色等。更多函数请参见MSDN。

    AllocConsole();
        
    SetConsoleTitle("Lonefox love China"); //修改Console的标题
        
    HANDLE hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE, //权限
        FILE_SHARE_READ | FILE_SHARE_WRITE, //console的共享方式
        NULL,//安全性设置,NULL默认即可
        CONSOLE_TEXTMODE_BUFFER,//唯一值
        NULL//保留
        );//创建console的屏幕内容缓存,一个进程可以有多个ScreenBuffer
        
    SetConsoleActiveScreenBuffer(hConsole); //显示该buffer的内容
        
    SetConsoleTextAttribute(hConsole,
        FOREGROUND_RED | BACKGROUND_GREEN); 
        
    TCHAR c[] = {"Hello world!/n"};
    WriteConsole(hConsole, c, sizeof(c), NULL, NULL); //在屏幕显示
        
    CloseHandle(hConsole);
        
    FreeConsole();
       后记:本文仅学习笔记,非教科书。若有问题欢迎留言讨论!

    --------------------------------------------------------------------------------

    简单的方法是:

        if(AllocConsole())
        {
            freopen("CONOUT$","w",stdout);
            printf("AllocConsole [OK]\n");
        }

    即可重定向标准输出,方便gui程序调试.

    --------------------------------------------------------------------------------

    本文完.

  • 相关阅读:
    JVM 综述
    看 Netty 在 Dubbo 中如何应用
    Netty 心跳服务之 IdleStateHandler 源码分析
    Netty 高性能之道
    Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
    Netty 源码剖析之 unSafe.write 方法
    Netty 出站缓冲区 ChannelOutboundBuffer 源码解析(isWritable 属性的重要性)
    Netty 源码剖析之 unSafe.read 方法
    Netty 内存回收之 noCleaner 策略
    Netty 源码阅读的思考------耗时业务到底该如何处理
  • 原文地址:https://www.cnblogs.com/linucos/p/2678972.html
Copyright © 2011-2022 走看看