Отображение сообщения в диалоговом окне Windows с помощью «cout» - C ++ - PullRequest
4 голосов
/ 13 ноября 2009

Может ли окно сообщения Windows отображаться с использованием синтаксиса cout?

Мне также нужно, чтобы окно командной строки было скрыто / скрыто.

Существуют способы вызова функции messagebox и отображения текста посредством ее использования, но основное ограничение здесь заключается в том, что должен использоваться синтаксис cout.

cout <<  "message";

Я думал о вызове команды VB msgbox в выводе cout, но не смог найти ничего, что сработало.

Есть идеи?

Ответы [ 7 ]

10 голосов
/ 13 ноября 2009

C ++ потоки работают с консольными или файловыми потоками. Windows работает по более или менее совершенно другой парадигме, поэтому контекст cout не очень подходит для работы с этим. Возможно, вы могли бы полностью смешать что-то, что в конечном итоге более или менее работало бы и выглядело более или менее похоже на этот синтаксис, но это не стоит того, когда вы можете просто сделать:

MessageBox( NULL, message, "", MB_OK );

См. Полную документацию по MessageBox для получения дополнительной информации.

9 голосов
/ 14 ноября 2009

Первое, что вы должны принять во внимание, - MessageBox останавливает поток, пока вы не закроете окно. Если это поведение, которое вы хотите, продолжайте.

Вы можете создать пользовательский streambuf и установить его на std::cout:

#include <windows.h>
#include <sstream>
#include <iostream>

namespace {
    class mb_streambuf : public std::stringbuf {
        virtual ~mb_streambuf() { if (str().size() > 0) sync(); }
        virtual int sync() {
            MessageBoxA(0, str().c_str(), "", MB_OK);
            str("");
            return 0;
        }
    } mb_buf;

    struct static_initializer {
        static_initializer() { 
            std::cout.rdbuf(&mb_buf); 
        }
    } cout_buffer_switch;
}

int main()
{
    std::cout << "Hello \nworld!"; // Will show a popup
}

Всплывающее окно будет отображаться всякий раз, когда очищается поток std :: cout.

6 голосов
/ 13 ноября 2009

Когда я сталкивался с этим в прошлом, я использовал stringstream вместе с манипулятором, который отображает текущее содержимое stringstream, используя MessageBox:

#include <windows.h>
#include <sstream>
#include <ostream>

std::ostream &MessageBox(std::ostream &s) {
    std::ostringstream *st = dynamic_cast<std::ostringstream *>(&s);
    if (NULL != st)
        ::MessageBox(NULL, st->str().c_str(), "", MB_OK);
    return s;
}

Чтобы использовать это, синтаксис выглядит довольно похоже на использование cout, но с MessageBox заменой std::endl. Например:

std::ostringstream stm;
stm  << " blah blah blah. Value: " << 1213.1231 << MessageBox;

Редактировать: в основном для fnieto. В этом случае, унылый необходим . Причина довольно проста: типичный инсертор получает и возвращает ссылку на ostream:

std::ostream &operator<<(std::ostream &os, T const &t) { 
    // code here to insert t into os, then return os;
}

Это берет оригинальный объект stringstream и молча (и безопасно) приводит его к простому ostream. Это само по себе прекрасно и прекрасно работает для большинства устройств вставки и манипуляторов, потому что они взаимодействуют только с самим интерфейсом ostream.

Этот манипулятор, однако, немного отличается - он использует элемент str(), который ostream не определяет вообще. Для нашего вызова str() для разрешения и компиляции мы должны преобразовать ostream & в ostringstream &, чтобы компилятор знал, что объект, с которым мы работаем, действительно будет иметь член str().

Чтобы исключить снижение, у нас действительно был бы только один выбор: сделать его параметр ostringstream &. Это будет работать до тех пор, пока мы никогда не зацепим операторов:

my_stream << x;
my_stream << MessageBox;

но попытка связать их не удастся:

// should be equivalent:
my_stream << x << MessageBox;

Хуже того, сообщение об ошибке компилятора, вероятно, попытается сообщить пользователю что-то о std::basic_ostream<char>::str(), которое вообще не упоминается в коде пользователя. Хуже того, большинство людей достаточно привыкли к цепочкам или не дают одинаковых результатов, так что им, вероятно, понадобится некоторое время, чтобы даже понять, почему код иногда работал нормально, а в других случаях не компилировался с совершенно неразборчивым сообщением об ошибке.

6 голосов
/ 13 ноября 2009

Включив sstream, вы можете использовать std::ostringstream и создать сообщение с помощью библиотеки iostream. Затем вы можете позвонить .str().c_str() и получить char * для передачи в MessageBox.

3 голосов
/ 13 ноября 2009
3 голосов
/ 13 ноября 2009

Нет простого пути в любом случае.

C in cout означает консоль, так что вам, вероятно, не повезло.

Если вы хотите скопировать только синтаксис, вы можете написать свой собственный класс потока, который создает окно сообщения под капотом и отображает его.

1 голос
/ 13 ноября 2009

Может ли окно сообщения Windows отображаться с использованием синтаксиса cout?

Вы не можете сделать это с std::cout. std::cout даже не обещает обрабатывать Unicode / широкие символы (см. std::wcout), хотя Windows cout не имеет проблем с широкими символами.

Вы можете легко сделать это с тем же синтаксисом ; то есть вы можете легко написать библиотеку, которая перегружает operator<< для отображения диалоговых окон. Попытка передать всю информацию в диалоговое окно таким способом будет очень трудной (как бы вы сказали, какие кнопки показывать, что эти кнопки должны делать при нажатии, где эти кнопки должны быть, а также размер и положение само окно?).

Возможно, вы захотите взглянуть на что-то вроде ncurses . Синтаксис другой, но у меня есть чувство, что это то, что ищет ваш коллега.

...