荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Jobs (温少), 信区: Visual
标  题: 利用VBA的键盘类
发信站: BBS 荔园晨风站 (Sun Jan 16 18:50:23 2000), 转信






  通过使用VBA,,你已经习惯于使用对象以及它们继承的属性和方法了。事实
上,用任何其他的方法编程是很困难(甚至是很痛苦)的。不幸的是,仍然存在
大量的只能提供给老式的、非面向对象方法的功能。一个典型的例子是函数调用
的海洋棗Windows API。使用类模块的一个诱人特征就是你可以用一套公共接口将
这样的功能体包如可以管理的对象。这就是说,你可以隐藏相关的信息集的详细
资料,并将它展现给对象。

  例如,假定你已经在某个VBA项目中找到了与用户的键盘进行交互作用的需要
。那么你可能想加快或降低箭头闪烁的速度;了解用户具有多少个功能键;修改
键盘重复速度及重复之前的延迟时间,或者检索和设置功能键的状态,例如n, c
和o。为了做到这一点,需要使用Windows API,,并且需要声明、外部函数调用、
使用用户定义的类型和API定义的常量棗所有这些都是令人感到不愉快的。


  如果你有一个简单的Keyboard对象,可以提供属性来为你完成所有的工作,
这不是很好吗?当然是!另外,正如已经指出的,这就是本文的目标。Windows
API提供了大量的有关键盘的信息,但是检索它需要调用大量 的函数,因此你必
须知道应该调用哪个函数,如何调用它们,它们返回什么信息等等。本文介绍了
一个VBA Keyboard类,它具有图1中所介绍的属性(使用它们创建的模块和对象的
更加吸引人的一个原因是你可以从相同的类例示多个对象,尽管你从不需要在单
个应用程序中创建Keyboard类的多个实例,不使用类模块也是没有理由的)。



Property Description Allowable Values Read/Write

KeyboardType Determines the type (number of keys) of the keyboard. N/A R

FunctionKeys Determines the number of function keys. N/A R

CapsLock Retrieves or sets the state of the c toggle. True/False R/W

NumLock Retrieves or sets the state of the n toggle. True/False R/W

ScrollLock Retrieves or sets the state of the o toggle. True/False R/W

Delay Retrieves or sets the keyboard repeat-delay setting. 0-3 R/W

Speed Retrieves or sets the keyboard repeat speed. 0-31 R/W

CaretBlinkTime Retrieves or sets the number of milliseconds between blinks of
the insertion caret. 200-1200 (generally in increments of 100) R/W

  图1 Keyboard类提供的属性

  为了测试一下Keyboard.cls(你将在本文的稍后部分找到代码,它还可以通
过下载提供棗请参阅本文结尾以获取详细信息),你首先需要一个名为Keyboard
的类模块,然后将你的代码插入项目。一旦已经在你的项目中获得了Keyboard类
模块,你就可以像使用任何其他类一样使用它了。例如,使用Keyboard类创建该
类的一个新实例,然后设置或检索它的可提供属性。例如,为了检索和设置当前
键盘延迟设置,你可以使用类似如下的代码:

Dim okb As Keyboard

Set okb = New Keyboard

If okb.Delay < 3 Then

okb.Delay = okb.Delay + 1

End If

  这显然比直接调用大量的Windows API函数要容易得多!

用困难的方法来做

  为了完成它的工作,Keyboard需要调用Windows API。本节文章将研究特定的
API调用。如果你怒感兴趣的话,可以介绍如何使用类的跳到下一节。

  键盘类型。检索键盘的类型和功能键的数目很简单。调用GetKeyboardType
API函数,向它传递值0可获得键盘类型,传递值2可获得功能键 的数目。该函数
将返回如图2所示的键盘类型,如图3所示的功能键数目。

Value Keyboard Type

1 IBM PC/XT or compatible (83-key)

2 Olivetti “ICO” (102-key)

3 IBM PC/AT (84-key) or similar

4 IBM enhanced (101- or 102-key)

5 Nokia 1050 and similar

6 Nokia 9140 and similar

7 Japanese

  图2 GetKeyboardType的键盘类型返回值

Value Number of Function Keys

1 10

2 12 (sometimes 18)

3 10

4 12

5 10

6 24

7 独立于硬件,由OEM指定

  图3 GetKeyboardType的功能键返回值

  当然,为了使用这些函数,类模块需要API函数的声明,因此它必须在它的
Declarations段包括如下的代码行:

Private Declare Function GetKeyboardType Lib "User32" _

(ByVal lngTypeFlag As Long) As Long

为了检索键盘类型或功能键的数目(如前所述),Keyboard类模块应包含如下过程:

Property Get KeyboardType() As Long

KeyboardType = GetKeyboardType(0)

End Property

Property Get FunctionKeys() As Long

FunctionKeys = GetKeyboardType(2)

End Property

  键盘切换。为了设置键盘切换,你必须使用GetKeyboardState 和
SetKeyboardState API函数。为了检索切换键盘当前的状态,请使用GetKeyState
函数。这需要如下的声明:

Private Declare Function GetKeyState Lib "User32" _

(ByVal lngVirtKey As Long) As Integer

Private Declare Function GetKeyboardState Lib "User32" _

(bytKeyState As Byte) As Long

Private Declare Function SetKeyboardState Lib "User32" _

(bytKeyState As Byte) As Long

  为了检索一个键的状态,请调用GetKeyState,传递代表该键盘键的Windows
虚拟键码。幸运的是,VBA为n和 c提供了常量(vbKeyNumlock 和 vbKeyCapital)
。不过,不是所有的VBA实现都为 o提供了一个相似的键常量,因此你可以需要自
己定义常量。

Private Const vbKeyScrollLock = 145

  GetKeyState函数返回一个整数,包含了与你已经发送的键有关的信息,但是
你所需要的只是最低位。为了只检索最低位,可以使用And操作符和值1来忽略除
了最低位以外的所有信息。

  (注意:在二进制中,值1是由一串0后面跟着一个单独的1组成。这些数字中
的每个都叫做“位”。 And操作符对两个操作数的每位进行逻辑运算,除非相同
位置的两位均为1,否则结果位就为0。如果相同位置的两位均为1,那么结果为就
为1。按这种方法,通过将返回值和1相与,除了最低位取决于返回值之外,输出
的其余位将确保为0。输出的最后一位或者为0,或者为1,取决于GetKeyState返
回的值。这没有帮助吗?回答是肯定的棗你不用深入研究位运算便可以利用VBA进
行开发。通过在VBA IDE的联机帮助里面搜索“And operator”,还可以找到大量
的帮助。或者,使用“Logical Operators” 来搜索可以了解逻辑操作符的整个
家族)。

  为了确认是否已经设置了o切换,Keyboard类使用了如下的属性过程:

Property Get ScrollLock() As Boolean

' Return the ScrollLock toggle.

ScrollLock = CBool(GetKeyState(vbKeyScrollLock) And 1)

End Property

  你将发现类似的过程用于检索n和c切换的状态。

  设置切换的状态需要付出一点努力;你必须遵循如下步骤:

  调用一个API 函数 (GetKeyboardState)来检索整个键盘作为一系列字节(每
个键盘一个字节)的当前状态。

  在字节数组的范围内,改变使你感兴趣的键的状态。

  调用一个API 函数(SetKeyboardState),发送修改后的字节数组。该操作将
设置整个键盘的状态。

  对于每个GetKeyboardState 或 SetKeyboardState函数,将256个字节数组的
第一个元素传递给这个API函数。该函数或者用有关键盘的信息填充这个256个元
素的数组,或者使用字节来设置键盘的状态。Keyboard类包括如下私有过程,它
们可以完成所有的工作:

Private Sub SetKeyState(intKey As Integer, _

fTurnOn As Boolean)

' Retrieve the keyboard state, set the particular key in

' which you're interested; then set the entire keyboard

' state back the way it was, with the one key altered.

Dim abytBuffer(0 To 255) As Byte

Call GetKeyboardState(abytBuffer(0))

abytBuffer(intKey) = CByte(Abs(fTurnOn))

Call SetKeyboardState(abytBuffer(0))

End Sub

  这个类模块内部的代码调用这个过程(为n, c和o传递键常数)。
SetKeyState过程按照前面列出的步骤来完成它的工作。例如,Property Let过程
ScrollLock就是这个样子的:

Property Let ScrollLock(Value As Boolean)

' Set the ScrollLock toggle.

Call SetKeyState(vbKeyScrollLock, Value)

End Property

  可以重复延迟和速度。设置键盘重复速度以及在开始重复键之前键盘等待的
毫秒数,并不是十分困难的。这些任务需要调用SystemParametersInfo函数来申
请必要的信息或设置值。SystemParametersInfo是一个“抓错”函数;它可以做
很多事情,你可以通过向它传递一个常数来表明你想让它做的事情。例如,为了
将键盘延迟设置为3,你可以对SystemParametersInfo做如下调用:


Call SystemParametersInfo(SPI_SETKEYBOARDDELAY, _3, 0, SPIF_TELLALL)

  在这种情况下,第三个参数是不用的,因此将其设为0。第四个参数是一个在
类模块中定义的常数,它的作用是告诉SystemParametersInfo更新合适的.ini文
件和Windows注册表。这个常数还指示SystemParametersInfo向所有运行的
Windows应用程序都发送一条消息,告诉它们你已经改变了设置。除了所使用的常
数不同之外,设置重复速度的过程是相同的。

  为了使用SystemParametersInfo,你必须对它及你将要使用的任何参数进行
声明。Keyboard类模块包括这些声明:

Private Const SPI_GETKEYBOARDDELAY = 22

Private Const SPI_SETKEYBOARDDELAY = 23

Private Const SPI_GETKEYBOARDSPEED = 10

Private Const SPI_SETKEYBOARDSPEED = 11

SystemParametersInfo flags

Private Const SPIF_UPDATEINIFILE = &H1

Private Const SPIF_SENDWININICHANGE = &H2

Private Declare Function SystemParametersInfo _

Lib "User32" Alias "SystemParametersInfoA" ( _

ByVal uAction As Long, ByVal uParam As Long, _

lpvParam As Any, ByVal fuWinIni As Long) As Long

' This is a made-up constant.

Private Const SPIF_TELLALL = SPIF_UPDATEINIFILE Or _

SPIF_SENDWININICHANGE

  使用SystemParametersInfo检索值需要做一些工作。为了检索值,你必须传
递一个变量作为第三个参数,(一般)将0作为第四个参数。
SystemParametersInfo用所要求的值来填充变量,下面是Keyboard类模块里面的
一段:

Property Get Speed() As Long

Get the keyboard repeat-speed setting.

Dim lngValue As Long

Call SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, _

lngValue, 0)

Speed = lngValue

End Property

  使用^符号。还可以使用Windows API调用来设置和检索文字插入^符号之间闪
烁的豪秒数。GetCaretBlinkTime函数用来检索有关^符号的信息,
SetCaretBlinkTime函数用来设置闪烁时间。为了使用这些函数,你必须首先声明
它们。

Private Declare Function GetCaretBlinkTime _

Lib "User32" () As Long

Private Declare Function SetCaretBlinkTime _

Lib "User32" (ByVal wMSeconds As Long) As Long

  一旦你已经声明了这些函数,它们的使用则是非常简单的。例如,为了设置^
符号以便每隔50毫秒闪烁一次(不是非常好的主意),那么你可以编写如下的代
码:

Call SetCaretBlinkTime(50)

  注意!^符号是全局资源,因此如果你为应用程序改变了闪烁时间的话,它将
在所有应用程序中都改变。

  不要为详细资料而烦恼

  Don’t Sweat the Details

  当然,一旦你理解了所有的API调用之后,也就完成了创建类模块所必需的大
部分工作。如果你想显示图1中列出的属性,仅仅是编写合适的Property Let 和
Property Get procedures过程的问题了。第10页上的清单1包括了所有的属性过
程。

  为了使用Keyboard类模块,可以把它作为任何其他的类(如前所述,除了不
能创建类的多个实例之外)来对待。例如,为了将^符号闪烁时间设置为100毫秒
,并且打开c和n 切换(保留所有设置原来的状态),你可以编写如图4所示的代
码:

Dim fCapsLock As Boolean

Dim fNumLock As Boolean

Dim intBlinkTime As Integer

Dim okb As Keyboard

Set okb = New Keyboard

intBlinkTime = okb.CaretBlinkTime

fCapsLock = okb.Capslock

fNumLock = okb.Numlock

okb.CaretBlinkTime = 100

okb.Capslock = True

okb.Numlock = True

Later, to reset the states:

okb.CaretBlinkTime = intBlinkTime

okb.Capslock = fCapsLock

okb.Numlock = fNumLock

图4 使用Keyboard类来设置闪烁速率以及c和n切换


肯定没有人否认使用简单对象的属性比直接调用Windows API要容易得多。一旦你
已经完成了类模块(这应该是很容易的:只需从范例文件复制和粘贴代码即可,
参见本文的结尾部分可以获得下载详细资料的信息),那么就可以使用任何VBA应
用程序了。还有,因为IntelliSense,你甚至不需要记住属性的名字(我承认,
当我发现我自己需要恢复到Office 或 VB以前的版本的时候,我通常在当前版本
中编写代码,利用IntelliSense,然后将代码复制和粘贴进已经完成的旧版本)


试一试

创建Keyboard类,将它添加到项目,然后使用它。你将看到没有比这更容易的了
。你不需要知道或记住这些讨厌的API调用是如何工作的。随着过程的继续,我敢
保证我们会介绍更多的API包装类。Mike Gilbert和我已经为各种项目编写了大量
的类。你不应该再感到烦恼了,下面是可以方便调用的类模块:

Begin Listing One

Property Get KeyboardType() As Long

' Determine the type of keyboard on the system.

' 1 IBM PC/XT or compatible (83-key) keyboard

' 2 Olivetti "ICO" (102-key) keyboard

' 3 IBM PC/AT (84-key) or similar keyboard

' 4 IBM enhanced (101- or 102-key) keyboard

' 5 Nokia 1050 and similar keyboards

' 6 Nokia 9140 and similar keyboards

' 7 Japanese keyboard

KeyboardType = GetKeyboardType(0)

End Property

Property Get FunctionKeys() As Long

' Determine the number of function keys on the keyboard.

' 1 10

' 2 12 (sometimes 18)

' 3 10

' 4 12

' 5 10

' 6 24

' 7 Hardware dependent and specified by the OEM

FunctionKeys = GetKeyboardType(2)

End Property

Property Get Capslock() As Boolean

Return the Capslock toggle.

Capslock = CBool(GetKeyState(vbKeyCapital) And 1)

End Property

Property Get Numlock() As Boolean

' Return the Numlock toggle.

Numlock = CBool(GetKeyState(vbKeyNumlock) And 1)

End Property

Property Get ScrollLock() As Boolean

' Return the ScrollLock toggle.

' ScrollLock = CBool(GetKeyState(vbKeyScrollLock) And 1)

End Property

Property Let Capslock(Value As Boolean)

' Set the Capslock toggle.

Call SetKeyState(vbKeyCapital, Value)

End Property



Property Let Numlock(Value As Boolean)

' Set the Numlock toggle.

Call SetKeyState(vbKeyNumlock, Value)

End Property

Property Let ScrollLock(Value As Boolean)

' Set the ScrollLock toggle.

Call SetKeyState(vbKeyScrollLock, Value)

End Property

Private Sub SetKeyState(intKey As Integer, _

fTurnOn As Boolean)

' Retrieve the keyboard state, set the particular

' key in which you're interested, and then set

' the entire keyboard state back the way it

' was, with the one key altered.

Dim abytBuffer(0 To 255) As Byte

Call GetKeyboardState(abytBuffer(0))

abytBuffer(intKey) = CByte(Abs(fTurnOn))

Call SetKeyboardState(abytBuffer(0))

End Sub

Property Let Delay(Value As Long)

' Sets the keyboard repeat-delay setting.

' Only values 0 through 3 are acceptable. Others will be

' set back to 0.

Call SystemParametersInfo(SPI_SETKEYBOARDDELAY, Value, _

0, SPIF_TELLALL)

End Property

Property Get Delay() As Long

Dim lngValue As Long

Call SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, _

lngValue, 0)

Delay = lngValue

End Property

Property Let Speed(Value As Long)

' Sets the keyboard repeat-speed setting.

' Only values 0 through 31 are acceptable. Others will

' be set back to 0.

Call SystemParametersInfo(SPI_SETKEYBOARDSPEED, Value, _

0, SPIF_TELLALL)

End Property

Property Get Speed() As Long

' Get the keyboard repeat-speed setting.

Dim lngValue As Long

Call SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, _

lngValue, 0)

Speed = lngValue

End Property

Property Get CaretBlinkTime() As Long

' Retrieve the number of milliseconds

' between blinks of the caret.

' SYSTEM RESOURCE. Change this with care.

CaretBlinkTime = GetCaretBlinkTime()

End Property

Property Let CaretBlinkTime(Value As Long)

' Set the number of milliseconds

' between blinks of the caret.

' SYSTEM RESOURCE. Change this with care.

' Allowable values: 200 to 1200 (multiples of 100)

Call SetCaretBlinkTime(Value)

End Property

End Listing One

本文中所引用的文件可以从位于http://www.informant.com/mod/modnewupl.htm
的Informant Web站点通过下载得到。文件名为MOD9712KG.ZIP。


Ken Getz 和 Mike Gilbert是MCW Technologies的高级顾问,MCW Technologies
是Microsoft Solution Provider,其重点是Visual Basic 和 Office 和
BackOffice 组件。他们最近完成了VBA Developer’s Handbook 和 Access 97
Developer’s Handbook (与 Paul Litwin合作),两本书均由SYBEX出版。









--

   好好学习,天天向上!!!!

※ 来源:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 192.168.11.111]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店