C++ and DirectShow - c++

I'm just getting started with DirectShow programming, and the 'C' nature of the DirectShow API is making my skin crawl. Endless return codes instead of exceptions, addref/release all over the place, functions taking pointer to pointers...
Are there any 'C++ friendly' wrappers for DirectShow programming that hide all the COM ugliness underneath.?

For 98% of DirectShow code, you should never see a call to AddRef or Release. Always use CComPtr<>. There are a few minor exceptions to this rule.
Also, understanding locking is important, as is CCritSec and CAutoLock; once again, I'd avoid manually locking CCritSec instances because it's a good way to deadlock an application.
Also, this code can be pretty handy:
#include <dxerr9.h>
...
HRESULT hr = S_OK;
... something goes wrong ...
CString err(::DXGetErrorString9(hr));
err += ::DXGetErrorDescription9(hr);
Lastly, make sure you're using the DShow eventing. All sorts of useful info comes in over events from a DShow graph, and it's surprising how many applications don't have this implemented (or have it implemented incorrectly).
A while ago, I wrote this, which I've sort of tossed together a few of the pitfalls of working with DShow. Sadly, I know these pitfalls because I've screwed up in almost all these ways.

CComPtr is a pretty handy one,
Beyond that you just have to live with things like the HRESULTS. I rather prefer them to exceptions ... find them much easier to work with ... each to their own.

It's worth knowing that DirectShow is implemented in quartz.dll, and DirectShow Editing Services in qedit.dll.
You can use those two with the Compiler COM Support from Visual C++ to write DirectShow client applications.
Here is a small play media_file example (compile with cl /D_UNICODE playfile.cpp):
#include <iostream>
#import <quartz.dll> rename_namespace("dshow")
#import <qedit.dll> rename_namespace("dshow")
// Required for CLSID_FilterGraph
#include <uuids.h>
#pragma comment(lib, "strmiids.lib")
int wmain(int argc, wchar_t* argv[])
{
using namespace dshow;
using namespace std;
if (argc != 2)
{
wcout << "Usage: play media_file" << endl;
return 1;
}
struct ComInitializer
{
ComInitializer()
{
::CoInitialize(0);
}
~ComInitializer()
{
::CoUninitialize();
}
} comInit;
try
{
IGraphBuilderPtr graphBuilder;
graphBuilder.CreateInstance(CLSID_FilterGraph);
graphBuilder->RenderFile(argv[1], 0);
IMediaControlPtr mediaControl = graphBuilder;
mediaControl->Run();
wcout << "Press Return to stop playback." << endl;
wcin.get();
mediaControl->Stop();
}
catch (const _com_error& err)
{
wcout << L"Error code: 0x" << hex << err.Error() << endl;
}
}
I've used this method in building a console DirectShow oggenc application.

If you don't find a wrapper then you can possibly benefit from the coding pattern discussed in my blog entry "B true, or B thrown! (Using the >> throwing pattern)".
Example from that blog entry (this can easily be adapted for COM, and in fact I first "invented" it for COM usage):
std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
Size const nBytes = wcstombs( 0, s, 0 );
(nBytes >= 0)
|| throwX( "wcstombs failed to deduce buffer size" );
Size const bufSize = nBytes + 1;
std::vector< char > buf( bufSize );
// The count of bytes written does not include terminating nullbyte.
wcstombs( &buf[0], s, bufSize )
>> Accept< IsNonNegative >()
|| throwX( "wcstombs failed to convert string" );
return (stream << &buf[0]);
}
There is some discussion at the blog, evidently everybody has his or her own preference for suitable operators etc., so I'm just throwing in the general principle here.
Oh, should add, instead of AddRef and Release calls, just use some COM smart pointer. There are so many of them around (e.g. in ATL/MFC, and the "intrinsic" one for Visual C++) that it's just pick and choose the one you like. Or create your own e.g. based on boost::intrusive_ptr.
Cheers & hth.,

Related

In C++ std:: streams, after a failure, how to get a failure reason? Required: threadsafe and common to Windows and Linux (or at least Msvc/Gcc)

Sorry for weird title. Limited to 150 chars so couldn't use proper sentences.
So let's say I've done the following to find out that something went wrong with my file stream:
std::ofstream ofs;
do_stuff_with(ofs);
// streams don't throw on error because C++ [edit: we can make them do so, but the .what()s aren't very user-friendly]
// so we have to check for failure manually
if(!ofs){
auto fail_code = errno; // threadsafe on Win/Linux
// but what goes here?
}
1) strerror:
Not threadsafe
2) strerror_s: Not in GCC? Or is it?
3) strerror_r: Not in Msvc? Or is it?
4) #ifdef/#define/etc: yuck, but may be the only choice
I did do some searching but I didn't find a "this will definitely work in a sensible yet slightly platform-dependent way" answer... That said, I feel like this is "obviously a duplicate question", but I can't find the original...
You can always throw your own exceptions using std::system_error:
#include <cerrno>
#include <fstream>
#include <iostream>
#include <system_error>
int main()
{
try
{
std::ofstream foo{"/root/bar.baz"};
foo << "bla" << std::endl;
foo.close();
if(!foo)
throw std::system_error{errno, std::generic_category()};
}
catch(const std::system_error& err)
{
std::cout << "Error: " << err.code() << " - " << err.what() << std::endl;
}
return 0;
}
This returns Error: generic:13 - Permission denied.
Since C++11, you can use the class std::error_code for that:
std::cout << std::error_code{errno, std::generic_category()}.message();
In fact you can even do it a little shorter than that:
std::cout << std::generic_category().message(errno);
Though I must say I find the first one a little more idiomatic.
As a sidenote, there is also std::system_category(), which seems to be largely equivalent to generic_category() on Unix but on Windows, it can be used to translate Windows API error codes such as returned by GetLastError() etc.
This is the same class that's also used within the std::system_error exception, but you don't need to create an instance of the exception if all you want to do is to get the error message.
This is the best I could come up with. It's the "yuck" answer, but at least you can put the "yuck" in a single function and hide it away in some cpp file somewhere. std::ios covers boost streams as well, of course.
Requires #ifdefs so it's a cheat. I believe Visual Studio #defines _WIN32 by default, so at least you don't have to set up that infrastructure per se.
void check_stream(std::ios & stream)
{
if (!stream){
char err[1024] = { 0 };
#ifdef _WIN32
strerror_s(err, errno);
#else
strerror_r(errno, err, 1024);
#endif
throw MyException(err);
}
}
My own solution makes me sad so hopefully a better one will come along. But time is finite, so just submit to the Dark Side, use something like this, and get on with your life. :P
try{
boost::filesystem::ifstream ifs("testfile");
check_stream(ifs);
}
catch (std::exception & e){
std::cout << e.what(); // "No such file or directory"
}

how to create my own 'cout' and 'cerr' class

How do I create my own class that behaves exactly like: std::cout & std::cerr.
I am writing a mini operating system and this is a requirement, having these as modules there.
The code will look like:
myNewCoutClass myCout; // create cout behavioral class
myNewCerrClass myCerr; // create cerr behavioral class
myCout << someString << endl; // prints the string
myCerr << someString << endl; // prints the string as error
First things first, don't do this unless you know very well what you're doing, and are willing to take all of the risks involved. It's just an example of how one could bind another stream to stdout, in effect creating a second cout, as a thought experiment. That said, here we go.
If you want to create another stream for stdout, you have to take a good look at your compiler's deep, dark innards, and find out how it defines cout, cerr, and/or clog. This will be in a compiler-dependent location, and most likely not where you expect; for example, on older versions of Visual Studio, you would have to look at a few of the files in the crt\src folder:
// Visual Studio 2010 implementation of std::cout.
// Irrelevant parts omitted.
// cout.cpp
__PURE_APPDOMAIN_GLOBAL static filebuf fout(_cpp_stdout);
#if defined(_M_CEE_PURE)
__PURE_APPDOMAIN_GLOBAL extern ostream cout(&fout);
#else
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream cout(&fout);
#endif
struct _Init_cout
{
__CLR_OR_THIS_CALL _Init_cout()
{
_Ptr_cout = &cout;
if (_Ptr_cin != 0)
_Ptr_cin->tie(_Ptr_cout);
if (_Ptr_cerr != 0)
_Ptr_cerr->tie(_Ptr_cout);
if (_Ptr_clog != 0)
_Ptr_clog->tie(_Ptr_cout);
}
};
__PURE_APPDOMAIN_GLOBAL static _Init_cout init_cout;
// stdio.h
#define _INTERNAL_BUFSIZ 4096
// ...
#define _IOB_ENTRIES 20
// ...
#ifndef _STDSTREAM_DEFINED
#define stdin (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])
#define _STDSTREAM_DEFINED
#endif /* _STDSTREAM_DEFINED */
// _file.c
char _bufin[_INTERNAL_BUFSIZ];
FILE _iob[_IOB_ENTRIES] = {
/* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
/* stdin (_iob[0]) */
{ _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
/* stdout (_iob[1]) */
{ NULL, 0, NULL, _IOWRT, 1, 0, 0 },
/* stderr (_iob[3]) */
{ NULL, 0, NULL, _IOWRT, 2, 0, 0 },
};
_CRTIMP FILE * __cdecl __iob_func(void)
{
return _iob;
}
// `__PURE_APPDOMAIN_GLOBAL` is an internal macro that can generally be ignored.
// `_CRTIMP` is an internal macro that can generally be ignored.
// `_CRTDATA2` is an internal macro that can generally be ignored.
// `__CLR_OR_THIS_CALL` is a calling convention macro that expands to either
// `__clrcall` or `__thiscall`.
From this, we can derive our own stream for stdout, although it'll be compiler-dependent.
// Visual Studio 2010 user-created char16_t cout.
// Note that in VStudio 2010, char16_t is actually a typedef for unsigned short.
#include <iostream>
#include <fstream>
#include <string>
#include <codecvt>
#define _cpp_stdout (&(__iob_func())[1])
typedef std::basic_filebuf<char16_t, std::char_traits<char16_t>> filebuf_c16;
typedef std::basic_ostream<char16_t, std::char_traits<char16_t>> ostream_c16;
int main() {
filebuf_c16 f16out(_cpp_stdout);
ostream_c16 c16out(&f16out);
// It really should be tied to the other stdin/stdout/stderr streams,
// but this is a simple program where it won't be a problem.
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
std::string u8tmp = "Hello from char16_t!";
std::u16string u16str = converter.from_bytes(u8tmp);
c16out << u16str << std::endl;
}
And the results...
Hello from char16_t!
If you wanted to tie a second standard ostream (a.k.a. a basic_ostream<char, char_traits<char>>) to stdout, you could use something similar. Note that as fout is static, you would need to make your own filebuf. Also note that this is just asking for trouble, but that's beside the point; just be careful of data races, or anything of the sort.
Note that while you can do this, unless you know very well what you're doing, are willing to take responsibility for anything that goes wrong, and are willing to spend enough time delving into your compiler's library and/or code to find out how exactly it implements stdout and the default strings, you very well shouldn't do it.
Also note that your code will be tightly coupled to the compiler, and there's a very high probability that future versions of the same compiler may break it. For example, to my knowledge, this code won't compile with Visual Studio 2015 because of changes to the CRT (specifically, I believe it's because of changes to FILE, but I didn't look into it).
These objects are std::ostreams. You can create your own std::ostream. Precisely how that'll work depends entirely on the data sink, which you haven't specified, but an std::ostringstream will be enough to get you started on testing the code that uses it.
However, if you literally wish to reinvent std::cout, don't. Its data sink is the magic file handle stdout, which you can't recreate as it's provided by the OS. You could create a std::ostream that steals that buffer from std::cout but what's the point?

Winforms RichTextBox as istream

I'm adapting a console based program to GUI.
The console program reads a text file and "compiles" it.
My GUI application reads the text file and displays in a RichTextBox.
I'm looking for a method to treat the RichTextBox as a C++ std::istream. This would allow me to use code from the console program without modifying it.
I searched the web and StackOverflow and didn't find any solutions for treating a RichTextBox as an std::istream.
Does anybody know of any Winforms library functions that would allow treating of RichTextBox as an std::istream?
My ideas:
Create an adapter to treat RichTextBox as a stream.
Change the console program to pass a "getline" function to the
compiler portion, and have two getline functions (one as the
std::getline, another to get a line from the RichTextBox).
Write the RichTextBox contents to a file and feed the file to the
compiler.
I'm using Visual Studio 2010 on Win 7 using ".NET" 4.0, using C++ (don't suggest any C# techniques as I'm not fluent in translating).
In real C++, you can create a stream buffer from an RTF control like this:
class RTF_buf : public std::streambuf {
std::vector<char> buffer;
public:
RTF_buf(HWND ctrl) {
DWORD len = SendMessage(ctrl, WM_GETTEXTLENGTH, 0, 0);
buffer.resize(len+1);
SendMessageA(ctrl, WM_GETTEXT, len+1, (LPARAM)&buffer[0]);
setg(&buffer[0], &buffer[0], &buffer[len]);
}
};
Note that this isn't actually restricted to an RTF control. Just for one other example, it'll also work fine with a normal EDIT control.
C++/CLI adds a few wrinkles to this. First of all, you're dealing with "wide" characters in the RichTextBox. Second, you won't (normally) start with an HWND -- you have to retrieve that from the System.Windows.Forms.RichTextBox via its Handle property. This, unfortunately, returns the HWND as an IntPtr instead of an HWND, so you have to add a cast to get it to the right type. That makes the code a little uglier, but nothing too terrible:
#include <windows.h>
#include <streambuf>
#include <iostream>
#include <vector>
#include <algorithm>
#pragma comment(lib, "user32.lib")
using namespace System;
using namespace System::Windows::Forms;
class RTF_buf : public std::wstreambuf {
std::vector<wchar_t> buffer;
public:
RTF_buf(RichTextBox^ control) {
HWND ctrl = *reinterpret_cast<HWND *>(&control->Handle);
int len = SendMessage(ctrl, WM_GETTEXTLENGTH, 0, 0);
buffer.resize(len+1);
SendMessage(ctrl, WM_GETTEXT, len+1, (LPARAM)&buffer[0]);
setg(&buffer[0], &buffer[0], &buffer[len]);
}
};
We can create a buffer and istream something like this:
RTF_buf b(this->richTextBox1);
std::wistream in(&b);
Finally, we can read data from our stream and process them like we would essentially any other (wide) stream. For example:
wchar_t ch;
while (in >> ch)
// do something with ch
So C++/CLI does add a little complexity to the task, but ultimately only a little--mostly the one line to obtain the handle of the control, and cast it to the correct type. Other than that the code for the buffer class barely needs to change at all, and instantiating and using it changes only to the extent that we're working with wide characters instead of narrow.
The proper way to create a stream plugging into the IOStreams library is to implement a stream buffer, i.e., to derive from std::streambuf or std::wstreambuf (I'm not a Windows programmer but my understanding is that most code travels in terms of wchar_t rather than char) and override the suitable virtual member functions. Assuming you can get characters in bunches (possible all in a bukl) all you'd really overload is underflow() which is called if the input buffer was exhausted. If you can get all the characters during construction you can also set up a buffer.
Once you have a stream buffer you can use a pointer to the stream buffer to initialize an std::istream. Here is a simple example which uses a memory arean passed in the constructor as its input:
#include <iostream>
#include <streambuf>
class membuf
: std::streambuf {
public:
membuf(char* buffer, std::size_t size) {
this->setg(buffer, buffer, buffer + size);
}
};
int main() {
char input[] = "hello, world!\n";
membuf sbuf(input, sizeof(input - 1));
std::istream in(&sbuf);
char buffer[100];
if (in.getline(buffer, sizeof(buffer)) {
std::cout << "read '" << buffer << "'\n";
}
else {
std::cout << "ERROR: failed to read a line but Dietmar said...!?!\n";
}
}

How to serialize an object to send over network

I'm trying to serialize objects to send over network through a socket using only STL. I'm not finding a way to keep objects' structure to be deserialized in the other host. I tried converting to string, to char* and I've spent a long time searching for tutorials on the internet and until now I have found nothing.
Is there a way to do it only with STL?
Are there any good tutorials?
I am almost trying boost, but if there is how to do it with STL I'd like to learn.
You can serialize with anything. All serialization means is that you are converting the object to bytes so that you can send it over a stream (like an std::ostream) and read it with another (like an std::istream). Just override operator <<(std::ostream&, const T&) and operator >>(std::istream&, T&) where T is each of your types. And all the types contained in your types.
However, you should probably just use an already-existing library (Boost is pretty nice). There are tons of things that a library like Boost does for you, like byte-ordering, taking care of common objects (like arrays and all the stuff from the standard library), providing a consistent means of performing serialization and tons of other stuff.
My first question will be: do you want serialization or messaging ?
It might seem stupid at first, since you asked for serialization, but then I have always distinguished the two terms.
Serialization is about taking a snapshot of your memory and restoring it later on. Each object is represented as a separate entity (though they might be composed)
Messaging is about sending information from one point to another. The message usually has its own grammar and may not reflect the organization of your Business Model.
Too often I've seen people using Serialization where Messaging should have been used. It does not mean that Serialization is useless, but it does mean that you should think ahead of times. It's quite difficult to alter the BOM once you have decided to serialize it, especially if you decide to relocate some part of information (move it from one object to another)... because how then are you going to decode the "old" serialized version ?
Now that that's been cleared up...
... I will recommend Google's Protocol Buffer.
You could perfectly rewrite your own using the STL, but you would end up doing work that has already been done, and unless you wish to learn from it, it's quite pointless.
One great thing about protobuf is that it's language agnostic in a way: ie you can generate the encoder/decoder of a given message for C++, Java or Python. The use of Python is nice for message injection (testing) or message decoding (to check the output of a logged message). It's not something that would come easy were you to use the STL.
Serializing C++ Objects over a Network Socket
This is 6 years late but I just recently had this problem and this was one of the threads that I came across in my search on how to serialize object through a network socket in C++. This solution uses just 2 or 3 lines of code. There are a lot of answers that I found work but the easiest that I found was to use reinterpret_cast<obj*>(target) to convert the class or structure into an array of characters and feed it through the socket. Here's an example.
Class to be serialized:
/* myclass.h */
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
public:
int A;
int B;
MyClass(){A=1;B=2;}
~MyClass(){}
};
#endif
Server Program:
/* server.cpp */
#include "myclass.h"
int main (int argc, char** argv)
{
// Open socket connection.
// ...
// Loop continuously until terminated.
while(1)
{
// Read serialized data from socket.
char buf[sizeof(MyClass)];
read(newsockfd,buf, sizeof(MyClass));
MyClass *msg = reinterpret_cast<MyClass*>(buf);
std::cout << "A = " << std::to_string(msg->A) << std::endl;
std::cout << "B = " << std::to_string(msg->B) << std::endl;
}
// Close socket connection.
// ...
return 0;
}
Client Program:
/* client.cpp */
#include "myClass.h"
int main(int argc, char *argv[])
{
// Open socket connection.
// ...
while(1)
{
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
MyClass msg;
msg.A = 1;
msg.B = 2;
// Write serialized data to socket.
char* tmp = reinterpret_cast<char*>(&msg);
write(sockfd,tmp, sizeof(MyClass));
}
// Close socket connection.
// ...
return 0;
}
Compile both server.cpp and client.cpp using g++ with -std=c++11 as an option. You can then open two terminals and run both programs, however, start the server program before the client so that it has something to connect to.
Hope this helps.
I got it!
I used strinstream to serialize objects and I sent it as a message using the stringstream's method str() and so string's c_str().
Look.
class Object {
public:
int a;
string b;
void methodSample1 ();
void methosSample2 ();
friend ostream& operator<< (ostream& out, Object& object) {
out << object.a << " " << object.b; //The space (" ") is necessari for separete elements
return out;
}
friend istream& operator>> (istream& in, Object& object) {
in >> object.a;
in >> object.b;
return in;
}
};
/* Server side */
int main () {
Object o;
stringstream ss;
o.a = 1;
o.b = 2;
ss << o; //serialize
write (socket, ss.str().c_str(), 20); //send - the buffer size must be adjusted, it's a sample
}
/* Client side */
int main () {
Object o2;
stringstream ss2;
char buffer[20];
string temp;
read (socket, buffer, 20); //receive
temp.assign(buffer);
ss << temp;
ss >> o2; //unserialize
}
I'm not sure if is necessary convert to string before to serialize (ss << o), maybe is possible directly from char.
I think you should use google Protocol Buffers in your project.In network transport Protocol buffers have many advantages over XML for serializing structured data. Protocol buffers:
are simpler
are 3 to 10 times smaller
are 20 to 100 times faster
are less ambiguous
generate data access classes that are easier to use programmaticall
and so on. I think you need read https://developers.google.com/protocol-buffers/docs/overview about protobuf

Display message in windows dialogue box using "cout" - C++

Can a windows message box be display using the cout syntax?
I also need the command prompt window to be suppressed / hidden.
There are ways to call the messagebox function and display text through its usage, but the main constraint here is that cout syntax must be used.
cout << "message";
I was thinking of invoking the VB msgbox command in the cout output, but couldn't find anything that worked.
Any ideas?
C++ streams work with console or file streams. Windows work on a more or less completely different paradigm, so the cout context isn't really a good one for working with this. You could probably completely mash up something that would end up more or less working, and looking more or less similar to this syntax, but it's not really worth it when you can just do:
MessageBox( NULL, message, "", MB_OK );
See the full docs on MessageBox for more info.
First thing you should take into account is that MessageBox stops the thread until you close the window. If that is the behavior you desire, go ahead.
You can create a custom streambuf and set it to 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
}
A popup will be shown whenever std::cout stream is flushed.
By including sstream, you can use std::ostringstream and build a message using the iostream library. You can then call .str().c_str() and get a char * to pass to MessageBox.
When confronted with this in the past, I've used a stringstream along with a manipulator that displays the current contents of the stringstream using 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;
}
To use this, the syntax looks a fair amount like using cout, but with MessageBox replacing std::endl. For example:
std::ostringstream stm;
stm << " blah blah blah. Value: " << 1213.1231 << MessageBox;
Edit: mostly for fnieto. In this case, the downcast really is necessary. The reason is fairly simple: a typical inserter receives and returns a reference to an ostream:
std::ostream &operator<<(std::ostream &os, T const &t) {
// code here to insert t into os, then return os;
}
This takes the original stringstream object and silently (and safely) casts it up to a simple ostream. That's fine in itself, and works fine for most inserters and manipulators, because they only interact with the ostream interface themselves.
This manipulator, however, is a bit different -- it uses the str() member, which ostream doesn't define at all. For our call to str() to resolve and compile, we have to convert the ostream & to an ostringstream &, so the compiler is aware that the object we're working with really will have a str() member.
To eliminate the downcast, we'd really only have one choice: make its parameter an ostringstream &. That would work as long as we never chained operators:
my_stream << x;
my_stream << MessageBox;
but trying to chain those would fail:
// should be equivalent:
my_stream << x << MessageBox;
Worse, the compiler's error message will probably try to tell the user something about std::basic_ostream<char>::str(), which isn't mentioned in the user's code at all. Worse still, most people are sufficiently accustomed to chaining or not giving identical results that it would probably take them a while to even figure out why the code sometimes worked fine, and other times failed to compile, with a completely indecipherable error message.
No simple way anyway.
The c in cout stands for console, so you're probably out of luck.
If it's just the syntax you're looking to copy, then you could write your own stream class that creates a message box under the hood and displays it.
You may want to check this out:
How can I redirect stdout to some visible display in a Windows Application?
Can a windows message box be display using the cout syntax?
You can't do it with std::cout. std::cout doesn't even promise to handle Unicode/wide characters (see std::wcout), although Windows's cout has no trouble with wide characters.
You could easily do it with the same syntax; that is, you could easily write a library that overloads operator<< to display dialog boxes. Trying to pass all the information to the dialog box that way would be very difficult, though (how would you you say which buttons to show, what those buttons should do when pressed, where those buttons should be, and the size and position of the window itself?).
You may want to look at something like ncurses. The syntax is different, but I have a
feeling it's what your coworker is looking for.