简体   繁体   English

C ++ Windows:如何关闭控制台窗口?

[英]C++ Windows: How to close a console window?

I have a console window opened using AllocConsole(), besides the main Win32 window. 我有一个使用AllocConsole()打开的控制台窗口,除了主Win32窗口。 The console window opens before the main one. 控制台窗口在主窗口之前打开。

When I close the main window and the program returns from main function, the console remains open(and so does the process). 当我关闭主窗口并且程序从main函数返回时,控制台保持打开状态(过程也是如此)。 It actually gets stuck somewhere in ntdll, as the debugger shows on pausing the program from Visual Studio 2012. 它实际上被卡在ntdll中的某个地方,因为调试器显示暂停Visual Studio 2012中的程序。

Closing it by clicking on the X button exits the process, but closing it with FreeConsole() doesn't, the process remains working windowless. 通过单击X按钮关闭它会退出该过程,但是使用FreeConsole()关闭它不会,该过程仍然无窗口。 CloseWindow(GetConsoleWindow()) doesn't close it, it minimizes it (!?!). CloseWindow(GetConsoleWindow())不关闭它,它最小化它(!?!)。 PostMessage(GetConsoleWindow(),WM_QUIT,0,0) closes the window but the process still remains working(visually this is the same as FreeConsole(). PostMessage(GetConsoleWindow(),WM_QUIT,0,0)关闭窗口但该过程仍然有效(在视觉上这与FreeConsole()相同。

Occasionally the program exits in the right way, but clicking on the X button works every time. 有时程序会以正确的方式退出,但每次点击X按钮都会有效。

How do I do the same thing that clicking on the X button does? 如何点击X按钮做同样的事情?

Use PostMessage(wnd, WM_CLOSE, 0, 0) to close the console window, but the problem is probably somewhere else in your program even if this works as a hotfix. 使用PostMessage(wnd, WM_CLOSE, 0, 0)关闭控制台窗口,但问题可能是程序中的其他位置,即使这可用作修补程序。 The console window should close/disappear automatically when you return from your main() or WinMain() . main()WinMain()返回时,控制台窗口应自动关闭/消失。

You need to destroy the console within the WM_DESTROY message using FreeConsole . 您需要使用FreeConsoleWM_DESTROY消息中销毁控制台。 I usually do this all in a class that wraps my console. 我通常在包装我的控制台的类中执行此操作。 This way it can redirect input/output to the console in the constructor and reset input/output in the destructor as well as alloc/destroy the console respectively. 这样它就可以在构造函数中将输入/输出重定向到控制台,并在析构函数中重置输入/输出以及分别分配/销毁控制台。

However, without using a class or any wrappers, it can be done as follows.. 但是,如果不使用类或任何包装器,可以按如下方式完成。

Example: 例:

#include <windows.h>
#include <streambuf>
#include <fstream>
#include <iostream>

std::streambuf *CinBuffer, *CoutBuffer, *CerrBuffer;
std::fstream ConsoleInput, ConsoleOutput, ConsoleError;

void RedirectIO()
{
    CinBuffer = std::cin.rdbuf();
    CoutBuffer = std::cout.rdbuf();
    CerrBuffer = std::cerr.rdbuf();
    ConsoleInput.open("CONIN$", std::ios::in);
    ConsoleOutput.open("CONOUT$", std::ios::out);
    ConsoleError.open("CONOUT$", std::ios::out);
    std::cin.rdbuf(ConsoleInput.rdbuf());
    std::cout.rdbuf(ConsoleOutput.rdbuf());
    std::cerr.rdbuf(ConsoleError.rdbuf());
}

void ResetIO()
{
    ConsoleInput.close();
    ConsoleOutput.close();
    ConsoleError.close();
    std::cin.rdbuf(CinBuffer);
    std::cout.rdbuf(CoutBuffer);
    std::cerr.rdbuf(CerrBuffer);
    CinBuffer = NULL;
    CoutBuffer = NULL;
    CerrBuffer = NULL;
}

LRESULT __stdcall WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
        case WM_CREATE:
            AllocConsole();
            RedirectIO();
            std::cout<<"HELLO CONSOLE!"<<std::endl;
            break;

        case WM_DESTROY:
            std::cout<<"BYE-BYE CONSOLE!"<<std::endl;
            ResetIO();
            FreeConsole();
            PostQuitMessage(0);
            return 0;

        default:
            return DefWindowProc(Hwnd, Msg, wParam, lParam);
    }
    return 0;
};

int main()
{
    WNDCLASSEX WndClass =
    {
        sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
        0, 0, GetModuleHandle(NULL), LoadIcon(NULL, IDI_APPLICATION),
        LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
        NULL, "WindowClass", LoadIcon (NULL, IDI_APPLICATION)
    };

    if(RegisterClassEx(&WndClass))
    {
        HWND WindowHandle = CreateWindowEx(0, "WindowClass", "Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
        if(WindowHandle)
        {
            MSG msg = {NULL};
            ShowWindow(WindowHandle, SW_SHOWDEFAULT);
            while(GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
}
#include <windows.h>

HWND myConsole = GetConsoleWindow(); //window handle
ShowWindow(myConsole, 0); //handle window

The solution I wound up using was to set Linker->System->SubSystem to "Windows (/SUBSYSTEM:WINDOWS)" instead of "Console (/SUBSYSTEM:CONSOLE)". 我使用的解决方案是将Linker-> System-> SubSystem设置为“Windows(/ SUBSYSTEM:WINDOWS)”而不是“Console(/ SUBSYSTEM:CONSOLE)”。 This makes the console not even appear, which avoids flickering. 这使得控制台甚至不出现,这避免了闪烁。 The second solution was better for me, and it rendered the first obsolete. 第二个解决方案对我来说更好,它使第一个过时了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM