我尝试将此代码输出到控制台:
#include <Windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
AllocConsole();
HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
int hCrt = _open_osfhandle((long) handle_out, _O_TEXT);
FILE* hf_out = _fdopen(hCrt, "w");
setvbuf(hf_out, NULL, _IONBF, 1);
*stdout = *hf_out;
HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
hCrt = _open_osfhandle((long) handle_in, _O_TEXT);
FILE* hf_in = _fdopen(hCrt, "r");
setvbuf(hf_in, NULL, _IONBF, 128);
*stdin = *hf_in;
printf("Hello!");
}
控制台打开但没有输出任何内容。这段代码出了什么问题?
我尝试了所有这些建议:
https://justcheckingonall.wordpress.com/2008/08/29/console-window-win32-app/
http://dslweb.nwnexus.com/~ast/dload/guicon.htm
How do I print to the debug output window in a Win32 app?
但是我无法在WinMain的Windows 10上使用AllocConsole()创建的控制台获得任何输出。 注意:我实际上没有创建任何真正的Window。 在Window 10中有什么改变阻止了上述解决方案的工作,或者有什么东西我可能会丢失(编译器标志或其他东西)?
您怎么看?
答案 0 :(得分:6)
试试这段代码。
AllocConsole();
HANDLE stdHandle;
int hConsole;
FILE* fp;
stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
hConsole = _open_osfhandle( (long)stdHandle, _O_TEXT);
fp = _fdopen(hConsole, "w");
freopen_s( &fp, "CONOUT$", "w", stdout);
printf("Hello console on\n");
std::cout << "Windows 10" << std::endl;
答案 1 :(得分:4)
根据ProXicT链接的接受答案进行一些修改。以下代码适用于std :: cout。其他方法在使用Visual Studio 2015时不会在64位上运行:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <Windows.h>
// For debugging
#include <io.h>
#include <fcntl.h>
#define UNUSED(x) (void)(x) // Unused param (C compatible - not applicable to expressions)
class outbuf : public std::streambuf {
public:
outbuf() {
setp(0, 0);
}
virtual int_type overflow(int_type c = traits_type::eof()) {
return fputc(c, stdout) == EOF ? traits_type::eof() : c;
}
};
int CALLBACK
WinMain (HINSTANCE hInstance,
HINSTANCE /*hPrevInst*/, // Unused param (C++ only)
LPSTR lpCmdLine,
int (nShowCmd))
{
UNUSED(hInstance);
// UNUSED(hPrevInst);
UNUSED(lpCmdLine);
UNUSED(nShowCmd); // This param is used
// create the console
if (AllocConsole()) {
FILE* pCout;
freopen_s(&pCout, "CONOUT$", "w", stdout);
SetConsoleTitle(L"Debug Console");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
}
// set std::cout to use my custom streambuf
outbuf ob;
std::streambuf *sb = std::cout.rdbuf(&ob);
// do some work here
printf("Hello!\n");
std::cout << "nShowCmd = " << nShowCmd << std::endl;
std::cout << "Now making my first Windows window!" << std::endl;
// make sure to restore the original so we don't get a crash on close!
std::cout.rdbuf(sb);
MessageBoxW (NULL,
L"Hello World!",
L"hello",
MB_OK | MB_ICONINFORMATION);
return 0;
}
编辑:
与上述相同的东西,但有完整性的颜色:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <Windows.h>
// For debugging
#include <io.h>
#include <fcntl.h>
#define UNUSED(x) (void)(x) // Unused param (C compatible - not applicable to expressions)
class outbuf : public std::streambuf {
public:
outbuf() {
setp(0, 0);
}
virtual int_type overflow(int_type c = traits_type::eof()) {
return fputc(c, stdout) == EOF ? traits_type::eof() : c;
}
};
int CALLBACK
WinMain (HINSTANCE hInstance,
HINSTANCE /*hPrevInst*/, // Unused param (C++ only)
LPSTR lpCmdLine,
int (nShowCmd))
{
UNUSED(hInstance);
// UNUSED(hPrevInst);
UNUSED(lpCmdLine);
UNUSED(nShowCmd); // This param is used
// create the console
if (AllocConsole()) {
FILE* pCout;
freopen_s(&pCout, "CONOUT$", "w", stdout);
SetConsoleTitle(L"Debug Console");
}
// set std::cout to use my custom streambuf
outbuf ob;
std::streambuf *sb = std::cout.rdbuf(&ob);
// do some work here
printf("Hello!\n");
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
WORD defaultConsoleTextAttributes;
GetConsoleScreenBufferInfo(stdHandle, &consoleInfo);
defaultConsoleTextAttributes = consoleInfo.wAttributes;
WORD currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "nShowCmd = " << nShowCmd << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_BLUE;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_RED;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_RED | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_BLUE;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_RED;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_BLUE | FOREGROUND_RED;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
currentConsoleTextAttributes = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
SetConsoleTextAttribute(stdHandle, currentConsoleTextAttributes);
std::cout << "Now making my first Windows window!" << std::endl;
// make sure to restore the original so we don't get a crash on close!
std::cout.rdbuf(sb);
Sleep(5000);
ShowWindow(GetConsoleWindow(), SW_HIDE);
FreeConsole();
MessageBoxW (NULL,
L"Hello World!",
L"hello",
MB_OK | MB_ICONINFORMATION);
return 0;
}
现在剩下的就是将它变成一个完整的日志记录类。
答案 2 :(得分:1)
如果您正在使用g ++,并且您希望应用程序始终同时拥有控制台和GUI,那么您可以提供-mconsole
和-mwindows
的链接器标志来实现此目的。
See this answer了解更多细节。