一、閒扯
今天領導心血來潮說伺服器的執行介面是乙個黑乎乎的控制台,太低端了,看我們能不能把它圖形化,至少做成乙個視窗有按鈕點啟動、停止。好吧,領導拍腦袋就叫人幹活的事不少,也沒有產品規劃,也就是讓他看的舒服,只能去做了。
其中有乙個關鍵性問題,就是原先是往控制台輸出的資訊,使用mfc圖形化之後該往哪輸出,工程維護人員肯定還是希望能在圖形介面上能夠看到這些資訊的,因此就涉及到了如何獲取到輸出控制台的訊息(都是cout、printf這種標準輸出),然後再將這些訊息重寫到view上。這時候想到了標準輸出重定向,因此整理了下思路:
1.將標準輸出重定向到管道
2.建立乙個執行緒從管道裡取出資料
3.在view的onpaint中將資料顯示出來
二、實現
1.建立管道
bool bret = createpipe(&hread, &hwrite, null, 0); // 建立匿名管道
if (bret != true)
printf("建立匿名管道失敗,錯誤**:%d\n", getlasterror());
2.將標準輸出重定向到管道的寫控制代碼中
int nopenhandle = _open_osfhandle((intptr_t)hwrite, _o_text);
file* fp = _fdopen( nopenhandle, "w");
*stdout = *fp;
注意:這裡不能使用setstdhandle(std_output_handle, hwrite),在mfc中setstdhandle是沒有效果的。
3.建立執行緒從管道取資料
boost::thread thr(boost::bind(&ckdsshellview::print_cb, this));
這裡用到boost的thread建立執行緒,ckdsshellview就是你自己的view了,print_cb是自定義的執行緒函式。
void ckdsshellview::print_cb()
; while (1) }
}
std::vectortmp;
boost::split(tmp, strlog, boost::is_any_of("\n"));
for (int i = 0; i < tmp.size(); ++i)
else
}log_vector.push_back(str);
} }if(::iswindow(m_hwnd)) }
由於輸出的字串有\n\r的換行符,並且可能有多條日誌同時輸出,在view中顯示不美觀,因此做了一些字串的調整,主要是有log_vector.push_back(str),這是將處理好的字串裝入容器中,然後通過updatewindow()觸發view的onpaint()。
void ckdsshellview::onpaint()
int j = 0;
for(; i < log_vector.size(); i++)
// 不為繪圖訊息呼叫 cview::onpaint()
}
效果如下圖:
控制台輸出重定向到Memo
函式runcmd void fastcall tform1 runcmd ansistring cmdline,tstrings result else createpipe hreadpipe,hwritepipe,null,1024 screen cursor crhourglass try d...
控制台輸入輸出重定向
一般來講gui程式不能使用stdin和stdout,但是有時有些特殊需要,希望gui程式也有控制台,如 乙個程式,既可以以gui方式執行,又可以如果使用者在控制台裡打程式名的話,就以控制台程式的方式執行。通過allocconsole 和 attachconsole 這兩個win api就能實現上面的...
MFC控制台指令的重定向輸出到檔案方法
前一篇文章講過如何隱藏控制台視窗,並把結果返回。但是控制台有個輸出重定向輸出到檔案功能,這個在createprocess中是不支援的。因此那個函式改進如下 tchar strlog 1024 cstring strcmp t test.exe abc abc.h runcmd strlog,strc...