用VB建立字符界面的控制臺程序

編輯推薦:VB初學者
即使是初學VB的人,對于如何用它來建立一個GUI界面的標準Windows應用程序,肯定也是胸有成竹;然而,對于如何用VB來編寫字符界面的控制臺程序(Console-Mode Applications),知道的人恐怕不多。有人甚至認為這是不可能的,因為VB對編寫控制臺程序并無內在的支持,在VB的“新建工程”對話框里沒有“控制臺程序”這一選項。實際上,利用Windows提供的應用程序編程接口(API),VB是能夠建立控制臺程序的。控制臺程序與圖形界面的標準Windows程序不同,它沒有Windows程序所通行的窗口,其與用戶的交互是基于字符界面,外觀類似于“MS-DOS方式”,同標準的Windows程序相比,控制臺程序具有界面簡單、占內存少、生成的可執行文件小的優點,因而在某些場合還有用武之地。
由于VB對建立控制臺程序并無內在支持,全部工作都是依靠調用API函數來完成,故首先要用VB建立一個新的“標準EXE”工程,并刪除其默認窗體(Form1),添加一標準模塊(Module1),將其改名為VBConsole.bas,后續的所有工作都是在此模塊中完成的。
下面按功能分類逐一介紹本文用到的API函數。
1.創建和銷毀控制臺窗口(consol window)用VB創建控制臺程序的第一步就是為VB程序創建一個console window,并在程序結束時銷毀它。這分別用到AllocConsole和FreeConsole函數。
| Private Declare Function AllocConsole Lib "kernel32"() As Long |
功能:為VB程序創建一個 console window。
| Private Declare Function FreeConsole Lib "kernel32"() AS Long |
功能:銷毀為VB程序創建的 console window。
2.取得所建立的 console window 的句柄(Handle)
DOS程序有三個標準文件:標準輸入文件(stdin),標準輸出文件(stdout),標準錯誤文件(siderr)。與此類似,控制臺程序窗口有三個句柄:
輸入句柄(input handle) — 指向控制臺程序的輸入緩沖區
輸出句柄(output handle)、錯誤句柄(error handle)— 指向控制臺程序的屏幕輸出緩沖區
在能夠進行輸入/輸出操作之前,必須用 GetstdHandle 函數取得 console window 的這三個句柄。
| Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long |
功能:返回 console window 的三個句柄之一。
說明:參數nStdHandle決定此函數返回的是哪一個句柄,它可以取如下值之一:
| Private Const STD_INPUT_HANDLE = -10& ''返回 input handle Private Const TD_OUTPUT_HANDLE = - 11&''返回 output handle Private Const STD_ERROR_HANDLE = -12& ''返回 error handle |
3.控制臺輸入/輸出創建了
console window 并獲得其 input/output handle 后,就可以利用WriteConsole和ReadConsole進行輸入/輸出了。
| Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" _ (ByVal hConsoleoutput As Long,ByVal lpBuffer As Any, ByVal nNumberofCharsTowrite _ As Long, IpNumberofCharsWritten As Long, lpReserved As Any) As Long |
功能:向控制臺窗口輸出字符串。
說明:hConsoleOutput—控制臺的outputhandle。
lpBuffer—要輸出的字符串。
nNumberOfCharsToWrite—要輸出的字符串的長度。
lpNumberofCharsWritten—實際輸出的字符串的長度,可置為vbNull。
lpReserved—保留,必須置為vbNul。
| Private Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" _ (ByVal hConsoleInput As Long, ByVal lpBuffer As String, ByVal nNumberofCharsToRead _ As Long,lpNumberofCharsRead As Long, lpReserved As Any) As Long |
功能:從輸入緩沖區輸入字符串。
說明:此函數是以塊方式輸入信息。在本文的示例中,只有用戶按了Enter(回車)鍵后,此函數才返回。
hConsoleInput—console window的input handle。
lpBuffer—輸入緩沖區地址。
nNumberOfCharsToRead—輸入緩沖區的長度。
lpNumberOfCharsRead—實際讀入的字符數,可置為vbNull。
lpReserved—保留,必須置為vbNull。
| Private Declare Function SetConsoleMode Lib "kernel32" (ByVal hConsoleHandle _ As Long, dwMode As Long) As Long |
功能:設置控制臺輸入緩沖區的輸人模式或屏幕輸出緩沖區的輸出模式。
說明:在用 ReadConsole和 WriteConsole函數行輸入/輸出前,要用此函數設置好輸入/輸出模式。
hConsoleHandle—console window的Input handle或output handle。
dwMode是要設置的輸入或輸出模式值。hConsoleHandle是Input handle時, dwMode可取如下值的組合:
| Private Const ENABLE_LINE_INPUT = &H2 Private Const ENABLE_ECHO_INPUT = &H4 Private Const ENABLE_MOUSE_INPUT = &H10 Private Const ENABLE_PROCESSED_INPUT = &H1 Private Const ENABLE_WINDOW_INPUT = &H8 |
當 hConsoleHandle 是 output handle 時,dwMode可取如下值的組合:
| Private Const ENABLE_PROCESSED_OUTPUT = &H1 Private Const ENABLE_WRAP_AT_EOL_OUTPUT = &H2 |
這些取值的具體意義,請參見 WINDOWS SDK 文檔,此處不再詳述。
注意:VB的API瀏覽器對WriteConsole和ReadConsole兩函數的聲明是不對的。盡管lpBuffer為長指針,它仍然應為傳值調用,這是由于VB和API對字符串的存儲和處理方式不一致造成的。
4.其他API函數
有了l、2、3所述的API函數,就可以創建一個基本的控制臺程序了。當然,我們還可以用如下的API函數再“修飾”一下呆板的控制臺窗口。
| Private Declare Function SetConsoleTitle_Lib "kernel32"Alias "SetConsoleTitleA" _ (ByVal lpConsoleTitle As String) As Long |
功能:設置控制臺窗口的標題。
說明:lpConsoeTitle—要設置的窗口標題(字符串)。
| Private Declare Functon SetConsoleTextAttribute Lib "hernel32" _ (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long |
功能:設置要在控制臺窗口輸出的字符的前景色和背景色
說明: hConsoleOutput—控制臺窗口的output handle
wAttributes—決定了console window的前景色和背景色,可以是如下數值的組合:
| Private Const FOREGROUND_BLUE = &H1 ''前景:藍 Private Const FOREGROUND_GREEN = &H2 ''前景:綠 Private Const FOREGROUND_RED = &H4 ''前恐;紅 Private Const FOREGROUND_INTENSITY = &H8 ''前景:高亮度 Private Const BACKGROUND_BLUE = &H10 ''背景:藍 Private Const BACKGROUND_GREEN = &H20 ''背景:綠 Private Const BACKGROUND_RED = &H40 ''背景:紅 Private Const BACKGROUND_INTENSITY = &H80 ''背景:高亮度 |
例如,要設置前景色為黃色,可定義如下的常量并將其賦值給 wAttributes。
| Private Const FOREGROUND_YELLOW = FOREGROUND_RED Or FOREGROUND_GREEN |
程序清單
示例程序將創建一個控制臺窗口,并輸出提示信息,要用戶輸入自己的名字。用戶輸入名字后,程序輸出問候信息,并等待用戶按鍵返回。本文的示例程序在VB6.0中文版下調試通過。
| Option Explicit '' API函數聲明 Private Declare Function AllocConsole Lib "kernel32" () As Long Private Declare Function FreeConsole Lib "kernel32" () As Long Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long Private Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" _ (ByVal hConsoleInput As Long, ByVal lpBuffer As String, ByVal nNumberOfCharsToRead _ As Long, lpNumherOfCharsRead As Long, lpReserved As Any) As Long Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" _ (ByVal hConsoleOutput As Long, ByVal lpBuffer As Any, ByVal nNumberOfCharsToWrite _ As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long Private Declare Function SetConsoleMode Lib "kernel32" (ByVal hConsoleOutput As Long, _ dwMode As Long) As Long Private Declare Function SetConsoleTitle Lib "kernel32" Alias "SetConsoleTitleA" _ (ByVal lpConsoleTitle As String) As Long Private Declare Function SetConsoleTextAttribute Lib "kernel32" _ (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long ''定義API函數中用到的所有常量 ''GetStdHandle函數的 nStdHandle參數的取值 Private Const STD_INPUT_HANDLE = -10& Private Const STD_OUTPUT_HANDLE = -11& Private Const STD_ERROR_HANDLE = -12& ''SetConsoleTextAttribute函數的wAttributes參數的取值(按RGB方式組合) Private Const FOREGROUND_bLUE = &H1 Private Const FOREGROUND_GREEN = &H2 Private Const FOREGROUND_RED = &H4 Private Const FOREGROUND_INTENSITY = &H8 Private Const BACKGROUND_BLUE = &H10 Private Const BACKGROUND_GREEN = &H20 Private Const BACKGROUND_RED = &H40 Private Const BACKGROUND_INTENSITY = &H80 ''SetConsoleMode的輸入模式 Private Const ENABLE_LINE_INPUT = &H2 Private Const ENABLE_ECHO_INPUT = &H4 Private Const ENABLE_MOUSE_INPUT = &H10 Private Const ENABLE_PROCESSED_INPUT = &H1 Private Const ENABLE_WINDOW_INPUT = &H8 ''SetConsoleMode的輸出模式 Private Const ENABLE_PROCESSED_OUTPUT = &H1 Private Const ENABLE_WRAP_AT_EOL_OUTPUT = &H2 Private hConsoleIn As Long ''控制臺窗口的 input handle Private hConsoleOut As Long ''控制臺窗口的output handle Private hConsoleErr As Long ''控制臺窗口的error handle ''主程序 Private Sub Main() Dim szUserInput As String AllocConsole ''創建 console window SetConsoleTitle "VB控制臺應用程序" ''設置console window的標題 ''取得console window的三個句柄 hConsoleIn = GetStdHandle(STD_INPUT_HANDLE) hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE) hConsoleErr = GetStdHandle(STD_ERROR_HANDLE) SetConsoleTextAttribute hConsoleOut, FOREGROUND_GREEN Or FOREGROUND_INTENSITY ''前景:亮綠;背景:黑 ConsolePrint "What''s your name?" szUserInput = ConsoleRead() If Not szUserInput = vbNullString Then ConsolePrint "Hello, " & szUserInput & "!" & vbCrLf Else ConsolePrint "You don''t have a name?" & vbCrLf End If ConsolePrint vbCrLf & "Press enter to exit!" Call ConsoleRead FreeConsole ''銷毀 console window End Sub ''程序中用到的子函數 Private Sub ConsolePrint(szOut As String) WriteConsole hConsoleOut, szOut, Len(szOut), vbNull, vbNull End Sub Private Function ConsoleRead() As String Dim sUserInput As String * 256 Call ReadConsole(hConsoleIn, sUserInput, Len(sUserInput), vbNull, vbNull) ''截掉字符串結尾的&H00和回車、換行符 ConsoleRead = Left$(sUserInput, InStr(sUserInput, Chr$(0)) - 3) End Function |