二樓狼Robot兄弟已經(jīng)提供了更優(yōu)秀的解決辦法,此文只為立此存照,記錄樓豬分析思路,請(qǐng)尋找答案的童鞋直接大跨步跳過~~
在Excel的VBA編程中,設(shè)計(jì)一個(gè)用于錄入的用戶窗體,該窗體包含1個(gè)文本框和2個(gè)按鈕,文本框用于掃描槍的錄入。 要求掃描槍可以連續(xù)錄入,即每掃描完一個(gè)條碼,文本框自動(dòng)清空,文本框繼續(xù)獲得焦點(diǎn)。
我們知道掃描槍錄入實(shí)際上等同于往文本框錄入一段字符串并回車, 那么剛才的要求理論上可以在文本框的KeyDown事件子過程中編程,先判斷錄入的字符是否回車鍵,如果是則清空文本框。 1 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 2 If KeyCode = 13 Then TextBox1.Value = '' 3 End Sub 至此,如果是VB編程,要求本應(yīng)完成。但實(shí)際運(yùn)行發(fā)現(xiàn),掃描槍錄入后,文本框雖然自動(dòng)清空,但是焦點(diǎn)卻跑到下一個(gè)按鈕上去了。
未及細(xì)想,手動(dòng)用SetFocuse方法來設(shè)置文本框獲得焦點(diǎn)。 1 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 2 If KeyCode = 13 Then 3 TextBox1.Value = '' 4 TextBox1.SetFocus 5 End If 6 End Sub 程序再運(yùn)行,焦點(diǎn)還是跑到按鈕上。不解,遂跟蹤之,發(fā)現(xiàn)是在執(zhí)行完KeyDown事件子過程后(End Sub語句后)發(fā)生的焦點(diǎn)轉(zhuǎn)移,難怪SetFocus方法顯得沒有起作用。 為什么執(zhí)行完KeyDown事件后會(huì)發(fā)生焦點(diǎn)自動(dòng)轉(zhuǎn)移呢?百思不得其解,遂清除代碼反復(fù)測試,終于搞清楚一個(gè)結(jié)論:在Excel VBA編程中,文本框控件接收到回車鍵以后,會(huì)將焦點(diǎn)移到Tab鍵順序的下一個(gè)對(duì)象。(這一結(jié)論通過參閱文本框控件的EnterKeyBehavior屬性說明也可側(cè)面印證) 之所以特別強(qiáng)調(diào)是在Excel VBA編程中,是因?yàn)槲乙老》路鹩浀迷赩B6里面,系統(tǒng)是不會(huì)“聰明的”幫文本框做焦點(diǎn)轉(zhuǎn)移的。(多年不用VB6了,回憶的事情未必正確!但是,其它許多面向事件的UI編程里面,系統(tǒng)是不會(huì)自動(dòng)幫忙文本框做焦點(diǎn)轉(zhuǎn)移的。)
既然查明原委,自然應(yīng)找尋解決之道,且看我折騰。從文本框按下回車鍵到Button1按鈕獲得焦點(diǎn),依次產(chǎn)生如下事件: 1 TextBox1_KeyDown( ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As fmShiftState) 2 3 TextBox1_Exit( ByVal Cancel As MSForms.ReturnBoolean) 4 5 Button1_Enter( ) 6 7 Button1_KeyPress( ByVal KeyANSI As MSForms.ReturnInteger) 8 9 Button1_KeyUp( ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As fmShiftState) 我的初步想法既然焦點(diǎn)轉(zhuǎn)移是不可干預(yù)的系統(tǒng)行為,那就“事后”將它逆轉(zhuǎn)回來,如此從Exit事件開始往后都可以用SetFocus方法將焦點(diǎn)重新設(shè)回文本框(此處說法不嚴(yán)謹(jǐn),如果在Exit事件里面實(shí)現(xiàn),不適用SetFocus方法,而是用Cancel=True,個(gè)中原因請(qǐng)自查VBA幫助)。但這樣帶來一個(gè)邏輯問題,從業(yè)務(wù)上判斷,只有在文本框輸入操作時(shí),才需要讓文本框保持焦點(diǎn),其它時(shí)候不需要,否則會(huì)導(dǎo)致除了文本框之外的其它控件都得不到焦點(diǎn),無法操作!因此干預(yù)焦點(diǎn)轉(zhuǎn)移的代碼邏輯只能在KeyDown事件中實(shí)現(xiàn)。 既然不能“事后”逆轉(zhuǎn),那就只能從中打斷了。我又嘗試了在KeyDown事件中用 Exit Sub 或 Call 跳出子過程,未果,系統(tǒng)仍然會(huì)自動(dòng)做焦點(diǎn)轉(zhuǎn)移。 靈光乍現(xiàn)間,我想到既然不能打斷子過程,何不打斷事件。方法是再做一個(gè)UserForm2窗體,當(dāng)在文本框按回車時(shí),隱藏現(xiàn)有窗體,顯示 UserForm2窗體,這時(shí)會(huì)觸發(fā)UserForm2的Activate事件, 同時(shí)窗體顯示的切換也打斷了文本框向按鈕轉(zhuǎn)移焦點(diǎn),那么只要在Activate事件中再隱藏UserForm2窗體,顯示原窗體,設(shè)置焦點(diǎn)到文本框就OK了。這個(gè)事件是在KeyDown事件子過程中通過代碼人為產(chǎn)生的,是受控的,因此可以將其看作是KeyDown事件代碼邏輯的一部分。 1 'UserForm1窗體 2 3 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 4 If KeyCode = 13 Then 5 TextBox1.Value = '' 6 UserForm1.Hide 7 UserForm2.Show 8 End If 9 End Sub 1 'UserForm2窗體 2 3 Private Sub UserForm_Activate() 4 UserForm2.Hide 5 UserForm1.Show 6 UserForm1.TextBox1.SetFocus 7 End Sub 實(shí)測效果非常理想,窗體切換的速度肉眼根本察覺不到,感覺就是文本框保持焦點(diǎn),用條碼槍連續(xù)輸入,不需要鍵盤和鼠標(biāo)輔助定位。 這是我的解決之道,可能比較繁瑣,如果你有更高明的方法,歡迎蒞臨指導(dǎo)! |
|