Win32API讲座4

第四课:鼠标、插入符及系统函数

一、指针剪切

    什么是指针呢?我想大家都知道,没必要我多讲。只是概念上应当清楚,指针是指针,鼠标是鼠标,鼠标控制着指针。在win16中,指针只有一个,运行在系统中的应用程序共享这个指针。但在win32中,各个窗体都具有着自己的指针。这倒不是说屏幕上能同时出现好几个指针,而是说每个窗体都具有它自己的样式和一些特征的指针。指针移动到某窗体的时候,指针就自动变成那个窗体的指针样式。
对指针需要认识的另一点是,指针的位置都是以像素屏幕坐标指定的。这一点很重要。
接下来,我们进入本小节的主题。

    只要你细心一些就能够发现,鼠标指针一般是不能超出屏幕(显示器屏幕)范围的。但这倒也不是绝对的,一会儿你就会明白。指针一般控制在屏幕以内,这是事实。从这个事实中我们可以知道,指针是限定在某个区域之内活动着的。把指针的活动限定一个区域的过程叫做指针剪切。
有关指针剪切的函数有两个。一个是GetClipCursor函数,它可以获得当前鼠标指针的剪切区域。此函数只有一个RECT结构的参数,函数调用结束后,这个RECT结构的数据,中便装载当前鼠标的矩形剪切区域大小。如果在一般情况下调用此函数,你大概获得的正好是屏幕大小。

    另一个函数是,SetClipCursor函数,作用是设置指定大小的指针剪切区域。欲设置的指针大小是装在一个RECT结构的数据中传递的。
这两个函数一般搭配使用。在设置新的指针剪切区域前用GetClipCursor函数获取当前指针剪切区域,以便保存其值,而后调用SetClipCursor函数设置新的剪切区域。当这种新的剪切区域不再需要时就向SetClipCursor函数传递先前保存下来的区域值,就可以恢复到原来的指针剪切区域了。
本教程为此提供了Program1.vbp演示程序。本人在设计这个程序时,忘了恢复原来的指针区域,结果指针无法脱离新设定的框架(自然也就无法按动敗翑按钮了),不得不用
CTRL+ALT+DELETE强行关闭VB设计器。望也成为您的一个经验。

二、指针位置函数

     指针位置函数,简单得和指针剪切函数差不多。WINDOWS为此也提供了两个函数,一个是GetCursorPos,另一个是SetCursorPos。GetCursorPos函数只有一个参数,用来装载一个POINTAPI结构的数据,该数据说明的是当前指针的X和Y的坐标。但SetCursorPos
函数有所不同,它不依靠POINTAPI结构的数据,需要直接向它传递指针的X和Y两个参数。
    本教程提供的program2.vbp正是对这两个函数的使用演示,演示一种指针的自动移动。

在这两个函数中GetCursorPos函数的使用率比较高。作为一个比较精彩的例子,本人把自己的第4号演示程序简化为本教程的program6.vbp。此程序演示如何拖动无标题栏的窗体。程序还使用了我们在前几个课堂当中学习到的一些窗口函数,可作为一个好的复习材料,欢迎阅读。
在program2.vbp中,对程序中采用的一点数学知识,怕有些朋友难以看出来(注意∶不是斈岩岳斫鈹),在此简单说明。首先程序通过一些方法计算出了鼠标指针的开始位置(
OldPoint)和终点位置(NewPoint)。指针需要在连接这两个点的直线上移动。我们知道,如果设(X,Y)是指这个直线上的一个点,那么这个直线的方程可以是这样写的∶Y=aX+b

    这里a和b是常数。
    如果我们知道了a和b,那么只要X按一定的单位量增加,那么Y的值也就可以得知了。问题是如何确定这里的a和b呢?
解决方法是∶
设,鼠标起点坐标为∶X1,Y1
    鼠标终点坐标为∶X2,Y2
则∶
Y1=aX1+b      ①
Y2=aX2+b      ②
从①可得∶b=Y1-aX1    ③

    把③代入②可得,Y2=aX2+Y1-aX1   ④
    从④可得∶a=(Y2-Y1)÷(X2-X1)
    获得a以后剩下的事情就好办了,可以用①或②获得b。
    (这实际上是初中一年级的内容!不过一年级的学生可能不一定知道它代表的是直线。解析几何好象在高中二年级开课。你也可以用解析几何的方法来理解。)

三、其他指针函数

    有关的指针函数还有以下几个

函  数                          说  明
CreateCursor             在两幅位图的基础上创建一个指针
DestroyCursor            清除一个指针,并释放它占用的系统资源
GetCursor                取得当前指针的句柄
GetDoubleClickTime       了解两次连续鼠标单击之间被看作双击事件的时间长度
LoadCursor               从一个文件载入指针资源
mouse_event              生成一个鼠标模拟事件
SetCursor                    选择要使用的指针
SetDoubleClickTime       设置两次连续单击之间被看作一次双击的时间长度
SetSystemCursor          改变任何系统标准指针
ShowCursor                 控制指针的可视性
SwapMouseButton          交换左右鼠标按钮的作用

    这里写出的很多函数并没有太大的用处。当然,您正好找这些函数,那这对你来说可能是一件非常斨卮髷的发现。你已经看到,对于有些函数功能,VB自身已经拥有的。在这几个函数中本人最喜欢mouse_even函数,有必要向大家介绍。
    如果你还没有看Program2.vbp,那么最好先启动并运行它一下。程序的目的是用鼠标指针的移动来自动演示擷ing对你说“Xing对你说”这个按钮的用法。可喜,鼠标指针移动到这个按钮后,按钮并没有被按下。当然,这个程序根本没有设计成按那个按钮,而是直接调用Command2_Click过程。这当然是假的了,糊弄人的了。

    有了mouse_even函数以后,我们可以更换一下设计思路。也就是说,当鼠标指针移动到“Xing对你说”这个按钮以后,不要直接调用Command2_Click过程,而是模拟产生对按钮的点击操作。Program3.vbp正是把这个设计思路搬到了实际程序。程序中还使用了一个还没有学到的API函数Sleep。此函数用来使线程等待一定时间,时间以毫秒表示。如果想等待20毫秒,就可以写为: Sleep 20  。由于经常需要使用,先在这里简单讲一讲为好。
    请打开并运行Program3.vbp,现在,示范过程是否像个那么一回事?

四、关于插入符

    作为一个资源,插入符通常用于表示文本编辑器中的一个位置,用来输入文字。外观上一般是闪烁的线段或者光标块。但,事实上插入符可以是任何样式。其样式可以用位图来处理。但由于使用位图是以后的学习内容,本教程不予演示程序。等您学会了位图,这些都是很轻松的事情。您现在需要认识的是什么是插入符,它到底是如何创建,如何固定位置,如何显示等内容,以便在自己的程序中应用。

函  数                   说   明
CreateCaret             创建和选择一个插入符
DestroyCaret            清除插入符
GetCaretBlinkTime       获得插入符的闪烁频率
GetCaretPos             了解插入符在逻辑坐标中的位置
HideCaret               隐藏插入符
SetCaretBlinkTime       设置插入符的闪烁速率
SetCaretPos             设置插入符在逻辑坐标中的位置
ShowCaret               让插入符可见

    按道理来讲,插入符函数应当在控件的GotFocus事件中进行创建和初始化处理。也就是说,在控件得到焦点的时候。不幸的是,VB中只有在控件丢失焦点,并由当前应用程序中另一个控件继承焦点的事后,才会触发GotFocus事件。你可以启动Program4.vbp作试验。具体方法是,应用程序启动以后点一下VB设计器,使VB设计器成为活动窗体。这时,应用程序窗口将退到VB后面看不到。确认VB设计器中看到了闪烁的插入符光标后,从任务栏中点一下应用程序任务条,使应用程序窗体成为活动窗口。这时应用程序窗体将从VB
设计器后面跳到前台并显示。这时你可以观察到,上面的Picture1控件的光标消失了。用鼠标点击控件也无任何反应。除非你先点一下下方的Text控件,然后再点Picture控件,光标是不会出现的。当然完全可以用一个计时器来探测控件得到焦点的情况,但这种作法显然麻烦。对于这个问题我一般是在控件的Click事件中写一行代码来激活GotFocus事件内部的代码(参看程序,并将Private Sub Picture1_Click()事件中的代码Picture1_GotFocus无效)。

    书本上说,插入符应当在LostFocus事件中清楚掉。但本人认为没有必要,这反而会产生一些符作用。比如在本教程提供的Program4中,如果使LostFocus事件内的代码dl& = DestroyCaret有效,结果当我们点击Text控件的时候会看不到插入符的。所以我认为,在想用插入符的时候,您尽管创建就可以了。不想看到它,就采用HideCaret函数隐藏之。
    附带的演示程序Program4.vbp总结了一些常用的插入符函数。

五、键盘控制函数

    要使用键盘控制函数,首先必须认识什么是扫描码,什么是虚拟键码。所谓扫描码是一种计算机键盘的硬件决定的代码,可以说不同类型的键盘有不同标准的扫描码。如果我们直接用扫描码来设计程序,那大概是一件非常枯燥的事情,况且很难保证程序的兼容性。与扫描码不同,虚拟键码对每台计算机来讲都是一样的。这里,所谓键码不是别的,只是用哪个数据来表示哪个按键的问题。
    从工作原理来讲,计算机键盘向计算机发送的是扫描码,然后来自键盘的扫描码将被转换为虚拟键码,究竟谁去做这种转换,我们就不用关心了。最后,WINDOWS将虚拟键码再转换为ASCII码或字符。正如所看到过的那样,VISUAL BASIC的KeyPressed等事件中递送过来的键码就是ASCII码了。

    另外,Unicode字符集和ANSI字符集的概念也需要掌握一些。时间关系,以下直接把一本叫《VB核心技术》的书中一段精彩的论述摘录给大家,作者是Bruce Mckinney。现在就要学习的朋友请点击这里。
    现在,把有关键盘处理函数列到如下表,大家先大概看一下究竟都有哪些功能的函数∶

键盘处理API函数

函  数                         说   明
ActivatekeyBoardLayout  在由系统定义的键盘布局中选择一种
EnumSystemCodePages     获得系统支持或安装的所有代码页的一个列表
GetACP                 获得目前使用的ANSI代码页的表示符
GetAsyncKeyState 获取函数调用时指定虚拟键的状态
GetCPinfo               获取与一个代码页有关的信息
GetKeyboardLayout       判断一个指定线程使用的键盘布局
GetkeyboardLayoutList 取得目前可用键盘布局的一个列表
GetKeyboardLayoutName 取得键盘布局的名称
GetKeyboardState 取得256个虚拟键目前的状态
GetKeyboardType         判断目前使用的键盘类型
GetKeyNameText          判断一个特定虚拟键的名称
GetKeyState             取得指定虚拟键的状态
GetOEMCP                取得目前正在使用的OEM代码页的标识符
keybd_event             为系统生成一个新的键盘布局
LoadKeyboardLayout      载入一个新的键盘布局
MapVirtualKey           在字符与虚拟键、扫描码以及ASCII码之间进行转换
MapVirtualKeyEx         同上
OemKeyScan              将ASCII代码转换成OEM扫描码
SetKeyboardState        将256个虚拟键的状态设为WINDOWS所能理解的状态
ToAsciiToAsciiEx          将一个扫描码和Shift状态转换成对应的ASCII码字符
ToUnicode                   将一个扫描码和Shift状态转换成对应的Unicode字符
UnloadKeyboardLayout    卸载以前有LoadKeyboardLayout函数载入的键盘布局
VkkeyScan,VkKeyScanEx   将ASCII代码转换成虚拟键码和Shift键状态。

    已经看到有很多键盘控制函数。但这些函数的参数基本上都局限在虚拟码和扫描码,也就是说你能够为这些函数提供虚拟码和扫描码,这些函数基本上都能够掌握和使用的。虚拟键码供有256个,很难在这里给出,但我觉得也没必要给出,简单说明一下就可以了。虚拟键码是以“VK_”开头的,比如Ctrl键为VK_CONTROL,Alt键为VK_MENU。只要你打开API文本游览器,选择常数(Consts)后键入“VK_”那么从列表框中可以看到一大堆以“VK_”开头的虚拟键码。另一种技巧是VB本身也有自己的简码表,VK_CONTROL在VB中大概是vbKeyControl了,你把前面的“vbKey”字样去掉,然后换上“VK_”,估计也能查到相关的虚拟键名( 好象其值也一样,比如vbKeyContol的值为17(十进制),而VK_CONTRIL的值为&H11(16进制)。我不敢保证,也没有太多的时间一一对照,有兴趣的朋友可以直接用vbKeyXXXXX来试一试。)。至于扫描码,就依靠MapVirtualKey函数从一个虚拟键码转换一下就可以了。

     为了帮助大家理解好这些函数的实际应用,本教程附带了两个例程,一个是Program4.vbp,另一个是Program8.vbp。
     前一个程序是从我的一个演示程序中转化过来的,主要演示按键检测与设定快捷键。这个程序可能有另外的一个用处。举例来说,我一开始不明白键盘上的“Print Screen SysRq”键的虚拟键名是什么。我当然有虚拟键码表,但正如一般人只知道“Ctrl”键名而不知道“CONTROL”这个键名一样(两者实际上是一样),我在列表上无法找到“Print Screen SysRq”这个键的虚拟键名了。后来我启动我这个程序,按了一下“Print Screen SysRq”一看,程序表明它的虚拟键值等于是40(十进制),接着拿Windows提供的计算器一换算,其16进制数据为&H2C。哈,这下就好办了,一看列表,合&H2C对应的虚拟键名为“VK_SNAPSHOT”怎么样,很有意思吧?

     第二个程序是我曾经回答一位网由时做的小程序。不幸的是这位网友提的问题在我上一次的硬盘故障中丢失了。大概内容是这样的,很像考试卷里的提问∶“窗体里只有一个文本框,在文本框中输入一些文字后点击一下已经启动的Word,Windows的笔记本等文本编辑器程序窗口,这时,文本框里的内容直接粘贴到这些编辑页中,而不按任何其他的键(如Ctrl+V)。”我的这个程序是以Word为例编写的,要成功地运行它事先您必须启动Word编辑器,并打开一个新的编辑页。

六、系统函数

    对与Windows的系统函数,我觉得没必要进行特别的说明,因为这些函数根本就没有特别之处。只是,这些函数主要是用来获取和设置系统有关信息的。比如设置桌面壁纸,默认的窗体呀,命令按钮呀之类的颜色呀什么的,还是您自己看更好一些。如下列表∶

函  数                   说  明
Beep                     使PC喇叭发出声音
ExitWindowsEx            以各种方式退出和重新启动WINDOWS
ExpandEnvironmentStrings 构件环境字串
FreeEnvironmentStrings   释放由GetEnvironmentStrings分配的一个环境字串块
GetCommandLine           取得用于启动应用程序的命令行
GetCOmputerName          取得当前电脑的名字
GetEnvironmentString     取得一个环境块,它提供的对环境变量的访问途径
GetEnvironmentVariable   获得环境块中一个单独的环境变量
GerLastError             取得上一个API函数调用的扩展错误信息。Visual Basic中请用Err对象的LastDLLError属性获得这个值
GetSysColor              取得Windows当前的各种颜色设置
GetSystemInfo            取得与硬件平台有关的信息
GetSystemMetrics         判断一系列系统样式信息;比如菜单栏或窗体标题的高度,垂直滚动条的高度,窗口最小尺寸等等。
GetSystemPowerStatus     取得与电源以及系统状态的有关信息
GetUserName              取得当前的用户名字
GetVersion,GetVersionEx  判断正在运行的Windows和DOS的版本
MessageBeep              生成一个标准系统声音
SetComputerName          设置电脑名
SetEnvironmentVariable   设置一个环境块中的环境变量
SetSysColors             设置Windows对象的当前颜色
SystemParametersInfo     一个功能强大的函数,用来获取与设置众多的系统参数比如保护程序,桌面墙纸,键盘延迟和重复率等等。

   当然,从这些函数中忽乱选择一些函数,也做了一个演示程序(Program7.vbp)。分析代码时请掌握好SYSTEM_INFO和OSSYSTEMINFO结构的用法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值