在使用c/c++学习Win32编程的过程中,有时候需要对程序运行情况进行观察与调试。使用传统的控制台进行输出日志就是很方便的一种方法。下面给出添加日志控制台的一个函数。
输入参数hWnd为窗口句柄,用来生成消息框,作为消息框的所有者窗口的句柄。
BOOL addConsole(HWND hWnd) {
HANDLE hStdin;
DWORD mode;
if (AllocConsole() == 0) {
MessageBox(hWnd, _T("AllocConsole failed!"), NULL, MB_OK);
return false;
}
hStdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
mode &= ~ENABLE_INSERT_MODE;
mode &= ~ENABLE_MOUSE_INPUT;
SetConsoleMode(hStdin, mode);
if (freopen("conout$", "w", stdout) == NULL) {
MessageBox(hWnd, _T("freopen stdout failed!"), NULL, MB_OK);
return false;
}
if (freopen("conin$", "r", stdin) == NULL) {
MessageBox(hWnd, _T("freopen stdin failed!"), NULL, MB_OK);
return false;
}
if (freopen("conerr$", "w", stderr) == NULL) {
MessageBox(hWnd, _T("freopen stderr failed!"), NULL, MB_OK);
return false;
}
printf("添加控制台成功!\n");
return true;
}
- AllocConsole()函数
为当前线程分配一个控制台窗口,一般来说一个线程只能分配一个控制台窗口,多次分配会失败并返回0。windows系统用特殊的文件名:conout$,conin$ 以及conerr$ 来标识控制台输入、输出以及错误输出缓冲区。当使用AllocConsole()分配成功(或线程成功挂载到一个控制台)时,上述三个描述符变得有效,否则使用这些描述符会使程序报错。 - freopen()函数
c语言标准库函数,用来重定向输入输出流,包含于stdio.h头文件之中。当我们使用printf()与scanf()函数的时候,会默认调用stdout与stdin的输入输出流。如果我们创建的是控制台项目,那么stdout与stdin会默认使用控制台作为输入输出文件。但是Win32 GUI程序初始不带有控制台窗口,因此在分配了控制台后如果要使用它,还需要将stdin与stdout重定向到指定的控制台窗口。
第一个参数是重定向到的文件。如果重定向到硬盘内的路径,则会打开(或创建)这个文件,用以输出或输入数据。特殊地,conout$,conin$ 以及conerr$ 文件名指示输出输入到控制台中。 - 控制台卡死
在使用控制台的时候,如果鼠标选中或尝试输入内容,线程会被堵塞导致程序卡死,只有输入回车将控制台缓冲清空时程序才会恢复正常。这个时候可以右键控制台窗口的标题栏,设置属性,将快速编辑模式和插入模式移除。更方便地,可以使用SetConsoleMode()函数移除这些模式。这个时候,控制台充当了仅可读临时日志的功能,而且不能选中文字内容。
本文参考了@小七爱淘气的文章。