让Win32窗口程序拥有控制台窗口

让Win32窗口程序拥有控制台窗口


    首先,为什么我们有了普通窗口后还要控制台窗口呢?因为我们可以用它方便的输出调试信息,而且普通玩家看到了也会觉得很高端。如果他会输几条命令,可能他会以为自己就是黑客了。


示例效果:


    WinMain作为入口函数后,手动创建了控制台窗口,然后创建了普通窗口,输出了一些信息到控制台窗口。





具体实现:


    为什么我不用main作为入口函数,再创建普通窗口呢?因为用户不可以选择关闭控制台窗口。如果强行实现就是先找到窗口句柄然后再调用ShowWindow隐藏掉窗口。但实际还是会闪一下,其实大家可以发现有一些比较low的病毒双击后就会闪一下。

    要创建一个控制台窗口,首先调用AllocConsole创建一个。但此时调用cout或者printf都不能正常输出文字到窗口(包括输入流cin和scanf)。所以需要如下重定向输入输出流:

AllocConsole();
FILE* stream;
freopen_s(&stream, "CON", "r", stdin);//重定向输入流
freopen_s(&stream, "CON", "w", stdout);//重定向输入流

如果我们需要用到控制台窗口句柄,可以调用FindWindow取得:

HWND _consoleHwnd;
SetConsoleTitle(DEFAULT_CONSOLE_TITLE);//设置窗口名
for (int i = 0; i < 100; i++)
{
        _consoleHwnd = FindWindow(NULL, DEFAULT_CONSOLE_TITLE);
        if (_consoleHwnd)
                break;
        Sleep(100);
}

然后还需要输出流句柄:

HANDLE _handleOutput;
_handleOutput = GetStdHandle(STD_OUTPUT_HANDLE);

在不需要的时候请调用FreeConsole释放控制台窗口:

FreeConsole();

完成以上工作后,就能够创建一个控制台窗口,并能够使用cout标准输出流输出文字到其上。这里我们用wcout为例,并给文字添加上颜色:

void DebuggerConsole::Write(const String& str, int level)
{
        switch(level)
        {
        case DebugLevel::BLANK://空白
                SetConsoleTextAttribute(_handleOutput,
                                FOREGROUND_INTENSITY |
                                BACKGROUND_INTENSITY);
                break;
        case DebugLevel::TIME://时间(白色)
                SetConsoleTextAttribute(_handleOutput,
                                BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE |
                                BACKGROUND_INTENSITY);
                break;
        case DebugLevel::INFO://信息(白色蓝底)
                SetConsoleTextAttribute(_handleOutput,
                        FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE |
                        BACKGROUND_BLUE |
                        FOREGROUND_INTENSITY);
                break;
        case DebugLevel::NOTICE://提示(绿色)
                SetConsoleTextAttribute(_handleOutput,
                        FOREGROUND_GREEN |
                        BACKGROUND_GREEN |
                        FOREGROUND_INTENSITY);
                break;
        case DebugLevel::WARN://警告(黄色)
                SetConsoleTextAttribute(_handleOutput,
                        FOREGROUND_GREEN | FOREGROUND_RED |
                        BACKGROUND_GREEN | BACKGROUND_RED |
                        FOREGROUND_INTENSITY);
                break;
        case DebugLevel::ERR://错误(红色)
                SetConsoleTextAttribute(_handleOutput,
                        FOREGROUND_RED |
                        BACKGROUND_RED |
                        FOREGROUND_INTENSITY);
                break;
        }
        std::wcout << str.GetWcs();//获取字符串WCHAR数组版本
}

其中SetConsoleTextAttribute设置了输出文本的颜色,第一个参数是前面取得的输出句柄,第二个参数是宏的值组合。FOREGROUND前缀代表前景色,BACKGROUND代表背景色。RED、GREEN、BLUE是三原色分量,INTENSITY代表颜色加强(变得更亮)。
    最后再提一句,wcout不能直接输出中文,需要提前调用一句(至于为什么我也不知道^_^):

locale::global((locale("")));


作者:略游
日期:17-07-31
QQ:1339484752



  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值