VBA TextBox实现拦截特定字符,实现快捷键

VBA版本:7.1

系统:Win10 64位

VBA虽然是一门古老的语言,但是在办公方面仍然有奇效,特别是Excel模板打印,本人浸淫打印2年多,平均每天打印不下十张POP,经过不断探索,发现一条通过VBA实现自动化模板打印的解决之道。今天分享一下在UserForm中实现快捷键的方式

一、KeyMap

        按键映射,每个键按下后,会有一个keyCode,和一个shift,前者表示单个键对应的键码,后者表示控制键的组合码。

 

KeyCode
65a
66b
67c
68d
69e
70f
71g
72h
73i
74j
75k
76l
77m
78n
79o
80p
81q
82r
83s
84t
85u
86v
87w
88x
89y
90z
188,
190.
191/
186;
222'
219[
221]
220\
20Caps
192`
491
502
513
524
535
546
557
568
579
480
189-
187=
8Cancel
46Delete
45Ins
36Home
35End
33PageUp
34PageDown
44PageDown
145ScrlLk
19Pause
123F12
122F11
27ESC
45Ins
112F1
113F2
114F3
115F4
116F5
117F6
118F7
119F8
120F9
121F10
38Up
40Down
37Left
39Right
93Menu
Shift
1

Shift

2Ctrl
4Alt

例如:Ctrl + Shift + a,则Keycode = 65(a的KeyCode),Shift = 3(Ctrl=1 + Shift=2),注意此处Shift是Shift、Ctrl、Alt 3个键统称,

VBA有内置KeyCodeConstaints枚举常量,可以知道每个键对应的KeyCode,但是我没找到怎么通过KeyCode找到对应的键名,只好一个键一个键按,然后录入进去😶。可以直接将KeyCode的映射表复制到单元格内,利用Match或者Vlookup函数查询每次按键对应的按键名。

如下图:我将KeyCode与KeyName的映射保存在从101行开始往后,每次按键时将KeyCode填入A100,然后在B100中通过公式查找KeyCode对应的KeyName,在程序中就可以直接读取B100的值获取KeyName

通过textbox设置快捷键:

 

'keyUP快捷键注册
Private Sub ShortKeyTBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    ShortKeyTBox = getShortKey(KeyCode, Shift)
    applyCBT.SetFocus '阻止后续的控制键keyup事件,将焦点转移到别处
    ShortKeyTBox.SetFocus '再转移回来
End Sub

'快捷键录入的文本框调用此代码,获取用户按下的键名组合,并返回组合字符串
Public Function getShortKey(ByVal KeyCode As Integer, ByVal Shift As Integer)
    Dim controlKey As String
    Dim KeyName As String
    Dim rowCount As Integer
    
    If KeyCode = 16 Or KeyCode = 17 Or KeyCode = 18 Then '过滤单独的Ctrl,Shift,Alt按键事件
        Exit Function
    End If
    
    Sheet1.Range("B28") = Shift '将Shift组合码保存在单元格中

    Select Case Shift '根据Shift组合码分析控制按键组合,Shift=1,Ctrl=2,Alt=4,3者任意组合
        Case 0
            controlKey = ""
        Case 1
            controlKey = "Shift + "
        Case 2
            controlKey = "Ctrl + "
        Case 4
            controlKey = "Alt + "
        Case 5
            controlKey = "Alt + Shift + "
        Case 6
            controlKey = "Ctrl + Alt + "
        Case 3
            controlKey = "Ctrl + Shift + "
    End Select
    
    KeyName = ShortKeyTBox '如果是按下的0-9或者字母符号,并且没有按下控制键,可以直接在文本框中获取到按键名,不用通过KeyCode获取映射,如果不是文本框则此方法无效
    
    If KeyName = "" Then '查询KeyCode对应的KeyName
        Sheet1.Range("A100") = KeyCode
        KeyName = Sheet1.Range("B100")
    End If
        
    
    If KeyName = "" Then '没查到KeyName,用户手动输入
    
        KeyName = InputBox(CStr(KeyCode) + "键名为空,请输入您刚按下的最后一个键键帽上的字符,如F1键则输入'F1'", "键盘映射") '获取用户输入的对话框
        
        rowCount = Sheet1.Range("A" & Rows.count).End(xlUp).Row '获取映射表最后一行行号,用于追加新信息
        
        Sheet1.Range("A" & CStr(rowCount + 1)) = KeyCode '将KeyCode追加到映射表格的最后一行
        
        Sheet1.Range("B" & CStr(rowCount + 1)) = KeyName '将KeyName追加到映射表格的最后一行
        
    End If
    
    
    Sheet1.Range("B29") = KeyCode '将KeyCode保存在单元格中
    Sheet1.Range("C29") = KeyName '将KeyName保存在单元格中
    
    getShortKey = controlKey + KeyName '快捷键的组合名
End Function

没有找到全局按键监听方式,好像VBA的按键不是冒泡机制,没有传递或者无法在按键触发的起点进行拦截,只能针对获取焦点的对象进行设置,所有想要实现全局快捷键。。。也不是不可以,将每一个控件都设置一下就可以了😎

例如为TextBox注册一个打印快捷键:

        先通过前面的方法录入快捷键,例如Ctrl+Enter,Keycode=13,Shift=2

        然后:

'注册快捷键的TextBox,在KeyUp中注册
Private Sub PD1PLUTB_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
    
    Call setPrintListener(KeyCode, Shift)
End Sub
'注册快捷键
Sub setPrintListener(ByVal KeyCode As Integer, _
ByVal Shift As Integer)
    If KeyCode = Sheet1.Range("B29") And Shift = Sheet1.Range("B28") Then
        Call printNow
    End If
    
End Sub

Public Sub printNow()

    Excel.ActiveSheet.PrintOut
    
    If Sheet1.Range("B27") Then '打印后userform失去焦点,需要重新打开获取焦点
        singlePageUSF.Hide
        singlePageUSF.Show
    End If
End Sub

 这样在注册了快捷键的文本框内按Ctrl+Enter,Excel就会打印激活的sheet

但是我比较懒,我觉得两个键还不够快,不够丝滑,所以我想将快捷键设置为一个键打印,也就是一键打印。比如说设置为空格(根据实际情况,需要输入的内容只有数字,没有其他的字符,所有可以设置为空格),但是有个问题,文本框中按空格键效果你懂的,就是多了一个空格,就算注册了快捷键也会多一个空格,一开我想将空格键KeyDown时之前文本框内的类容保存下来,空格键KeyUp之后再重新设置回去,我试了一下,效果差强人意,但还是不够丝滑,中间明显有一个过渡期,多了一个空格然后全部消失,然后再全部变回去。

经过一顿搜索,我找到了一点线索,耶~。

 TextBox有个Boolean属性叫Locked(锁),当Locked属性为true时,文本框无法输入信息,但是可以选中,也可以监听Key事件,所以问题解决了:

'这里KeyCode = 32可以改成自己设置的,或者某个单元格,反正是某个变量,我这是之前测试的,还没改
Private Sub PD1PromotionStartDateTB_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 32 Then
        PD1PromotionStartDateTB.Locked = True '如果按下了目标键,锁住TextBox,实现了过滤效果
    End If
End Sub

Private Sub PD1PromotionStartDateTB_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
End Sub

Private Sub PD1PromotionStartDateTB_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Call setPrintListener(KeyCode, Shift)
    PD1PromotionStartDateTB.Locked = False '释放目标键后,将TextBox解锁
End Sub

效果非常丝滑~

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值