1、引言
在一般的以CEditView爲基類的單文檔/多文檔視圖程序中,能夠很好的響應鍵盤輸入的回車鍵,只需比較最近兩次的輸入的字符,看看最新輸入的字符是否內碼是13(0x0d,回車鍵的內碼)便可識別出來,而要單獨把一個編輯框放入對話框中卻根本不響應,這個看似簡單的問題在實際應用中仍是解決起來比較困難的。尤爲是當一個充當表單錄入的對話框上有若干個編輯框,這就要求在一個編輯框添完一項表單後用習慣的回車鍵將該編輯框上的數據讀取到內存中去,並自動將光標移動到下一個編輯框中準備填寫下一欄表單。無疑這種界面是十分人機友好的,使錄入人員沒必要去執行每填一下表單就去按一下執行讀入到緩存功能的按鈕的煩瑣操做。但上述功能的實現卻並不象其演示的功能那樣簡單,下面本文就對這項技術的實現及附帶的其餘技術做簡要的介紹。
2、不能響應回車鍵的緣由分析
之因此在以CEditView做爲基類的程序中能夠響應回車鍵,是因爲該程序的視類自己就是一個Edit控件,這就是問題的關鍵所在。CEditView做爲CView的派生類能響應從鍵盤輸入的各類消息,其中有和鍵盤輸入相關的WM_CHAR、WM_KEYDOWN、WM_KEYUP等消息。咱們就能夠在這些消息的響應函數中靈活地設計程序去捕捉到回車鍵的輸入,並執行響應的操做。
當咱們將編輯框做爲一個普通的控件放到對話框上時狀況就發生了變化。在此咱們以CFormView爲例,它也是CView的一個派生類,視是一個Form窗體(即對話框),當放有編輯框的窗體有回車鍵輸入時,因爲只有編輯框能夠接受從鍵盤輸入的字符,因此當鍵盤按下時通通把消息都發給了編輯框(在Windows下每一個窗口、按鈕、編輯框都看做一個窗口,均可以接受消息),能夠經過ClassWizard在"Object IDs"選中編輯框所對應的ID號,在右邊的消息框中能夠看出該編輯框並不能響應WM_CHAR等消息,只能用EN_CHANGE事件來作相似的響應。可當咱們加入了對該事件的處理函數時,卻又將回車鍵看成控制字符,當輸入回車鍵並不會激發EN_CHANGE事件,也就是說用這種方法仍舊沒法捕獲回車鍵的輸入。
3、攔截回車鍵的思路與方法
Windows操做系統下各個窗口、控件歸根結底都是經過系統的各類各樣的消息來相互協調、相互聯繫的,而咱們所遇到的這個問題換到消息的角度說就是"如何使程序能響應在編輯框上輸入的回車鍵所發出的消息",只要能響應到這個消息,剩下的工做均可以在消息處理函數中完成。因此有必要對Windows系統的消息機制作些瞭解。
每一個Windows應用程序開始執行後,Windows都爲該程序建立一個"消息隊列(message queue)",用來存放郵寄給該程序可能建立的各類不一樣窗口的消息。消息隊列中消息的結構(MSG)爲:緩存
typedef struct tagMSG{ |
在系統下最經常使用的消息循環是調用GetMessage()函數從消息隊列中取出消息,而後調用DespatchMessage() 函數讓系統把消息發送給窗口函數,通常狀況下其結果是把窗口的全部消息都傳送給窗口函數。但特殊狀況下能夠在GetMessage()函數得到消息而又沒發送出去以前,經過TranslateMessage()函數能夠中途對消息進行解析,能夠對指定的消息進行攔截,攔截後便可以照樣發送出去,也能夠不繼續發送,完成對該消息的攔截,下面代碼是該過程的示例:spa
MSG msg; |
因爲按下回車鍵時把產生的消息加入到消息隊列中了,也傳給了編輯框,但僅僅是因爲編輯框沒有能力處理該消息而形成了沒法對回車鍵的響應,因此能夠在消息循環裏在把消息發送到編輯框以前就對消息進行攔截,並對其進行處理。其效果同編輯框響應回車鍵是同樣的,僅在時序上有所提早而已。上述代碼是在SDK(Software Develope Kits)下使用的,在MFC(Microsoft Foundation Class)下早已對其進行了封裝,能夠經過重載虛函數PreTranslateMessage()對所關心的消息進行解析:設計
BOOL CTestView::PreTranslateMessage(MSG* pMsg) |
在上面的代碼中,首先將pMsg->message所表示的消息同WM_KEYFIRST 和WM_KEYLAST比較,肯定是鍵盤消息,而後經過消息參數pMsg->wParam的值來判斷是不是回車鍵(VK_RETURN,虛擬鍵碼能夠從SDK相關資料查到)。如是,則能夠將已輸入到編輯框中的字符讀取到m_Text中,並將其顯示出來。對象
4、對編輯框的識別
前面已經能夠對回車鍵響應了,可一個表單窗體有若干個編輯框,其各自的處理方式不盡相同,這就有必要對編輯框進行識別、對不一樣的編輯框作不一樣的處理。並且當按下回車鍵時必須保證只有當前有焦點的編輯框能完成對回車鍵的響應動做,不然也就失去了實際意義。
在Windows下的程序中,全部的資源都是有惟一標號的,使每一個資源對象能惟一的區別於其餘資源,因此咱們能夠經過資源ID來對編輯框作出區別,使之完成各自的響應處理。在Microsoft Visual C++ 6.0下能夠經過"View"菜單的"ID= Resource Symboles…"查到指定ID的資源標識號的實際數值,如在本例中的兩個編輯框IDC_EDIT1和IDC_EDIT2所對應的數值分別爲1000和1001,對前面的解析消息的代碼作些改動,主要以下所示:隊列
…… |
在此經過API函數::GetFocus()(注意前面的"::",標識是全局API函數,而非某個類中的成員函數)取得當前光標所處的(即有焦點的)編輯框的句柄,而後經過API函數::GetDlgCtrlID()根據這個句柄返回此窗口資源的ID 號,該ID號是動態獲取的,使之同預先查看好的編輯框的ID做下比較便可區分出是須要哪一個編輯框對回車鍵做出響應。
小結:
本文經過對消息的解析實現了對特定編輯框的回車鍵的響應,在對消息機制有了基本的瞭解以後,能夠用與本文相似的方法,對代碼稍做改動,就可使其餘一些不能響應特殊消息的控件能接收、處理特定的消息。內存