Как выполнить печать в окне вывода отладки в приложении Win32?


У меня есть проект win32, который я загрузил в Visual Studio 2005. Я хотел бы иметь возможность печатать вещи в окне вывода Visual Studio, но я не могу за всю свою жизнь понять, как это сделать. Я пробовал "printf" и " cout

есть ли какой-то специальный способ печати в окне вывода Visual Studio?

9 74

9 ответов:

можно использовать OutputDebugString. OutputDebugString - это макрос, который в зависимости от варианта либо карты OutputDebugStringA(char const*) или OutputDebugStringW(wchar_t const*). В более позднем случае вам придется предоставить широкую символьную строку для функции. Для создания широкого символьного литерала можно использовать L префикс:

OutputDebugStringW(L"My output string.");

обычно вы будете использовать макрос с _T макрос вроде этого:

OutputDebugString(_T("My output string."));

если ваш проект настроен на сборку для UNICODE, он будет разверните в:

OutputDebugStringW(L"My output string.");

если вы не строите для UNICODE он будет расширяться в:

OutputDebugStringA("My output string.");

если проект является проектом GUI, консоль не появится. Чтобы изменить проект на консольный, вам нужно перейти на панель свойств проекта и установить:

  • в "компоновщик->система->подсистема" стоимостью "консоль (/SUBSYSTEM:CONSOLE)"
  • в "С/C++->Препроцессор->Определения Препроцессора" добавить " _CONSOLE" определить

Это решение работает только если у вас классический " int main ()" точки входа.

но если вы похожи на мой случай (проект openGL), вам не нужно редактировать свойства, так как это работает лучше:

AllocConsole();
freopen("CONIN$", "r",stdin);
freopen("CONOUT$", "w",stdout);
freopen("CONOUT$", "w",stderr);

printf и cout будут работать как обычно.

Если вы вызываете AllocConsole до создания окна, консоль появится за окном, если вы вызываете ее после, она появится впереди.

для печати real консоль, вы должны сделать его видимым с помощью флага компоновщика /SUBSYSTEM:CONSOLE. Дополнительное окно консоли раздражает, но для целей отладки это очень ценно.

OutputDebugString выводится на вывод отладчика при запуске внутри отладчика.

рассмотрите возможность использования макросов среды выполнения VC++ для создания отчетов _RPTN() и _RPTFN()

можно использовать макросы _RPTn и _RPTFn, определенные в CRTDBG.Ч, замените использование инструкций printf для отладки. Этот макрос автоматически исчезает в сборке выпуска, когда _DEBUG не является определено, поэтому нет необходимости заключать их в #ifdefs.

пример...

if (someVar > MAX_SOMEVAR) {
    _RPTF2(_CRT_WARN, "In NameOfThisFunc( )," 
         " someVar= %d, otherVar= %d\n", someVar, otherVar );
}

или вы можете использовать функции среды выполнения VC++_CrtDbgReport, _CrtDbgReportW напрямую.

_CrtDbgReport и _CrtDbgReportW могут отправлять отчет об отладке в три различных назначения: файл отчета об отладке, монитор отладки (the Visual Studio debugger) или окно сообщения отладки.

_CrtDbgReport и _CrtDbgReportW создают сообщение пользователя для отчета отладки, подставляя аргументы аргумента[n] в формат строку, используя те же правила, определенные функции printf и wprintf функции. Затем эти функции генерируют отладочный отчет и определите пункт назначения или пункты назначения на основе текущего отчета режимы и файл, определенные для reportType. Когда отчет отправляется окно сообщения отладки, имя файла, номер строки и имя модуля являются включены в информацию, отображаемую в окне.

ваш проект Win32, скорее всего, проект GUI, а не консольный проект. Это вызывает разницу в заголовке исполняемого файла. В результате ваш проект GUI будет отвечать за открытие своего собственного окна. Это может быть окно консоли, хотя. Звоните AllocConsole() чтобы создать его и использовать функции консоли Win32 для записи в него.

Если вы хотите напечатать десятичные переменные:

wchar_t text_buffer[20] = { 0 }; //temporary buffer
swprintf(text_buffer, _countof(text_buffer), L"%d", your.variable); // convert
OutputDebugString(text_buffer); // print

Если вам нужно увидеть вывод существующей программы, которая широко использовала printf без изменения кода (или с минимальными изменениями), вы можете переопределить printf следующим образом и добавить его в общий заголовок (stdafx.ч.)

int print_log(const char* format, ...)
{
    static char s_printf_buf[1024];
    va_list args;
    va_start(args, format);
    _vsnprintf(s_printf_buf, sizeof(s_printf_buf), format, args);
    va_end(args);
    OutputDebugStringA(s_printf_buf);
    return 0;
}

#define printf(format, ...) \
        print_log(format, __VA_ARGS__)

Я ищу способ сделать это сам и придумал простое решение.

Я предполагаю, что вы запустили проект Win32 по умолчанию (приложение Windows) в Visual Studio, который предоставляет функцию "WinMain". По умолчанию Visual Studio устанавливает точку входа в "Подсистема: WINDOWS". Вы должны сначала изменить это, перейдя к:

Проект - > Свойства - > Компоновщик - > Система - > Подсистема

и выберите "консоль (/SUBSYSTEM: CONSOLE)" из меню раскрывающийся список.

теперь программа не будет работать, так как вместо функции" WinMain "требуется функция" main".

Итак, теперь вы можете добавить функцию "main", как обычно в C++. После этого, чтобы запустить программу GUI, вы можете вызвать функцию "WinMain" изнутри функции "main".

начальная часть вашей программы теперь должна выглядеть примерно так:

#include <iostream>

using namespace std;

// Main function for the console
int main(){

    // Calling the wWinMain function to start the GUI program
    // Parameters:
    // GetModuleHandle(NULL) - To get a handle to the current instance
    // NULL - Previous instance is not needed
    // NULL - Command line parameters are not needed
    // 1 - To show the window normally
    wWinMain(GetModuleHandle(NULL), NULL,NULL, 1); 

    system("pause");
    return 0;
}

// Function for entry into GUI program
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // This will display "Hello World" in the console as soon as the GUI begins.
    cout << "Hello World" << endl;
.
.
.

результат моего реализация

теперь вы можете использовать функции для вывода на консоль в любой части вашей программы GUI для отладки или других целей.

вы также можете использовать WriteConsole метод для печати на консоли.

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);