Visual Studio:如何在“Win32”项目中获取输出

3
我想写一个简单的程序,以查找所有打开的窗口并显示它们的窗口名称;但是,在 Visual Studio 中使用“Win32 项目”,控制台不会输出任何内容,这时候 "cout" 函数也没法用。

但如果我尝试将代码放在“Win32 控制台”项目中,则会出现关于外部依赖项的错误(所以我认为我不能那样做?)

那么,有没有办法将控制台添加到“Win32”项目中?

相关代码(当然还没完成):

// ConsoleApplication2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>

using namespace std;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int nCmdShow){
    EnumWindows(EnumWindowsProc, NULL);
    return 0;
}

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam){
    LPTSTR title = 0;

    GetWindowText(hwnd, title, sizeof(title));
    cout << "Window Name: " << endl;

    return TRUE;
}

最后,当我尝试在“Win32控制台”项目中运行代码时遇到的错误。
Error   2   error LNK1120: 1 unresolved externals   c:\users\justin\documents\visual studio 2012\Projects\ConsoleApplication5\Debug\ConsoleApplication5.exe 1   1   ConsoleApplication5
Error   1   error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup   c:\Users\Justin\documents\visual studio 2012\Projects\ConsoleApplication5\ConsoleApplication5\MSVCRTD.lib(crtexe.obj)   ConsoleApplication5

您可以在Win32控制台项目中实现此功能。这对我来说很有效,在VS2012中,但实际上它应该适用于2010、2008等版本。 - Borgleader
3个回答

4
在您的控制台项目中,主函数必须被称为“main”,而不是“WinMain”。
#include <iostream>
#include <windows.h>

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam)
{
    LPTSTR title = 0;

        GetWindowText(hwnd, title, sizeof(title));
        std::cout << "Window Name: " << std::endl;

        return true;
}

int main(int argc, char* argv[]) // SUBSYSTEM:CONSOLE
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int nCmdShow) // SUBSYSTEM:WINDOWS
{
        EnumWindows(EnumWindowsProc, NULL);

        std::cin.get();
        return 0;
}

这将适用于Win32控制台应用程序项目。这正是您的代码,但我更改了WinMain函数的签名以成为标准的main函数。
要知道您应该使用哪个,请检查以下设置:属性 -> 链接器 -> 系统 -> 子系统,如果设置为Console (/SUBSYSTEM:CONSOLE),则它将期望标准的main函数签名;如果设置为Windows (/SUBSYSTEM:WINDOWS),则它将期望WinMain函数签名。

我在想这是否可行,因为在OpenGL中,当我使用GLUT API来显示窗口时,我使用int main(),它是一个控制台应用程序,但GLUT内部使用win32调用。现在我的程序已经可以工作了。 我的问题是>但这真的是一个好的实践吗? - 2am

2

作为Autoit用户,我真的不喜欢缺少基本功能,这使得生活变得更加困难。如果您仍然想在win32 gui Windows项目中使用标准控制台/SUBSYSTEM:CONSOLE,我建议您使用此文件:

#pragma once
#include <stdio.h>


FILE *g_ic_file_cout_stream; FILE *g_ic_file_cin_stream;

// Success: true , Failure: false
bool InitConsole() 
{
    if (!AllocConsole()) { return false; }
    if (freopen_s(&g_ic_file_cout_stream, "CONOUT$", "w", stdout) != 0) { return false; } // For std::cout 
    if (freopen_s(&g_ic_file_cin_stream, "CONIN$", "w+", stdin) != 0) { return false; } // For std::cin
    return true;
}

将其保存为InitConsole.h。

在你的代码区域中,首先包含“InitConsole.h”,然后在使用“std::cout”之前,首先调用“InitConsole()”。确保它没有返回false。如果返回false,则无法创建和初始化控制台。

此外,它不会触发VS 2015中令人讨厌的警告。

我不明白为什么没有这样一个基本功能。我建议您将此文件保留以便将来在任何win32 gui项目(用于调试目的)中重复使用。

注意:我非常新手C++,如果我的代码有问题,请多多指教。

编辑:std::cin无法使用。如果有人能改进这个代码并使它也能工作,我将非常感激。无论如何,它仍然很好。

更新:代码已更新以支持std::cin功能。


2
在非控制台应用程序中,您可以使用API调用AllocConsole(以及它的伙伴FreeConsole)来创建(和销毁)控制台窗口。通常这是为了调试目的而进行的。
此外,有许多函数允许您控制控制台窗口。有关更多信息,请参见MSDN上的控制台参考
此外,标准输出被绑定到控制台,因此如果需要,您可以使用cout将内容写入其中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接