馮偉偉,王遠(yuǎn)斌,嵇亮亮
(中國(guó)電子科技集團(tuán)公司第二十八研究所,江蘇南京 210007)
在網(wǎng)絡(luò)日益發(fā)達(dá)的今天,無(wú)論是百度、搜狐等國(guó)內(nèi)知名的搜索引擎,還是大家經(jīng)常使用的IE、360 瀏覽器,它們無(wú)時(shí)無(wú)刻不在使用輸入聯(lián)想功能。輸入聯(lián)想功能加快了人們的輸入速度,同時(shí)越來(lái)越成為人們登錄互聯(lián)網(wǎng)不可或缺的一項(xiàng)基本功能,它為人們提供了很大的方便。在工程應(yīng)用中,經(jīng)常會(huì)通過(guò)人機(jī)交互界面輸入較復(fù)雜的控制命令,這時(shí)輸入聯(lián)想功能顯得尤為重要。對(duì)于已經(jīng)輸入過(guò)的比較復(fù)雜的控制命令,用戶(hù)只需要輸入命令開(kāi)頭的幾個(gè)控制字符,就可以在產(chǎn)生的下拉列表框中選擇所需指令,而不需要逐個(gè)字符的手動(dòng)輸入,這樣就為用戶(hù)提供了極大的方便。
ComboBox 控件可以實(shí)現(xiàn)自動(dòng)選擇的功能[1],當(dāng)用戶(hù)在組合框中按下一個(gè)鍵時(shí),以該字母開(kāi)頭的第一個(gè)條目被自動(dòng)高亮顯示。每當(dāng)一個(gè)鍵被按下,該字符串就被檢查一遍,并檢查列表框中是否存在與該項(xiàng)相匹配的條目,如果存在,則高亮顯示。本文在此文獻(xiàn)的基礎(chǔ)上,采用自定義控件實(shí)現(xiàn)了ComboBox 控件的輸入聯(lián)想功能。
從用戶(hù)角度看,ComboBox 控件由一個(gè)允許用戶(hù)鍵入的文本框和下拉列表框組成[2,3]。用戶(hù)可以從預(yù)先定義的列表框里選擇一個(gè)選項(xiàng),也可以直接在文本框里輸入文本信息。當(dāng)下拉菜單的選項(xiàng)較多時(shí),下拉菜單的右側(cè)會(huì)產(chǎn)生一個(gè)滾動(dòng)條來(lái)實(shí)現(xiàn)手動(dòng)滾動(dòng)查詢(xún)。
自定義組合框控件為了實(shí)現(xiàn)ComboBox 控件的相應(yīng)功能一般需要包含以下4 個(gè)類(lèi):CEdit 類(lèi)、窗口類(lèi)、下拉列表類(lèi)、滾動(dòng)條類(lèi)[4,5]。自定義組合框的創(chuàng)建及其實(shí)現(xiàn)輸入聯(lián)想的過(guò)程與上述4 個(gè)類(lèi)創(chuàng)建順序的關(guān)系如圖1 所示。
圖1 自定義組合框與相應(yīng)類(lèi)創(chuàng)建順序關(guān)系框
手動(dòng)輸入也是組合框的一項(xiàng)基本功能,而CEdit 類(lèi)可以使自定義組合框控件具有手動(dòng)鍵盤(pán)輸入的功能,由圖1知,CEdit 類(lèi)在自定義控件產(chǎn)生時(shí)已經(jīng)產(chǎn)生,因此這時(shí)的控件已經(jīng)具有了鍵盤(pán)輸入功能,而與控件的下拉菜單是否產(chǎn)生無(wú)關(guān)。
窗口類(lèi)是自定義組合框控件實(shí)現(xiàn)下拉菜單必不可少的部分,當(dāng)用戶(hù)點(diǎn)擊控件的下拉按鈕或進(jìn)行聯(lián)想輸入功能時(shí)程序創(chuàng)建一個(gè)窗口類(lèi),此窗口可以承載所產(chǎn)生的下拉列表框和滾動(dòng)條。
下拉列表框類(lèi)是隨著窗口類(lèi)的產(chǎn)生而產(chǎn)生,當(dāng)下拉窗口產(chǎn)生后會(huì)創(chuàng)建下拉列表框類(lèi),當(dāng)銷(xiāo)毀下拉窗口時(shí),需要先銷(xiāo)毀下拉列表框類(lèi)。
滾動(dòng)條類(lèi)也是隨著窗口類(lèi)的產(chǎn)生而產(chǎn)生,當(dāng)下拉窗口產(chǎn)生后會(huì)創(chuàng)建滾動(dòng)條類(lèi),當(dāng)銷(xiāo)毀下拉窗口時(shí),需要先銷(xiāo)毀滾動(dòng)條類(lèi)。
本文基于對(duì)話(huà)框?qū)崿F(xiàn)自定義組合框控件,首先添加一個(gè)自定義控件到對(duì)話(huà)框,設(shè)置控件的基類(lèi)為CAdvComboBox。CAdvComboBox 是新建的類(lèi),它繼承于類(lèi)CWnd。此外,還需要添加繼承于類(lèi)CWnd 的窗口類(lèi)CDropWnd,繼承于類(lèi)CListBox的列表框類(lèi)CDropListBox 和繼承于類(lèi)CSrollBar 的滑動(dòng)條類(lèi)CDropScrollBar。
類(lèi)CAdvComboBox 包含類(lèi)CComboBox 的基本功能,因此,它需要重載CComboBox 的一些完成基本功能的函數(shù),如SetCurSel()、GetCurSel()、GetCount()等。
當(dāng)程序創(chuàng)建自定義控件時(shí),首先進(jìn)行一些初始化操作,包括創(chuàng)建CEdit 類(lèi)以支持控件鍵盤(pán)輸入功能等,因此,需要重載PreSubclassWindow()函數(shù)來(lái)完成這些任務(wù)。
自定義組合控件的內(nèi)部使用List 實(shí)現(xiàn)[6],其內(nèi)部處理流程如圖2 所示。
當(dāng)用戶(hù)手動(dòng)輸入字符串時(shí),程序內(nèi)部需要判斷哪些歷史記錄需要在下拉框中顯示,因此,需要重載輸入響應(yīng)函數(shù)OnUpdateEdit()進(jìn)行判斷,函數(shù)中判斷列表框的命令記錄中那些與當(dāng)前輸入的字符串相匹配的條目,其主要代碼如下:
圖2 輸入聯(lián)想內(nèi)部實(shí)現(xiàn)流程
類(lèi)成員變量m_List 中存儲(chǔ)加入控件的指令歷史記錄,臨時(shí)變量suggestList 用來(lái)存儲(chǔ)命令記錄中與當(dāng)前輸入的字符相匹配的條目。當(dāng)用戶(hù)輸入可見(jiàn)字符串str,程序會(huì)遍歷列表m_List 的每一個(gè)元素,查找元素開(kāi)頭字符串與字符串str 一致的條目并把該條目加入到suggestList 列表中。遍歷m_List 結(jié)束后,判斷suggestList 是否為空,如果為空則返回,如果不為空,則創(chuàng)建下拉菜單并顯示列表suggestList 的所有元素項(xiàng)。
當(dāng)?shù)谝淮问褂么溯斎肟丶r(shí),或者輸入的指令不在列表中,或者用戶(hù)只知道某條指令開(kāi)始的幾個(gè)字符,這時(shí)就需要手動(dòng)輸入指令,手動(dòng)鍵盤(pán)輸入時(shí)聯(lián)想功能流程如圖3 所示。
由圖3 可知,當(dāng)用戶(hù)使用鍵盤(pán)向控件中輸入指令時(shí),如果列表框的命令記錄中不存在與當(dāng)前輸入的字符串相匹配的條目,此時(shí)不會(huì)創(chuàng)建下拉菜單窗口,指令輸入完畢按下回車(chē)鍵,程序會(huì)把當(dāng)前輸入框中的指令加入到命令記錄中,同時(shí)把指令發(fā)送到接收端,接收端接收到指令進(jìn)行相應(yīng)的操作。
如果列表框的命令記錄中存在與當(dāng)前輸入的字符相匹配的條目,則程序會(huì)執(zhí)行函數(shù)CreateDropList(suggestList)創(chuàng)建一個(gè)窗口類(lèi),其中的參數(shù)suggestList 為列表框的命令記錄中與當(dāng)前輸入的字符串相匹配條目的列表,函數(shù)代碼如下:
圖3 鍵盤(pán)輸入時(shí)聯(lián)想功能流程
在上述代碼中,當(dāng)程序執(zhí)行完函數(shù)m_pDropWnd->Create()后會(huì)自動(dòng)執(zhí)行窗口類(lèi)重載的函數(shù)CDropWnd::OnCreate(),在此函數(shù)中創(chuàng)建滾動(dòng)條類(lèi)和列表框類(lèi),主要代碼如下:
滾動(dòng)條類(lèi)和列表框類(lèi)創(chuàng)建成功后就會(huì)出現(xiàn)選擇下拉菜單,則下拉菜單會(huì)列出所有與輸入字符串相匹配的命令記錄,這時(shí)用戶(hù)可以通過(guò)上、下鍵選擇輸入命令,最后把指令發(fā)送出去,但是,如果下拉菜單列出的所有與輸入字符串相匹配的命令記錄中不存在用戶(hù)想要輸入的命令,那么用戶(hù)還需要繼續(xù)手動(dòng)輸入指令,最后把指令加入到命令記錄并發(fā)送出去。
除了通過(guò)上述的方式輸入指令外,用戶(hù)還可以通過(guò)點(diǎn)擊自定義控件右側(cè)下拉按鈕的方式實(shí)現(xiàn)指令輸入,此時(shí)系統(tǒng)工作流程如圖4 所示。
圖4 點(diǎn)擊下拉按鈕的流程
由圖4 可知,當(dāng)用戶(hù)點(diǎn)擊自定義控件右側(cè)的下拉按鈕時(shí),程序會(huì)創(chuàng)建一個(gè)窗口類(lèi),因此需要重載類(lèi)CAdvComboBox 的鼠標(biāo)左鍵的響應(yīng)函數(shù)OnLButtonDown()。接著,調(diào)用函數(shù)CreateDropList(m_list)創(chuàng)建一個(gè)滾動(dòng)條類(lèi)和一個(gè)列表框類(lèi),其中參數(shù)m_list 加入自定義控件的指令歷史記錄。當(dāng)滾動(dòng)條類(lèi)和列表框類(lèi)創(chuàng)建成功后會(huì)顯示新創(chuàng)建的選擇下拉菜單,如果控件中存在輸入指令記錄,則下拉菜單會(huì)列出所有命令記錄,這時(shí)用戶(hù)可以通過(guò)上、下鍵選擇輸入命令。當(dāng)用戶(hù)按下回車(chē)鍵時(shí),被選擇的指令就會(huì)加入當(dāng)前的輸入框,同時(shí)下拉菜單銷(xiāo)毀。當(dāng)用戶(hù)再次按下回車(chē)鍵時(shí),就可以把當(dāng)前輸入框中的指令發(fā)送出去。
在人機(jī)交互的應(yīng)用中,利用上述思想我們實(shí)現(xiàn)了自定義組合框控件的聯(lián)想功能。當(dāng)用戶(hù)輸入命令時(shí),用戶(hù)只需要輸入命令開(kāi)頭的幾個(gè)字符就可以在列表框中選擇需要輸入的命令,這樣就為用戶(hù)提供了很大的方便。人機(jī)交互模塊的輸入聯(lián)想功能應(yīng)用如圖5 所示。
圖5 人機(jī)交互應(yīng)用
本文介紹了一種全新的設(shè)計(jì)思想實(shí)現(xiàn)組合控件的輸入聯(lián)想功能,雖然程序的設(shè)計(jì)和編碼相對(duì)比較繁瑣,但其實(shí)現(xiàn)了比較高級(jí)的輸入聯(lián)想功能,滿(mǎn)足了用戶(hù)的需求,獲得了較好的使用效果。
[1]孫皓.Visual C++范例大全[M].北京:機(jī)械工業(yè)出版社,2009.
[2]David j et al.Visual C++6.0 技術(shù)內(nèi)幕[M].希望圖書(shū)室,譯.5版.北京:北京希望電子出版社,1999.
[3]侯俊杰.深入淺出MFC[M].2 版.武漢:華中科技大學(xué)出版社,2001.
[4]Bjarne Stroustrup.C++程序設(shè)計(jì)語(yǔ)言[M].裘宗燕,譯.北京:機(jī)械工藝出版社,2002.
[5]錢(qián)能.C++程序設(shè)計(jì)教程[M].北京:清華大學(xué)出版社,1994.
[6]范磊.零起點(diǎn)學(xué)通C++:多媒體范例教學(xué)[M].北京:科學(xué)出版社,2010.
[7]孫鑫.VC++深入詳解(修訂版)[M].北京:電子工業(yè)出版社,2012.
[8]Lippman Lajoie.C++Primer 中文版[M].潘愛(ài)民,張麗,譯.3版.北京:中國(guó)電力出版社,2002.
[9]Christopher Tavares,Kirk Fertitta,Brent Rector.深入解析ATL[M].賴(lài)儀靈,曹雨田,譯.2 版.北京:電子工業(yè)出版社,2007.
[10]Dale Rogerson.COM 技術(shù)內(nèi)幕[M].楊秀章,譯.北京:清華大學(xué)出版社,1998.