在Win32視窗程式中開啟console視窗
前言
用Win32視窗程式寫出來的測試程式一直以來有個麻煩,就是切換測試項目(如測試光、測試影子...等)時會需要終止程式後,修改部分的code後再run一次,如果能有個debug的工具可以在不關閉程式的狀況下修改程式特定的參數不是很好嗎?可是如果自己了視窗的控件再交由C++來控制的話,成本實在有點高,如果有個console視窗可以輸入命令和輸出結果就可以解決上述的問題。在此把學習的過程做個紀錄。內容
使用的示範如下//Open console... AllocConsole(); std::wstring strW = L"Dev Console"; SetConsoleTitle( strW.c_str() ); DrawMenuBar(GetConsoleWindow()); // //call ReadConsole() or WriteConsole() to control console //... //Close console... FreeConsole();
開啟console視窗後,用ReadConsole()與WriteConsole()來控制輸入與輸出,但這兩個funciton的參數不是很用,如果可以將輸出入的結果導到stdin與stdout的話,就可以直接使用C++的IO function(scanf、printf...等),這樣用起來比較直接也比較好懂,所以導到stdin與stdout的範例如下
//Open console... AllocConsole(); std::wstring strW = L"Dev Console"; SetConsoleTitle( strW.c_str() ); DrawMenuBar(GetConsoleWindow()); //Redirection IO to stdin and stdout freopen( "CON", "r", stdin ) ; freopen( "CON", "w", stdout ) ; //call c++ IO function to control console //... //Close console... FreeConsole();
上述的範例如果要搭配Win32視窗程式使用的話,需要自己產生一個thread去控制輸入,為什麼呢?因為IO的輸入是block funciton,如果使用主thread去取得IO的輸入的話,整個程式都會停頓下來,這點請務必注意!
接著還有一個麻煩是要將控制輸入的thread停下來的問題,當企圖停下一個thread時的標準做法是用WaitForSingleObject()來等待結束,可是scanf()或std::cin並不會自己中斷等待,所以需要給"假的"輸入來中斷IO的等待,範例如下
//abort console inpurt HWND hWndConsole=GetConsoleWindow(); INPUT ip[2]; ip[0].type = INPUT_KEYBOARD; ip[0].ki.wVk = 0x41;; ip[0].ki.wScan = 0; ip[0].ki.dwFlags = 0; ip[0].ki.time = 0; ip[0].ki.dwExtraInfo = 0; ip[1].type = INPUT_KEYBOARD; ip[1].ki.wVk = VK_RETURN; ip[1].ki.wScan = 0; ip[1].ki.dwFlags = 0; ip[1].ki.time = 0; ip[1].ki.dwExtraInfo = 0; SendInput(2, ip, sizeof(INPUT) );
在範例中是輸入"a"和"enter"去中止console的blocking,要注意指輸入一個"enter"是無法中止blocking,必須要有一個有效的字元!
後記
如果有看微軟的console使用說明Consoles的話,會發現還有其他的控制function可以使用,但由於本次的需求不需要用到所以都沒提到,有機會再來研究研究。參考資料
Creation of a ConsoleCreate window console inside main win32 window
Consoles
沒有留言:
張貼留言