地址:http://blog.csdn.net/huiyouyongdeyu2011/article/details/6556168
AllocConsole Function 為主調進程分配一個新的控制台。
文法 C++ : BOOL WINAPI AllocConsole(void); 參數: 無 傳回值:如果函數成功,傳回值是非零值;如果函數失敗,傳回值是零值。 備忘: 一個進程僅能關聯一個控制台,所以該函數在主調進程已經具有控制台時將會失敗。 一個進程可以使用 FreeConsole 函數來釋放與之關聯的控制台,之後它就可以調用該函數來建立一個新的控制台或使用 AttachConsole 函數來關聯另一個控制台。 如果主調進程建立了一個子進程,則子進程也將繼承這個新建立的控制台。 該函數為新的控制台初始化標準輸入、輸出、錯誤控制代碼等。 標準輸入控制代碼是一個控制台輸入緩衝的控制代碼,標準輸出和標準錯誤控制代碼則是控制台螢幕緩衝的控制代碼。為了獲得這些控制代碼,可以使用 GetStdHandle 函數。 該函數主要用於GUI應用程式來建立一個控制台視窗。 GUI應用程式初始化時時沒有控制台的,而控制台應用程式則以控制台來初始化的。 要求 : Minimum supported client Windows 2000 Professional Minimum supported server Windows 2000 Server Header: Wincon.h (include Windows.h) Library: Kernel32.lib DLL Kernel32.dll
----------------------------------------------------------------------------------------
雖然WIN32時代是圖形介面時代,但偶爾程式中還需要用到命令列模式,比如批處理,這時再搞個圖形介面出來顯得似乎就不那麼專業
了。但客戶還需要在正常狀態下(對於命令列模式,我認為使用者是非正常狀態,比如腦子進水。)使用圖形介面,這決定我們不能開一個控制台工程,而需要使用
MFC exe程式。
OK,理所當然的,通過條件控制,命令列下我關掉對話方塊介面的調用代碼,再使用
cout << "Hello world!" << endl; 來向這個友好的世界打個招呼,並堅持認為這句問候應該顯示在CMD那個漆黑的視窗裡。
很沮喪地說,事實給我與痛擊。cmd視窗裡仍然漆黑一片,系統完全不理會我的友好。
鄧爺爺說,改革開放好!也許,我也需要個改革。
在同事mr. zhang的指導下,我找到一組API:Console Functions!正是這組API,最終讓我的友好得以正當地表達。
一。建立一個Console,AllocConsole
直接使用 AllocConsole(); 馬上,若是進程內第一次調用這個函數,一個空的cmd視窗會蹦出來。需要注意,一個進程只能建立一個console,多次調用會返回FALSE;而且,這個視窗是個獨立的控制台視窗。
MSDN的解釋:A process can be associated with only one console, so the
AllocConsole function fails if the calling process already has a
console. 還有段:If the calling process creates a child process, the child
inherits the new console.
二。顯示Hello World,WriteConsole
有了console,我們還需要擷取它的控制代碼HANDLE,然後才能在上面顯示。方法是 GetStdHandle,它會擷取前面我們AllocConsole得到的cmd視窗的控制代碼;若未調用AllocConsole,將擷取標準的輸入輸出視窗控制代碼。
MSDN的解釋:The GetStdHandle function returns a handle for the standard input, standard output, or standard error device.
HANDLE hdlWrite = GetStdHandle(STD_OUTPUT_HANDLE); //這裡也可以使用STD_ERROR_HANDLE
TCHAR c[] = {"Hello world!"};
WriteConsole(hdlWrite, c, sizeof(c), NULL, NULL);
得到Console的控制代碼後直接使用 WriteConsole
函數即可在螢幕上顯示啦。這個函數有5個參數:第一個是console的控制代碼,第二個是寫出內容的地址,第三個參數是預計寫出長度,第四個參數是實際寫出
長度,可為NULL,但不建議,若使用NULL,boundchecker會在這提示錯誤用法,第五參數系統保留,必須使用NULL。
MSDN裡說也可以使用WriteFile來向console的handle輸出。
三。擷取使用者輸入, ReadConsole
光顯示是不夠的,使用者還需要操作啊,當然,是鍵盤輸入。
前面我們已經建立了一個Console,輸入也需要使用這個console,但若還用上面的OUTPUT控制代碼就不行了,我們會發現,程式在下面這句會直接跳過。
ReadConsole(hdlWrite, c, 2, NULL, NULL);
這裡,我們還需要一個STD_INPUT_HANDLE;如下:
TCHAR Buffer[100]; //開緩衝
memset(Buffer, 0, 100);
DWORD dwCount = 0;//已輸入數
HANDLE hdlRead = GetStdHandle(STD_INPUT_HANDLE);
ReadConsole(hdlRead, Buffer, 100, &dwCount, NULL);
這個函數和WriteConsole類似,但需要注意的是,第四個參數必須指定,否則會無法讀取。
MSDN裡還提到,若需要擷取其它鍵盤外的輸入資訊,如滑鼠資訊,只能使用ReadConsoleInput函數:
If the input buffer contains input events other than keyboard events
(such as mouse events or window-resizing events), they are discarded.
Those events can only be read by using the ReadConsoleInput function.
四。關閉Console
最後用完記得使用CloseHandle釋放控制代碼,如:
CloseHandle(hdlRead);
CloseHandle(hdlWrite);
若想關閉Console,可以使用FreeConsole(); 需要注意的是,若使用者直接點擊cmd視窗的關閉按鈕,整個程式(Application)將退出!
五。其他函數
這組函數還提供了其他有趣的功能,比如修改console的背景色,前景色彩等。更多函數請參見MSDN。
AllocConsole();
SetConsoleTitle("Lonefox love China"); //修改Console的標題
HANDLE hConsole = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE, //許可權
FILE_SHARE_READ | FILE_SHARE_WRITE, //console的共用方式
NULL,//安全性設定,NULL預設即可
CONSOLE_TEXTMODE_BUFFER,//唯一值
NULL//保留
);//建立console的螢幕內容緩衝,一個進程可以有多個ScreenBuffer
SetConsoleActiveScreenBuffer(hConsole); //顯示該buffer的內容
SetConsoleTextAttribute(hConsole,
FOREGROUND_RED | BACKGROUND_GREEN);
TCHAR c[] = {"Hello world!/n"};
WriteConsole(hConsole, c, sizeof(c), NULL, NULL); //在螢幕顯示
CloseHandle(hConsole);
FreeConsole();
後記:本文僅學習筆記,非教科書。若有問題歡迎留言討論!
--------------------------------------------------------------------------------
簡單的方法是:
if(AllocConsole())
{
freopen("CONOUT$","w",stdout);
printf("AllocConsole [OK]\n");
}
即可重新導向標準輸出,方便gui程式調試.
--------------------------------------------------------------------------------
本文完.