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

时间:2014-03-08 16:27:06

标签: c++ windows console exit

除了主Win32窗口外,我还使用AllocConsole()打开了一个控制台窗口。控制台窗口在主窗口之前打开。

当我关闭主窗口并且程序从main函数返回时,控制台保持打开状态(过程也是如此)。它实际上被卡在ntdll中的某个地方,因为调试器显示暂停Visual Studio 2012中的程序。

单击X按钮关闭它会退出该过程,但是使用FreeConsole()关闭它不会,该过程仍然无窗口。 CloseWindow(GetConsoleWindow())不关闭它,它最小化它(!?!)。 PostMessage(GetConsoleWindow(),WM_QUIT,0,0)关闭窗口但该过程仍然有效(在视觉上这与FreeConsole()相同。

有时程序会以正确的方式退出,但每次都会点击X按钮。

如何点击X按钮做同样的事情?

3 个答案:

答案 0 :(得分:5)

使用PostMessage(wnd, WM_CLOSE, 0, 0)关闭控制台窗口,但问题可能是程序中的其他位置,即使这可用作修补程序。当您从main()WinMain()返回时,控制台窗口应自动关闭/消失。

答案 1 :(得分:1)

您需要使用WM_DESTROYFreeConsole消息中销毁控制台。我通常在包装我的控制台的类中执行此操作。这样它就可以在构造函数中将输入/输出重定向到控制台,并在析构函数中重置输入/输出,以及分别分配/销毁控制台。

但是,如果不使用类或任何包装器,可以按如下方式完成。

示例:

#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);
            }
        }
    }
}

答案 2 :(得分:-1)

#include <windows.h>

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

我使用的解决方案是将Linker-&gt; System-&gt; SubSystem设置为“Windows(/ SUBSYSTEM:WINDOWS)”而不是“Console(/ SUBSYSTEM:CONSOLE)”。这使得控制台甚至不出现,这避免了闪烁。第二个解决方案对我来说更好,它使第一个过时了。