1

I have been messing around all day trying to get my MFC application to show the log output of a console application on the screen. Starting with what Visual Studio 2013's wizard gave me, I was able to modify their code to take a string as input and make a running log of application messages (below):

void COutputWnd::FillBuildWindow(std::string build_text)
{
std::wstring wsTmp(build_text.begin(), build_text.end());
std::wstring z = wsTmp;
LPTSTR x = new TCHAR[z.size() + 1];
_tcscpy(x, z.c_str());
m_wndOutputBuild.AddString(x);
free(x);
}

However, I cannot call this from outside the MFC function for a number of reasons. One is the object is not visible globally and two I am using windows.h in the console parts of my application and it does not play nicely with MFC.

Much of my application is already written and I am trying to put a GUI around it and use the ribbon features. Is there any way to take the cout statements and pipe them to a message log display in my MFC app? I have googled a ton of things today and not found anything that is either straightforward or clearly for applications which have both MFC and console code as part of their solution. I am not invoking a separate executable or dll. This is all compiled as a single standalone exe.

3
  • Are you trying to write to the Debug Output window in VS? Commented Nov 25, 2013 at 22:39
  • No, I am trying to present the user with output. For example they have a list of golf scores and I give them the top players in the output screen. Or errors, like they had bad data. Commented Nov 25, 2013 at 22:51
  • It's a bit of a far stretch to claim that MFC doesn't cope well with <windows.h>, considering that MFC's <afxv_w32.h> includes <windows.h>. Commented Nov 25, 2013 at 22:53

1 Answer 1

3

I have no idea about MFC but I would derive a class from std::streambuf to redirect its output to an MFC class and install the resulting stream buffer into std::cout. The stream buffer deals with the output written to a stream and you can get hold of the written characters in its overflow() and sync() methods:

class windowbuf
    : std::streambuf {
    SomeHandle handle;
    char       buffer[256];
public:
    typedef std::char_traits<char> traits;
    windowbuf(SomeHandle handle): handle(handle) { this->setp(buffer, buffer + 255); }
    int overflow(int c) {
        if (!traits::eq_int_type(c, traits::eof())) {
            *this->pptr() = traits::to_char_type(c);
            this->pbump(1);
        }
        return this->sync() == -1? traits::eof(): traits::not_eof(c);
    }
    int sync() {
        writeToHandle(this->handle, this->pbase(), this->pptr() - this->pbase());
        this->setp(buffer, buffer + 255);
        return 0;
    }
};

The above is a simple stream buffer which transfers characters somewhere identified by handle when its buffer is full or when the stream is flushed. I think it should be doable to come up with some handle and a write function which transfers the characters to an MFC window although I don't know anything about that part.

To have std::cout send its characters to the above stream buffer, you just need to install this stream buffer into std::cout, e.g., using

int main() {
    SomeHandle handle = get_a_handle_from_somewhere();
    std::streambuf* cout_rdbuf = std::cout.rdbuf(new windowbuf(handle));
    // run your program here
    std::cout.rdbuf(cout_rdbuf); // this should really be restored using RAII approaches
}

I'd think something like the above approach should be able to bridge the gap between some code writing to std::cout and other parts of the code displaying information with some sort of GUI.

Sign up to request clarification or add additional context in comments.

7 Comments

You left out the hard part: Attaching to a console's STDOUT, the part behind get_handle_from_somewhere(). Extra credits if you make this non-blocking (which you have to, since you are running on the GUI thread).
@IInspectable: I certainly didn't leave out the part capturing the programs output to std::cout: this is what the stream buffer is all about! The original request actually wasn't about capturing the program output but rather what is written to std::cout which is is a lot easier. Transferring the character between threads isn't much of an issue, either: just write them into a suitable queue.
I see what you mean, your SomeHandle refers to the GUI widget. Transferring output between threads is still somewhat involved. Still, +1 from me.
I was hoping it was not going to be this involved. One would think that Microsoft would have an easier solution for writing output from one hpp file to the window of another hpp file.
@matusi143: I can't comment on the Windows parts and I can imagine that there is a class which does roughly what I outlined above. However, I'm a UNIX programmer and I can only comment on the IOStreams side of it. The above approach may still provide the necessary starting point to find a suitable class.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.