




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、.控制臺窗口界面編程控制、摘要 一、概述 二、控制臺文本窗口的一般控制步驟 三、控制臺窗口操作 四、文本屬性操作 五、文本輸出 六、文本操作示例 七、滾動和移動 八、光標操作 九、讀取鍵盤信息 十、讀取鼠標信息 十一、結(jié)語 補充篇-經(jīng)典程序(Internet資源)摘要:文本界面的控制臺應用程序開發(fā)是深入學習C+、掌握交互系統(tǒng)的實現(xiàn)方法的最簡單的一種手段。然而,Visual C+的C+專用庫卻沒有TC所支持的文本(字符)屏幕控制函數(shù),為此本系列文章從一般控制步驟、控制臺窗口操作、文本(字符)控制、滾動和移動光標、鍵盤和鼠標等幾個方面討論控制臺窗口界面的編程控制方法。在眾多C+開發(fā)工具中,由于Mi
2、crosoft本身的獨特優(yōu)勢,選用 Visual C+已越來越被眾多學習者所接受。顯然,現(xiàn)今如果還再把TC作為開發(fā)環(huán)境的話,不僅沒有必要,而且也不利于向Windows應用程序開發(fā)的過渡。然而,Visual C+的C+專用庫卻沒有TC所支持的文本屏幕(控制臺窗口)控制函數(shù)(相應的頭文件是conio.h)。這必然給C+學習者在文本界面設計和編程上帶來諸多不便。要知道,文本界面設計是一種深入學習C+、掌握交互系統(tǒng)的實現(xiàn)方法的最簡單的一種手段,它不像C+的Windows圖形界面應用 程序,涉及知識過多。為此,本系列文章來討論在Visual C+ 6.0開發(fā)環(huán)境中,如何編寫具有美觀清晰的控制臺窗口界面的
3、C+應用程序。(一) 概述操作所謂控制臺應用程序,就是指那些需要與傳統(tǒng)DOS操作系統(tǒng)保持某種程序的兼容,同時又不需要為用戶提供完善界面的程序。簡單地講,就是指在Windows環(huán)境下運行的DOS程序。一旦控制臺應用程序在Windows操作系統(tǒng)中運行后,就會彈出一個窗口。例如下列代碼:#include <stdio.h>int main(int argc,char *argv)printf("Hello, Console!n");return 0;單擊小型編譯工具欄中的“Build”按鈕或按F7鍵,系統(tǒng)出現(xiàn)一個對話框,詢問是否將此項目的工作文件夾設定源文件所在的文件
4、夾,單擊是按鈕,系統(tǒng)開始編譯。 單擊小型編譯工具欄中的“Execute Program”按鈕或按Ctrl+F5鍵,運行剛才的程序。 程序運行后,彈出下圖的窗口:這就是控制臺窗口,與傳統(tǒng)的DOS屏幕窗口相比最主要的區(qū)別有:(1) 默認的控制臺窗口有系統(tǒng)菜單和標題,它是一個內(nèi)存緩沖區(qū)窗口,緩沖區(qū)大小取決于Windows操作系統(tǒng)的分配;而DOS屏幕是一種物理窗口,不具有Windows窗口特性,其大小取決于ROM BIOS分配的內(nèi)存空間。(2) 控制臺窗口的文本操作是調(diào)用低層的Win32 APIs,而DOS屏幕的文本操作是通過調(diào)用BIOS的16(10h)中斷而實現(xiàn)的。(3) 默認的控制臺窗口可以接收鍵
5、盤和鼠標的輸入信息,設備驅(qū)動由Windows管理,而DOS屏幕窗口接收鼠標時需要調(diào)用33h中斷,且鼠標設備驅(qū)動程序由自己安裝。(二) 控制臺文本窗口的一般控制步驟在Visual C+ 6.0中,控制臺窗口界面的一般編程控制步驟如下:調(diào)用GetStdHandle獲取當前的標準輸入(STDIN)和標準輸出(STDOUT)設備句柄。函數(shù)原型為:HANDLE GetStdHandle( DWORD nStdHandle );其中,nStdHandle可以是STD_INPUT_HANDLE(標準輸入設備句柄)、STD_OUTPUT_HANDLE(標準輸出設備句柄)和 STD_ERROR_HANDLE(標
6、準錯誤句柄)。需要說明的是,“句柄”是Windows最常用的概念。它通常用來標識Windows資源(如菜單、 圖標、窗口等)和設備等對象。雖然可以把句柄理解為是一個指針變量類型,但它不是對象所在的地址指針,而是作為Windows系統(tǒng)內(nèi)部表的索引值來使用 的。調(diào)用相關(guān)文本界面控制的API函數(shù)。這些函數(shù)可分為三類。一是用于控制臺窗口操作的函數(shù)(包括窗口的緩沖區(qū)大小、窗口前景字符和背景顏色、窗口標題、大小和位置等);二是用于控制臺輸入輸出的函數(shù)(包括字符屬性操作函數(shù));其他的函數(shù)并為最后一類。 調(diào)用CloseHandle()來關(guān)閉輸入輸出句柄。 注意,在程序中還必須包含頭文件windows.h。下面
7、看一個程序:#include <windows.h>#include <stdio.h>#include <conio.h>int main(void)HANDLE hOut;CONSOLE_SCREEN_BUFFER_INFO bInfo; / 存儲窗口信息COORD pos = 0, 0;/ 獲取標準輸出設備句柄hOut = GetStdHandle(STD_OUTPUT_HANDLE); / 獲取窗口信息GetConsoleScreenBufferInfo(hOut, &bInfo ); printf("nnThe soul sele
8、cts her own societyn");printf("Then shuts the doorn");printf("On her devine majorityn");printf("Obtrude no morenn");_getch();/ 向窗口中填充字符以獲得清屏的效果FillConsoleOutputCharacter(hOut,' ', bInfo.dwSize.X * bInfo.dwSize.Y, pos, NULL);/ 關(guān)閉標準輸出設備句柄CloseHandle(hOut); re
9、turn 0;程序中,COORD和CONSOLE_SCREEN_BUFFER_ INFO是wincon.h定義的控制臺結(jié)構(gòu)體類型,其原型如下:/ 坐標結(jié)構(gòu)體typedef struct _COORD SHORT X; SHORT Y; COORD; / 控制臺窗口信息結(jié)構(gòu)體typedef struct _CONSOLE_SCREEN_BUFFER_INFO COORD dwSize; / 緩沖區(qū)大小COORD dwCursorPosition; / 當前光標位置WORD wAttributes; / 字符屬性SMALL_RECT srWindow; / 當前窗口顯示的大小和位置COORD dw
10、MaximumWindowSize; / 最大的窗口緩沖區(qū)大小 CONSOLE_SCREEN_BUFFER_INFO ;還需要說明的是,雖然在C+中,iostream.h定義了cin和cout的標準輸入和輸出流對象。但它們只能實現(xiàn)基本的輸入輸出 操作,對于控制臺窗口界面的控制卻無能為力,而且不能與stdio.h和conio.h友好相處,因為iostream.h和它們是C+兩套不同的輸入 輸出操作方式,使用時要特別注意。(三) 控制臺窗口操作操作用于控制臺窗口操作的API函數(shù)如下:GetConsoleScreenBufferInfo 獲取控制臺窗口信息GetConsoleTitle 獲取控制臺窗
11、口標題ScrollConsoleScreenBuffer 在緩沖區(qū)中移動數(shù)據(jù)塊SetConsoleScreenBufferSize 更改指定緩沖區(qū)大小SetConsoleTitle 設置控制臺窗口標題SetConsoleWindowInfo 設置控制臺窗口信息此外,還有窗口字體、顯示模式等控制函數(shù),這里不再細說。下列舉一個示例,程序如下:#include <windows.h>#include <stdio.h>#include <conio.h>int main(void)char strTitle255;CONSOLE_SCREEN_BUFFER_INF
12、O bInfo; / 窗口緩沖區(qū)信息COORD size = 80, 25;HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); / 獲取標準輸出設備句柄GetConsoleScreenBufferInfo(hOut, &bInfo ); / 獲取窗口緩沖區(qū)信息GetConsoleTitle(strTitle, 255); / 獲取窗口標題printf("當前窗口標題是:n%sn", strTitle);_getch();SetConsoleTitle("控制臺窗口操作"); / 設置窗口標題GetCons
13、oleTitle(strTitle, 255); printf("當前窗口標題是:n%sn", strTitle);_getch();SetConsoleScreenBufferSize(hOut,size); / 重新設置緩沖區(qū)大小_getch();SMALL_RECT rc = 0,0, 80-1, 25-1; / 重置窗口位置和大小SetConsoleWindowInfo(hOut,true ,&rc);CloseHandle(hOut); / 關(guān)閉標準輸出設備句柄return 0;需要說明的是,控制臺窗口的原點坐標是(0, 0),而最大的坐標是緩沖區(qū)大小減1
14、,例如當緩沖區(qū)大小為80*25時,其最大的坐標是(79, 24)。(四) 文本屬性操作操作與DOS字符相似,控制臺窗口中的字符也有相應的屬性。這些屬性分為:文本的前景色、背景色和雙字節(jié)字符集(DBCS)屬性三種。事實上,我們最關(guān)心是文本顏色,這樣可以構(gòu)造出美觀的界面。顏色屬性都是一些預定義標識:FOREGROUND_BLUE 藍色FOREGROUND_GREEN 綠色FOREGROUND_RED 紅色FOREGROUND_INTENSITY 加強BACKGROUND_BLUE 藍色背景BACKGROUND_GREEN 綠色背景BACKGROUND_RED 紅色背景BACKGROUND_INTE
15、NSITY 背景色加強COMMON_LVB_REVERSE_VIDEO 反色與文本屬性相關(guān)的主要函數(shù)有:BOOL FillConsoleOutputAttribute( / 填充字符屬性HANDLE hConsoleOutput, / 句柄WORD wAttribute, / 文本屬性DWORD nLength, / 個數(shù)COORD dwWriteCoord, / 開始位置LPDWORD lpNumberOfAttrsWritten / 返回填充的個數(shù));BOOL SetConsoleTextAttribute( / 設置WriteConsole等函數(shù)的字符屬性HANDLE hConsoleO
16、utput, / 句柄WORD wAttributes / 文本屬性);BOOL WriteConsoleOutputAttribute( / 在指定位置處寫屬性HANDLE hConsoleOutput, / 句柄CONST WORD *lpAttribute, / 屬性DWORD nLength, / 個數(shù)COORD dwWriteCoord, / 起始位置LPDWORD lpNumberOfAttrsWritten / 已寫個數(shù));另外,獲取當前控制臺窗口的文本屬性是通過調(diào)用函數(shù)GetConsoleScreenBufferInfo后,在CONSOLE_SCREEN_ BUFFER_INF
17、O結(jié)構(gòu)成員wAttributes中得到。(五) 文本輸出操作文本輸出函數(shù)有:BOOL FillConsoleOutputCharacter( / 填充指定數(shù)據(jù)的字符HANDLE hConsoleOutput, / 句柄TCHAR cCharacter, / 字符DWORD nLength, / 字符個數(shù)COORD dwWriteCoord, / 起始位置LPDWORD lpNumberOfCharsWritten / 已寫個數(shù));BOOL WriteConsole( / 在當前光標位置處插入指定數(shù)量的字符HANDLE hConsoleOutput, / 句柄CONST VOID *lpBuff
18、er, / 字符串DWORD nNumberOfCharsToWrite, / 字符個數(shù)LPDWORD lpNumberOfCharsWritten, / 已寫個數(shù)LPVOID lpReserved / 保留);BOOL WriteConsoleOutput( / 向指定區(qū)域?qū)憥傩缘淖址鸋ANDLE hConsoleOutput, / 句柄CONST CHAR_INFO *lpBuffer, / 字符數(shù)據(jù)區(qū)COORD dwBufferSize, / 數(shù)據(jù)區(qū)大小COORD dwBufferCoord, / 起始坐標PSMALL_RECT lpWriteRegion / 要寫的區(qū)域);BOOL
19、WriteConsoleOutputCharacter( / 在指定位置處插入指定數(shù)量的字符HANDLE hConsoleOutput, / 句柄LPCTSTR lpCharacter, / 字符串DWORD nLength, / 字符個數(shù)COORD dwWriteCoord, / 起始位置LPDWORD lpNumberOfCharsWritten / 已寫個數(shù));可以看出:WriteConsoleOutput函數(shù)功能相當于SetConsoleTextAttribute和WriteConsole 的功能。而WriteConsoleOutputCharacter函數(shù)相當于SetConsoleC
20、ursorPosition(設置光標位置)和 WriteConsole的功能。不過在具體使用要注意它們的區(qū)別。(六) 文本操作示例操作下面看一個示例程序: / 在具有陰影效果的窗口中顯示一行字符#include <windows.h>HANDLE hOut;void ShadowWindowLine(char *str); void DrawBox(bool bSingle, SMALL_RECT rc); / 繪制邊框int main(void)hOut = GetStdHandle(STD_OUTPUT_HANDLE); / 獲取標準輸出設備句柄SetConsoleOutput
21、CP(437); / 設置代碼頁,這里如果設置成936(簡體中文),那么程序會怎樣?那樣的話,將畫不出邊框。ShadowWindowLine("Display a line of words, and center the window with shadow.");CloseHandle(hOut); / 關(guān)閉標準輸出設備句柄return 0;void ShadowWindowLine(char *str)SMALL_RECT rc;CONSOLE_SCREEN_BUFFER_INFO bInfo; / 窗口緩沖區(qū)信息WORD att0,att1,attText;int
22、i, chNum = strlen(str);GetConsoleScreenBufferInfo( hOut, &bInfo ); / 獲取窗口緩沖區(qū)信息/ 計算顯示窗口大小和位置rc.Left = (bInfo.dwSize.X - chNum)/2 - 2;rc.Top = 8; / 原代碼段中此處為bInfo.dwSize.Y/2 - 2,但是如果您的DOS屏幕有垂直滾動條的話,還需要把滾動條下拉才能看到,為了方便就把它改為10rc.Right = rc.Left + chNum + 4;rc.Bottom = rc.Top + 4;att0 = BACKGROUND_INTE
23、NSITY; / 陰影屬性att1 = FOREGROUND_RED |FOREGROUND_GREEN |FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE;/ 文本屬性attText = FOREGROUND_RED |FOREGROUND_INTENSITY; / 文本屬性/ 設置陰影然后填充COORD posShadow = rc.Left+1, rc.Top+1, posText = rc.Left, rc.Top;for (i=0; i<5; i+)FillConsoleOutpu
24、tAttribute(hOut, att0, chNum + 4, posShadow, NULL);posShadow.Y+;for (i=0;i<5;i+)FillConsoleOutputAttribute(hOut, att1,chNum + 4, posText, NULL);posText.Y+;/ 寫文本和邊框posText.X = rc.Left + 2;posText.Y = rc.Top + 2;WriteConsoleOutputCharacter(hOut, str, strlen(str), posText, NULL);DrawBox(true, rc);Se
25、tConsoleTextAttribute(hOut, bInfo.wAttributes); / 恢復原來的屬性void DrawBox(bool bSingle, SMALL_RECT rc) / 函數(shù)功能:畫邊框char chBox6;COORD pos;if (bSingle) chBox0 = (char)0xda; / 左上角點chBox1 = (char)0xbf; / 右上角點chBox2 = (char)0xc0; / 左下角點chBox3 = (char)0xd9; / 右下角點chBox4 = (char)0xc4; / 水平chBox5 = (char)0xb3; /
26、堅直elsechBox0 = (char)0xc9; / 左上角點chBox1 = (char)0xbb; / 右上角點chBox2 = (char)0xc8; / 左下角點chBox3 = (char)0xbc; / 右下角點chBox4 = (char)0xcd; / 水平chBox5 = (char)0xba; / 堅直/ 畫邊框的上 下邊界for(pos.X = rc.Left+1;pos.X<rc.Right-1;pos.X+)pos.Y = rc.Top;/ 畫上邊界WriteConsoleOutputCharacter(hOut, &chBox4, 1, pos,
27、NULL);/ 畫左上角if(pos.X = rc.Left+1)pos.X-;WriteConsoleOutputCharacter(hOut, &chBox0,1, pos, NULL);pos.X+;/ 畫右上角if(pos.X = rc.Right-2)pos.X+;WriteConsoleOutputCharacter(hOut, &chBox1, 1, pos, NULL);pos.X-;pos.Y = rc.Bottom;/ 畫下邊界WriteConsoleOutputCharacter(hOut, &chBox4, 1, pos, NULL);/ 畫左下
28、角if(pos.X = rc.Left+1)pos.X-;WriteConsoleOutputCharacter(hOut, &chBox2, 1, pos, NULL);pos.X+;/ 畫右下角if(pos.X=rc.Right-2)pos.X+;WriteConsoleOutputCharacter(hOut, &chBox3, 1, pos, NULL);pos.X-;/ 畫邊框的左右邊界for (pos.Y = rc.Top+1; pos.Y<=rc.Bottom-1; pos.Y+)pos.X = rc.Left;/ 畫左邊界WriteConsoleOutpu
29、tCharacter(hOut, &chBox5, 1, pos, NULL);pos.X = rc.Right-1;/ 畫右邊界WriteConsoleOutputCharacter(hOut, &chBox5, 1, pos, NULL);程序運行結(jié)果如下圖所示:需要說明的是:在上述例子中,如果調(diào)用DrawBox函數(shù)時,傳遞的第一個參數(shù)不是true而是false,那么畫出來的邊框?qū)⑹请p線的。運行結(jié)果如下:如果在上述程序無法編譯通過,您可以這樣修改,即程序中調(diào)用WriteConsoleOutputCharacter和FillConsoleOutputAttribute函數(shù)的時
30、候,最后一個參數(shù)不用NULL,而是先定義一個變量:DWORD written;然后把 &written作為最后一個參數(shù)。上述程序在不同的字符代碼頁面(code page)下顯示的結(jié)果是不同的。例如,中文Windows操作系統(tǒng)的默認代碼頁是簡體中文(936),在該代碼頁面下值超過128的單字符在Windows NT/XP是顯示不出來的。下表列出了可以使用的代碼頁。代碼頁(Code page)說明1258越南文1257波羅的海文1256阿拉伯文1255希伯來文1254土耳其語1253希臘文1252拉丁文(ANSI)1251斯拉夫文1250中歐文950繁體中文949韓文936簡體中文932日
31、文874泰文850使用多種語言(MS-DOS拉丁文)437MS-DOS美語/英語(七) 滾動和移動操作ScrollConsoleScreenBuffer是實現(xiàn)文本區(qū)滾動和移動的API函數(shù)。它可以將指定的一塊文本區(qū)域移動到另一個區(qū)域,被移空的那塊區(qū)域由指定字符填充。函數(shù)的原型如下:BOOL ScrollConsoleScreenBuffer(HANDLE hConsoleOutput, / 句柄CONST SMALL_RECT* lpScrollRectangle, / 要滾動或移動的區(qū)域CONST SMALL_RECT* lpClipRectangle, / 裁剪區(qū)域COORD dwDesti
32、nationOrigin, / 新的位置CONST CHAR_INFO* lpFill / 填充字符);利用這個API函數(shù)還可以實現(xiàn)刪除指定行的操作。下面來舉一個例子,程序如下:#include <windows.h>#include <stdio.h>#include <conio.h>HANDLE hOut;void DeleteLine(int row); / 刪除一行void MoveText(int x, int y, SMALL_RECT rc); / 移動文本塊區(qū)域void ClearScreen(void); / 清屏int main(voi
33、d)hOut = GetStdHandle(STD_OUTPUT_HANDLE); / 獲取標準輸出設備句柄WORD att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE;/ 背景是藍色,文本顏色是黃色SetConsoleTextAttribute(hOut, att);ClearScreen();printf("nnThe soul selects her own societyn");printf("Then shuts the door;n"
34、);printf("On her devine majority;n");printf("Obtrude no more.nn");COORD endPos = 0, 15;SetConsoleCursorPosition(hOut, endPos); / 設置光標位置SMALL_RECT rc = 0, 2, 40, 5;_getch();MoveText(10, 5, rc);_getch();DeleteLine(5);CloseHandle(hOut); / 關(guān)閉標準輸出設備句柄return 0;void DeleteLine(int row)S
35、MALL_RECT rcScroll, rcClip;COORD crDest = 0, row - 1;CHAR_INFO chFill;CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo( hOut, &bInfo ); rcScroll.Left = 0;rcScroll.Top = row;rcScroll.Right = bInfo.dwSize.X - 1;rcScroll.Bottom = bInfo.dwSize.Y - 1;rcClip = rcScroll;chFill.Attributes = b
36、Info.wAttributes;chFill.Char.AsciiChar = ' 'ScrollConsoleScreenBuffer(hOut, &rcScroll, &rcClip, crDest, &chFill);void MoveText(int x, int y, SMALL_RECT rc)COORD crDest = x, y;CHAR_INFO chFill;CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo( hOut, &bInfo ); chFill.
37、Attributes = bInfo.wAttributes;chFill.Char.AsciiChar = ' 'ScrollConsoleScreenBuffer(hOut, &rc, NULL, crDest, &chFill);void ClearScreen(void)CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo( hOut, &bInfo ); COORD home = 0, 0;WORD att = bInfo.wAttributes;unsigned long si
38、ze = bInfo.dwSize.X * bInfo.dwSize.Y;FillConsoleOutputAttribute(hOut, att, size, home, NULL);FillConsoleOutputCharacter(hOut, ' ', size, home, NULL);程序中,實現(xiàn)刪除行的操作DeleteLine的基本原理是:首先將裁剪區(qū)域和移動區(qū)域都設置成指定行row(包括該行)以下的控制臺窗口區(qū)域,然后將移動的位置指定為(0, row-1)。這樣,超出裁剪區(qū)域的內(nèi)容被裁剪掉,從而達到刪除行的目的。需要說明的是,若裁剪區(qū)域參數(shù)為NULL,則裁剪區(qū)域
39、為整個控制臺窗口。(八) 光標操作操作控制臺窗口中的光標反映了文本插入的當前位置,通過SetConsoleCursorPosition函數(shù)可以改變這個“當前”位置,這樣就能控制字符(串)輸出。事實上,光標本身的大小和顯示或隱藏也可以通過相應的API函數(shù)進行設定。例如:BOOL SetConsoleCursorInfo( / 設置光標信息HANDLE hConsoleOutput, / 句柄CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo / 光標信息);BOOL GetConsoleCursorInfo( / 獲取光標信息HANDLE hConsol
40、eOutput, / 句柄PCONSOLE_CURSOR_INFO lpConsoleCursorInfo / 返回光標信息);這兩個函數(shù)都與CONSOLE_CURSOR_INFO結(jié)構(gòu)體類型有關(guān),其定義如下:typedef struct _CONSOLE_CURSOR_INFO DWORD dwSize; / 光標百分比大小 BOOL bVisible; / 是否可見 CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;需要說明的是,dwSize值反映了光標的大小,它的值范圍為1-100;當為1時,光標最小,僅是一條最靠下的水平細線,當為100,光標最大,為一
41、個字符大小的方塊。(九) 讀取鍵盤信息操作鍵盤事件通常有字符事件和按鍵事件,這些事件所附帶的信息構(gòu)成了鍵盤信息。它是通過API函數(shù)ReadConsoleInput來獲取的,其原型如下:BOOL ReadConsoleInput(HANDLE hConsoleInput, / 輸入設備句柄PINPUT_RECORD lpBuffer, / 返回數(shù)據(jù)記錄DWORD nLength, / 要讀取的記錄數(shù)LPDWORD lpNumberOfEventsRead / 返回已讀取的記錄數(shù));其中,INPUT_RECORD定義如下:typedef struct _INPUT_RECORD WORD Even
42、tType; / 事件類型union KEY_EVENT_RECORD KeyEvent; MOUSE_EVENT_RECORD MouseEvent; WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; MENU_EVENT_RECORD MenuEvent; FOCUS_EVENT_RECORD FocusEvent; Event; INPUT_RECORD;與鍵盤事件相關(guān)的記錄結(jié)構(gòu)KEY_EVENT_RECORD定義如下:typedef struct _KEY_EVENT_RECORD BOOL bKeyDown; / TRUE表示鍵按下,F(xiàn)
43、ALSE表示鍵釋放WORD wRepeatCount; / 按鍵次數(shù)WORD wVirtualKeyCode; / 虛擬鍵代碼WORD wVirtualScanCode; / 虛擬鍵掃描碼union WCHAR UnicodeChar; / 寬字符CHAR AsciiChar; / ASCII字符 uChar; / 字符DWORD dwControlKeyState; / 控制鍵狀態(tài) KEY_EVENT_RECORD;我們知道,鍵盤上每一個有意義的鍵都對應著一個唯一的掃描碼,雖然掃描碼可以作為鍵的標識,但它依賴于具體設備的。因此,在應用程序中,使用的往往是與具體設備無關(guān)的虛擬鍵代碼。這種虛擬鍵
44、代碼是與設備無關(guān)的鍵盤編碼。在Visual C+中,最常用的虛擬鍵代碼已被定義在Winuser.h中,例如:VK_SHIFT表示SHIFT鍵,VK_F1表示功能鍵F1等。上述結(jié)構(gòu)定義中,dwControlKeyState用來表示控制鍵狀態(tài),它可以是CAPSLOCK_ON(CAPS LOCK燈亮)、ENHANCED_KEY(按下擴展鍵)、LEFT_ALT_PRESSED(按下左ALT鍵)、 LEFT_CTRL_PRESSED(按下左CTRL鍵)、NUMLOCK_ON (NUM LOCK燈亮)、RIGHT_ALT_PRESSED(按下右ALT鍵)、RIGHT_CTRL_PRESSED(按下右CTR
45、L鍵)、 SCROLLLOCK_ON(SCROLL LOCK燈亮)和SHIFT_PRESSED(按下SHIFT鍵)中的一個或多個值的組合。下面的程序是將用戶按鍵的字符輸入到一個控制臺窗口的某個區(qū)域中,并當按下NUM LOCK、CAPS LOCK和SCROLL LOCK鍵時,在控制臺窗口的最后一行顯示這些鍵的狀態(tài)。#include <windows.h>HANDLE hOut;HANDLE hIn;void DrawBox(bool bSingle, SMALL_RECT rc); / 這個自定義函數(shù)在第六章用過void ClearScreen(void);void CharWind
46、ow(char ch, SMALL_RECT rc); / 將ch輸入到指定的窗口中void ControlStatus(DWORD state); / 在最后一行顯示控制鍵的狀態(tài)void DeleteTopLine(SMALL_RECT rc); / 刪除指定窗口中最上面的行并滾動int main(void)hOut = GetStdHandle(STD_OUTPUT_HANDLE); / 獲取標準輸出設備句柄hIn = GetStdHandle(STD_INPUT_HANDLE); / 獲取標準輸入設備句柄WORD att = FOREGROUND_RED | FOREGROUND_GRE
47、EN | FOREGROUND_INTENSITY | BACKGROUND_BLUE ; / 背景是藍色,文本顏色是黃色SetConsoleTextAttribute(hOut, att);ClearScreen(); / 清屏INPUT_RECORD keyRec;DWORD state = 0, res;char ch;SMALL_RECT rc = 20, 2, 40, 12;DrawBox(false, rc);COORD pos = rc.Left+1, rc.Top+1;SetConsoleCursorPosition(hOut, pos); / 設置光標位置for(;) / 循
48、環(huán)ReadConsoleInput(hIn, &keyRec, 1, &res);if (state != keyRec.Event.KeyEvent.dwControlKeyState)state = keyRec.Event.KeyEvent.dwControlKeyState;ControlStatus(state);if (keyRec.EventType = KEY_EVENT)if (keyRec.Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE) break;/ 按ESC鍵退出循環(huán)if (keyRec.Event.KeyEven
49、t.bKeyDown)ch = keyRec.Event.KeyEvent.uChar.AsciiChar;CharWindow(ch, rc);pos.X = 0; pos.Y = 0;SetConsoleCursorPosition(hOut, pos); / 設置光標位置CloseHandle(hOut); / 關(guān)閉標準輸出設備句柄CloseHandle(hIn); / 關(guān)閉標準輸入設備句柄return 0;void CharWindow(char ch, SMALL_RECT rc) / 將ch輸入到指定的窗口中static COORD chPos = rc.Left+1, rc.To
50、p+1;SetConsoleCursorPosition(hOut, chPos); / 設置光標位置if (ch<0x20)|(ch>0x7e) / 如果是不可打印的字符,具體查看ASCII碼表return;WriteConsoleOutputCharacter(hOut, &ch, 1, chPos, NULL);if (chPos.X >= (rc.Right-2)chPos.X = rc.Left;chPos.Y+;if (chPos.Y>(rc.Bottom-1) DeleteTopLine(rc);chPos.Y = rc.Bottom-1;chPo
51、s.X+;SetConsoleCursorPosition(hOut, chPos); / 設置光標位置void ControlStatus(DWORD state) / 在第一行顯示控制鍵的狀態(tài)CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo( hOut, &bInfo ); COORD home = 0, 24; / 原來此處為bInfo.dwSize.Y-1,但為了更便于觀察,我把這里稍微修改了一下WORD att0 = BACKGROUND_INTENSITY ;WORD att1 = FOREGROUND_
52、GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED;FillConsoleOutputAttribute(hOut, att0, bInfo.dwSize.X, home, NULL);FillConsoleOutputCharacter(hOut, ' ', bInfo.dwSize.X, home, NULL);SetConsoleTextAttribute(hOut, att1);COORD staPos = bInfo.dwSize.X-16,24; / 原來此處為bInfo.dwSize.Y-1SetConsoleCursorP
53、osition(hOut, staPos);if (state & NUMLOCK_ON) WriteConsole(hOut, "NUM", 3, NULL, NULL);staPos.X += 4;SetConsoleCursorPosition(hOut, staPos);if (state & CAPSLOCK_ON) WriteConsole(hOut, "CAPS", 4, NULL, NULL);staPos.X += 5;SetConsoleCursorPosition(hOut, staPos);if (state &a
54、mp; SCROLLLOCK_ON) WriteConsole(hOut, "SCROLL", 6, NULL, NULL);SetConsoleTextAttribute(hOut, bInfo.wAttributes); / 恢復原來的屬性SetConsoleCursorPosition(hOut, bInfo.dwCursorPosition); / 恢復原來的光標位置void DeleteTopLine(SMALL_RECT rc)COORD crDest;CHAR_INFO chFill;SMALL_RECT rcClip = rc;rcClip.Left+; rcClip.Right -= 2;rcClip.Top+; rcClip.Bottom-;crDest.X = rcClip.Left;crDest.Y = rcClip.Top - 1;CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScre
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 木結(jié)構(gòu)建筑的日照模擬與優(yōu)化考核試卷
- 畜牧養(yǎng)殖疫病防控技術(shù)的研發(fā)與推廣考核試卷
- 紙板容器操作人員素質(zhì)提升考核試卷
- 稻谷種植農(nóng)業(yè)產(chǎn)業(yè)鏈協(xié)同創(chuàng)新考核試卷
- 噴槍在現(xiàn)代建筑外墻涂裝的應用考核試卷
- 竹材采運項目管理與招投標實務考核試卷
- 燈具行業(yè)展會策劃與參展技巧考核試卷
- 西藏大學《第二外語1(日語)》2023-2024學年第二學期期末試卷
- 玉樹藏族自治州稱多縣2025屆三下數(shù)學期末教學質(zhì)量檢測模擬試題含解析
- 蘇州信息職業(yè)技術(shù)學院《面向?qū)ο蠓治龊驮O計實踐》2023-2024學年第二學期期末試卷
- 防腐涂裝施工方案(22頁)
- 勞動關(guān)系管理法律實務案例題庫及答案(案例題)
- 2022年天津市中考道德與法治試題及答案解析
- 招商代理及運營管理服務合同(共9頁)
- 怎樣用PPT制作翻書效果
- 內(nèi)部控制風險評估報告模板
- 泵站課程設計(給水)
- 工程竣工照片檔案樣式01
- 福建省普通高等學校畢業(yè)生就業(yè)協(xié)議書A雙面打印
- 院校代表推廣手冊
- 連山易斷卦法(共60頁)
評論
0/150
提交評論