最近在做实验室项目,因为某些原因需要在MFC下开发,源码中涉及的COUT输出需要显示。
开始采取的方案一直是在控制台中显示,由于SetWindowText和GetWindowText代替了控制台的流,mfc下不能直接使用cout。
借鉴http://blog.csdn.net/wf6892/article/details/52955935
1.在MainFrame.h中添加头文件:
#include
#include
2.在MainFrame.h中声明函数:
public:
bool OpenConsole();
3.在MainFrame.cpp中添加函数定义:
bool CMainFrame::OpenConsole()
{
// 保证函数只执行一次
static bool Runed = false;
if (Runed)
return false;
Runed = true;
bool result;
HANDLE hStd;
FILE* fp;
long hFile;
result = AllocConsole();
hStd = GetStdHandle(STD_INPUT_HANDLE);
hFile = (long)_open_osfhandle((intptr_t)hStd, _O_TEXT);
fp = _fdopen(hFile, "r");
(*stdin) = (*fp);
hStd = GetStdHandle(STD_OUTPUT_HANDLE);
hFile = (long)_open_osfhandle((intptr_t)hStd, _O_TEXT);
fp = _fdopen(hFile, "w"); // 注意:必须是可写模式
(*stdout) = (*fp);
hStd = GetStdHandle(STD_ERROR_HANDLE);
hFile = (long)_open_osfhandle((intptr_t)hStd, _O_TEXT);
fp = _fdopen(hFile, "w"); // 注意:必须是可写模式
(*stderr) = (*fp);
cout << "打开控制台成功" << endl;
return result;
}
OpenConsole();
5.在要cout的类的头文件中加入如下代码:
#include
using namespace std;
后面因为需要在UI界面中进行输出,所以不得不另谋他路,使用的方法是直接从流中读取数据进行输出,这里说明一下,我的控件是多行文本,如果出现字符串闪动或者太长的话,可以参考这篇博客http://blog.csdn.net/jinhill/article/details/6180321
在UI界面输出
首先建立一个头文件
log.h
template >
class StandardOutputRedirector : public std::basic_streambuf {
typedef void(*cb_func_ptr)(const Elem*, std::streamsize count, void* data);
//typedef void(*cb_func_ptr)(const Elem*, std::streamsize count);
public:
StandardOutputRedirector(std::ostream& stream, cb_func_ptr cb_func,
void* data)
: stream_(stream), cb_func_(cb_func), data_(data) {
buf_ = stream_.rdbuf(this);
};
~StandardOutputRedirector() { stream_.rdbuf(buf_); }
std::streamsize xsputn(const Elem* ptr, std::streamsize count) {
cb_func_(ptr, count, data_);
return count;
}
typename Tr::int_type overflow(typename Tr::int_type v) {
Elem ch = Tr::to_char_type(v);
cb_func_(&ch, 1, data_);
return Tr::not_eof(v);
}
private:
std::basic_ostream& stream_;
std::streambuf* buf_;
cb_func_ptr cb_func_;
void* data_;
};
StandardOutputRedirector>* cout_redirector_;
在XXX.H中添加:
public:
static void update(const char* text, std::streamsize count, void* log_widget_ptr);
void show(const char* text, std::streamsize count, void* log_widget_ptr);
private:
static Reconstruction * res
在XXX.CPP中添加:
需要在XXX类构造函数中添加
res = this;
cout_redirector_ = new StandardOutputRedirector>(std::cout, update, this);
另外需要添加
XXX* XXX::res;
void XXX::update(const char* text, std::streamsize count, void* log_widget_ptr) {
res->show(text, count, log_widget_ptr);
}
void XXX::show(const char* text, std::streamsize count, void* log_widget_ptr) {
std::string text_str;
for (std::streamsize i = 0; i < count; ++i) {
if (text[i] == '\n') {
text_str += "\n";
}
else {
text_str += text[i];
}
}
CEdit *pEt = (CEdit *)GetDlgItem(LOG_EDIT);
int nLength = pEt->SendMessage(WM_GETTEXTLENGTH);
pEt->SetSel(nLength, nLength);
pEt->ReplaceSel(text_str.c_str());
pEt->LineScroll(pEt->GetLineCount());
}
之所以会使用到两个函数和一个静态变量,是因为出现的静态函数调用非静态成员函数或变量带来的问题,如果要对文本框进行赋值显示,必须先声明及实例化一个对象才可以,因此为了避免这点带来的问题,特意先声明一个静态变量和非静态成员函数。
如上,就应该可以在LOG_EDIT文本框中得到COUT的输出了