馮偉偉,王遠斌,嵇亮亮
(中國電子科技集團公司第二十八研究所,江蘇南京 210007)
在網絡日益發達的今天,無論是百度、搜狐等國內知名的搜索引擎,還是大家經常使用的IE、360 瀏覽器,它們無時無刻不在使用輸入聯想功能。輸入聯想功能加快了人們的輸入速度,同時越來越成為人們登錄互聯網不可或缺的一項基本功能,它為人們提供了很大的方便。在工程應用中,經常會通過人機交互界面輸入較復雜的控制命令,這時輸入聯想功能顯得尤為重要。對于已經輸入過的比較復雜的控制命令,用戶只需要輸入命令開頭的幾個控制字符,就可以在產生的下拉列表框中選擇所需指令,而不需要逐個字符的手動輸入,這樣就為用戶提供了極大的方便。
ComboBox 控件可以實現自動選擇的功能[1],當用戶在組合框中按下一個鍵時,以該字母開頭的第一個條目被自動高亮顯示。每當一個鍵被按下,該字符串就被檢查一遍,并檢查列表框中是否存在與該項相匹配的條目,如果存在,則高亮顯示。本文在此文獻的基礎上,采用自定義控件實現了ComboBox 控件的輸入聯想功能。
從用戶角度看,ComboBox 控件由一個允許用戶鍵入的文本框和下拉列表框組成[2,3]。用戶可以從預先定義的列表框里選擇一個選項,也可以直接在文本框里輸入文本信息。當下拉菜單的選項較多時,下拉菜單的右側會產生一個滾動條來實現手動滾動查詢。
自定義組合框控件為了實現ComboBox 控件的相應功能一般需要包含以下4 個類:CEdit 類、窗口類、下拉列表類、滾動條類[4,5]。自定義組合框的創建及其實現輸入聯想的過程與上述4 個類創建順序的關系如圖1 所示。

圖1 自定義組合框與相應類創建順序關系框
手動輸入也是組合框的一項基本功能,而CEdit 類可以使自定義組合框控件具有手動鍵盤輸入的功能,由圖1知,CEdit 類在自定義控件產生時已經產生,因此這時的控件已經具有了鍵盤輸入功能,而與控件的下拉菜單是否產生無關。
窗口類是自定義組合框控件實現下拉菜單必不可少的部分,當用戶點擊控件的下拉按鈕或進行聯想輸入功能時程序創建一個窗口類,此窗口可以承載所產生的下拉列表框和滾動條。
下拉列表框類是隨著窗口類的產生而產生,當下拉窗口產生后會創建下拉列表框類,當銷毀下拉窗口時,需要先銷毀下拉列表框類。
滾動條類也是隨著窗口類的產生而產生,當下拉窗口產生后會創建滾動條類,當銷毀下拉窗口時,需要先銷毀滾動條類。
本文基于對話框實現自定義組合框控件,首先添加一個自定義控件到對話框,設置控件的基類為CAdvComboBox。CAdvComboBox 是新建的類,它繼承于類CWnd。此外,還需要添加繼承于類CWnd 的窗口類CDropWnd,繼承于類CListBox的列表框類CDropListBox 和繼承于類CSrollBar 的滑動條類CDropScrollBar。
類CAdvComboBox 包含類CComboBox 的基本功能,因此,它需要重載CComboBox 的一些完成基本功能的函數,如SetCurSel()、GetCurSel()、GetCount()等。
當程序創建自定義控件時,首先進行一些初始化操作,包括創建CEdit 類以支持控件鍵盤輸入功能等,因此,需要重載PreSubclassWindow()函數來完成這些任務。
自定義組合控件的內部使用List 實現[6],其內部處理流程如圖2 所示。
當用戶手動輸入字符串時,程序內部需要判斷哪些歷史記錄需要在下拉框中顯示,因此,需要重載輸入響應函數OnUpdateEdit()進行判斷,函數中判斷列表框的命令記錄中那些與當前輸入的字符串相匹配的條目,其主要代碼如下:

圖2 輸入聯想內部實現流程

類成員變量m_List 中存儲加入控件的指令歷史記錄,臨時變量suggestList 用來存儲命令記錄中與當前輸入的字符相匹配的條目。當用戶輸入可見字符串str,程序會遍歷列表m_List 的每一個元素,查找元素開頭字符串與字符串str 一致的條目并把該條目加入到suggestList 列表中。遍歷m_List 結束后,判斷suggestList 是否為空,如果為空則返回,如果不為空,則創建下拉菜單并顯示列表suggestList 的所有元素項。
當第一次使用此輸入控件時,或者輸入的指令不在列表中,或者用戶只知道某條指令開始的幾個字符,這時就需要手動輸入指令,手動鍵盤輸入時聯想功能流程如圖3 所示。
由圖3 可知,當用戶使用鍵盤向控件中輸入指令時,如果列表框的命令記錄中不存在與當前輸入的字符串相匹配的條目,此時不會創建下拉菜單窗口,指令輸入完畢按下回車鍵,程序會把當前輸入框中的指令加入到命令記錄中,同時把指令發送到接收端,接收端接收到指令進行相應的操作。
如果列表框的命令記錄中存在與當前輸入的字符相匹配的條目,則程序會執行函數CreateDropList(suggestList)創建一個窗口類,其中的參數suggestList 為列表框的命令記錄中與當前輸入的字符串相匹配條目的列表,函數代碼如下:

圖3 鍵盤輸入時聯想功能流程

在上述代碼中,當程序執行完函數m_pDropWnd->Create()后會自動執行窗口類重載的函數CDropWnd::OnCreate(),在此函數中創建滾動條類和列表框類,主要代碼如下:

滾動條類和列表框類創建成功后就會出現選擇下拉菜單,則下拉菜單會列出所有與輸入字符串相匹配的命令記錄,這時用戶可以通過上、下鍵選擇輸入命令,最后把指令發送出去,但是,如果下拉菜單列出的所有與輸入字符串相匹配的命令記錄中不存在用戶想要輸入的命令,那么用戶還需要繼續手動輸入指令,最后把指令加入到命令記錄并發送出去。
除了通過上述的方式輸入指令外,用戶還可以通過點擊自定義控件右側下拉按鈕的方式實現指令輸入,此時系統工作流程如圖4 所示。

圖4 點擊下拉按鈕的流程
由圖4 可知,當用戶點擊自定義控件右側的下拉按鈕時,程序會創建一個窗口類,因此需要重載類CAdvComboBox 的鼠標左鍵的響應函數OnLButtonDown()。接著,調用函數CreateDropList(m_list)創建一個滾動條類和一個列表框類,其中參數m_list 加入自定義控件的指令歷史記錄。當滾動條類和列表框類創建成功后會顯示新創建的選擇下拉菜單,如果控件中存在輸入指令記錄,則下拉菜單會列出所有命令記錄,這時用戶可以通過上、下鍵選擇輸入命令。當用戶按下回車鍵時,被選擇的指令就會加入當前的輸入框,同時下拉菜單銷毀。當用戶再次按下回車鍵時,就可以把當前輸入框中的指令發送出去。
在人機交互的應用中,利用上述思想我們實現了自定義組合框控件的聯想功能。當用戶輸入命令時,用戶只需要輸入命令開頭的幾個字符就可以在列表框中選擇需要輸入的命令,這樣就為用戶提供了很大的方便。人機交互模塊的輸入聯想功能應用如圖5 所示。

圖5 人機交互應用
本文介紹了一種全新的設計思想實現組合控件的輸入聯想功能,雖然程序的設計和編碼相對比較繁瑣,但其實現了比較高級的輸入聯想功能,滿足了用戶的需求,獲得了較好的使用效果。
[1]孫皓.Visual C++范例大全[M].北京:機械工業出版社,2009.
[2]David j et al.Visual C++6.0 技術內幕[M].希望圖書室,譯.5版.北京:北京希望電子出版社,1999.
[3]侯俊杰.深入淺出MFC[M].2 版.武漢:華中科技大學出版社,2001.
[4]Bjarne Stroustrup.C++程序設計語言[M].裘宗燕,譯.北京:機械工藝出版社,2002.
[5]錢能.C++程序設計教程[M].北京:清華大學出版社,1994.
[6]范磊.零起點學通C++:多媒體范例教學[M].北京:科學出版社,2010.
[7]孫鑫.VC++深入詳解(修訂版)[M].北京:電子工業出版社,2012.
[8]Lippman Lajoie.C++Primer 中文版[M].潘愛民,張麗,譯.3版.北京:中國電力出版社,2002.
[9]Christopher Tavares,Kirk Fertitta,Brent Rector.深入解析ATL[M].賴儀靈,曹雨田,譯.2 版.北京:電子工業出版社,2007.
[10]Dale Rogerson.COM 技術內幕[M].楊秀章,譯.北京:清華大學出版社,1998.