摘要:針對DOS程序用戶界面差、不易掌握的缺點,提出了應用模擬鍵盤技術,并結合進程檢測技術進行數據傳遞的方法。該方法不需要對原DOS程序進行任何修改,就能將DOS程序升級成圖形操作界面。同時該方法還能對DOS程序的運行過程狀態進行監測,為Windows下DOS應用程序的改造和利用提供了一種簡便易行的途徑。
關鍵詞:DOS程序;升級;GUI;模擬鍵盤;CPU占用率
0 引言
在DOS時代開發的大量輔助計算類程序,受當時的技術條件所限制,不可能采用圖形化界面。這類程序的輸入和輸出基本都采用字符方式,在程序運行過程中需要用戶進行某種交互操作時,一般都是在DOS程序特有的黑屏幕界面上進行,程序的操作性不好。隨著技術的發展,開發人員已經可以很容易地開發出界面友好、易于學習和掌握的應用程序,用戶也不再愿意接受那些界面呆板的DOS程序。在這種背景下,出現了對DOS程序界面升級的需求。文獻[1-4]介紹了以文件作為DOS程序輸入的傳遞接口,實現界面升級。但這種方法需要修改原DOS程序代碼,重定向DOS程序從文件中讀取輸入信息,而不是等待用戶從鍵盤輸入,工作量比較大;如果沒有源代碼,將無法進行升級工作。
本文提出一種新的方法:基于模擬鍵盤技術和CPU占用率檢測的集成升級方法。這種方法的特點是不需要對原DOS程序進行任何修改,對不能在DOS控制臺窗口中運行的DOS也適用,解決了文獻[2]中所介紹方法的缺陷。
1 處理流程
對運行過程中不需要用戶輸入數據,以及可以將所需要的輸入數據作為命令行參數進行調用的DOS程序,升級為Windows的圖形化用戶界面都是很簡單的事情,這里不進行討論。本文重點論述的是在運行過程中需要用戶交互操作的DOS程序的升級,例如輸入所需的數據文件保存路徑,選擇計算過程中是否要考慮的一些因素等等。這種交互操作可能是一步,也可能是多步。圖1給出了一個典型的DOS程序運行界面示例。該程序是用于船體結構計算的一個子程序。從圖1看出,這類程序界面的提示信息很不友好,而且不能利用鼠標操作,操作性不好。

圖1 一個典型的DOS程序運行界面
本文所采用的方法,其處理流程如圖2所示。
首先,應用可視化編程語言編寫用戶交互操作界面程序。該程序建立起用戶、Windows系統和DOS程序的聯系。在這個程序上設置啟動或調用DOS程序的按鈕或菜單;還可以利用文本框、組合框或對話框接受用戶輸入,利用單選或復選按鈕實現DOS命令行參數的輸入等。
其次,啟動基于圖形界面的集成程序界面,并調用DOS程序。
第三,DOS程序運行后,監測該DOS程序的CPU占用率,對其運行狀態進行檢測。若程序正處于等待用戶輸入狀態,此時利用模擬鍵盤API函數,給程序發送所需要的輸入數據消息,直到程序模塊運行結束。當然程序運行所需要的數據,仍然需要用戶來決定,只是這類數據操作是利用圖形界面來操作的。
最后,程序結束運行,返回圖形操作界面,顯示計算結果。

圖2處理流程圖
2 主要技術原理
2.1進程技術
啟動一個可執行程序(.exe,.bat)的方法有多種,但主要是利用Windows平臺的API函數Winexec,或編程語言提供的其他類似函數,例如Visual Fortran提供的PUNQQ函數,VB提供的Shell函數等。這種方法啟動DOS平臺下的可執行程序,運行后出現的界面就是大家熟悉的黑屏幕,如圖1所示。這種方法稱為進程調用技術。因為被啟動的程序和基于GUI方式的主程序是在兩個不同的進程空間,相互不能直接訪問到對方的內存區。在本文的工作中,也利用進程技術來啟動要升級到GUI界面的原DOS平臺程序。本文利用VB.NET平臺,使用該平臺所提供的Process類來啟動相應的DOS程序。圖3是啟動一個DOS程序的界面示例。在『啟動計算』按鈕中設置如下代碼:
Dim p As New Process
p.Start(\"D:W.C2006.exe\")'要啟動的DOS程序是ZC2006.exe

圖3調用DOS程序的示例界面
2.2鍵盤模擬方法
本文采用鍵盤模擬的方式來實現主程序和被調用程序(DOS程序)間的數據傳遞。其原理如下:
Windows API函數keybd_event函數能夠模擬一次鍵盤按擊事件,其函數接口聲明如下:
Declare Sub keybd_event Lib\"user32\"Alias\"keybd_event\"
(ByVal bVk As Byte,ByVal bScan As Byte,ByVal dwFlags
As Long,ByVal dwExtralnfo As Long)
其中參數bVk就是要模擬的虛擬鍵碼,其他參數賦值為0。這里虛擬鍵碼與字符的ASCII碼是不對應的,比如字母“a”的ASCII碼是十進制的97,但這個字符的虛擬鍵碼是十進制的65。所以要進行必要的轉換。該轉換可以利用API函數VkKeyScan來實現。接口聲明如下:
Public Declare Function VkKeyScan Lib\"user32\"Alias
\"VkKeyScanA\"(ByVal cChar As Byte)As Integer
參數cChar代表需要取得虛擬鍵碼的字符的ASCII值。所以,對圖3所示界面的文本框中輸入的文件名,采用消息的方式發送到DOS程序窗口中去的主要代碼如下:
If Me.TxtB_filename.Text<>String.Empty Then
Dim i As Integer
For i=0 TO Me.TxtB_filename.Text.Length-1
keybd_event(VkKeyScan(Asc(Me.TxtB_filename.Text.
Substring(i,1))),0,0,0)
Next i
keybd_event(VK_RETURN,0,0,0)’發送一個回車按鍵
End If
對于運行時需要用戶多步交互操作的DOS程序,可在Windows圖形界面程序中,將用戶通過界面選擇、輸入的數據存入一個字符串類型數組M。然后利用定時器的定時消息來檢測DOS程序運行狀態,處于空閑態時,將字符串數組中當前要發送元素的內容用API函數發送給DOS程序,并記錄下一次要發送的消息在數組M中的位置。
2.3進程狀態檢測技術
被啟動的DOS程序,有些在運行過程中需要用戶進行多步交互操作。在這種情況下,就存在什么時間給DOS程序發送所需的輸入信息的問題。將該DOS程序正常運行所需要的多步輸入信息一次全部發送是沒有任何意義的。解決這個發送時間的問題有兩種處理方法。
方法一:因為以前開發的DOS程序在當前電腦硬件配置條件下,運行時間一般都很短,所以可以設定一個固定的時間間隔來發送,這個時間間隔可以比實際需要的時間大很多,以保證DOS程序已經運行到等待輸入的狀態。
方法二:利用Windows平臺的進程監測技術。如果一個程序正在運行,其對CPU的占用率肯定是大于0的,而處于等待輸入的狀態時,其對CPU的占用率就等于0。所以可以監測特定程序對CPU的占用率來判斷DOS程序的狀態。
兩種方法比較,方法一的實現很簡單,但如果特定程序在某兩步輸入操作間的運行時間很長,則這種方法不能保證一定合適,而且效率要低一些。所以本文采用第二種方法。 本文利用.NET平臺所提供的Process對象,能夠檢測出某個時間點上,一個進程對CPU的占用率。圖4是本文開發的進程檢測程序的界面。只有當程序處于等待用戶輸入的狀態時,才能發送所需要的數據給DOS程序。如果提前發送會導致數據的丟失,導致運行錯誤;而延遲發送又影響程序運行效率,最優化的方法是實時監控DOS程序的運行狀態。

圖4 進程信息示例程序界面
3 結束語
用可視化編程語言來制作用戶交互界面是很容易的,因此利用可視化編程語言來制作DOS程序的數據輸入界面和結果輸出界面,將DOS程序升級成具有良好操作性的圖形化界面,具有很強的應用價值。本文描述的DOS程序升級方法,不需對原DOS程序進行任何修改,花費最小的代價,將程序升級到GUI圖形界面,而且對沒有程序源代碼的DOS程序也完全適用。應用這一技術方案,對原DOS時代開發的船體計算程序進行了升級,證明了該方法簡單可行,完全可應用于其他同類型DOS程序的升級,為Windows下DOS應用程序的改造和利用提供了一種簡便易行的方法。
注:本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。