昨儿装了一XP的离开模式补丁,愕然发现自己的键盘没有Sleep键……
无奈开始着手写一个模拟按键的小程序,就这么一个小东西算是难住我了。
先后试了 SendKeys 、keybd_event 、PostMessage 都就不能模拟Sleep键,别的都行。
最后终于baidu到了方法~ 奉上。
驱动级模拟:直接读写键盘的硬件端口。
昨儿装了一XP的离开模式补丁,愕然发现自己的键盘没有Sleep键……
无奈开始着手写一个模拟按键的小程序,就这么一个小东西算是难住我了。
先后试了 SendKeys 、keybd_event 、PostMessage 都就不能模拟Sleep键,别的都行。
最后终于baidu到了方法~ 奉上。
驱动级模拟:直接读写键盘的硬件端口
在这里我们可以使用一个组件WINIO来完成读写端口操作。什么是WINIO?WINIO是一个全免费的、无需注册的、含源程序的WINDOWS2000 端口操作驱动程序组件(可以到http://www.internals.com/上 去下载)。它不仅可以操作端口,还可以操作内存;不仅能在VB下用,还可以在DELPHI、VC等其它环境下使用,性能特别优异。下载该组件,解压缩后可 以看到几个文件夹,其中Release文件夹下的3个文件就是我们需要的,这3个文件是WinIo.sys(用于win xp下的驱动程 序),WINIO.VXD(用于win 98下的驱动程序),WinIo.dll(封装函数的动态链接库),我们只需要调用WinIo.dll中的函数, 然后WinIo.dll就会安装并调用驱动程序来完成相应的功能。值得一提的是这个组件完全是绿色的,无需安装,你只需要把这3个文件复制到与你的程序相 同的文件夹下就可以使用了。用法很简单,先用里面的InitializeWinIo函数安装驱动程序,然后就可以用GetPortVal来读取端口或者用 SetPortVal来写入端口了。好,让我们来做一个驱动级的键盘模拟吧。先把winio的3个文件拷贝到你的程序的文件夹下,然后在VB中新建一个工 程,添加一个模块,在模块中加入下面的winio函数声明:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
Declare Function MapPhysToLin Lib "WinIo.dll" (ByVal PhysAddr As Int32, ByVal PhysSize As Int32, ByRef PhysMemHandle As Object) As Int32
Declare Function UnmapPhysicalMemory Lib "WinIo.dll" (ByVal PhysMemHandle, ByVal LinAddr) As Boolean
Declare Function GetPhysint32 Lib "WinIo.dll" (ByVal PhysAddr As Int32, ByRef PhysVal As Int32) As Boolean
Declare Function SetPhysint32 Lib "WinIo.dll" (ByVal PhysAddr As Int32, ByVal PhysVal As Int32) As Boolean
Declare Function GetPortVal Lib "WinIo.dll" (ByVal PortAddr As Integer, ByRef PortVal As Int32, ByVal bSize As Byte) As Boolean
Declare Function SetPortVal Lib "WinIo.dll" (ByVal PortAddr As Integer, ByVal PortVal As Int32, ByVal bSize As Byte) As Boolean
Declare Function InitializeWinIo Lib "WinIo.dll" () As Boolean
Declare Function ShutdownWinIo Lib "WinIo.dll" () As Boolean
Declare Function InstallWinIoDriver Lib "WinIo.dll" (ByVal DriverPath As String, ByVal Mode As Integer) As Boolean
Declare Function RemoveWinIoDriver Lib "WinIo.dll" () As Boolean
'---------以上是WINIO函数声明--------
Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Int32, ByVal wMapType As Int32) As Int32
'---------以上是WIN32 API函数声明--------
再添加下面五个过程:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
Sub KBCWait4IBE() '等待键盘缓冲区为空
Dim dwVal As Int32
Do
GetPortVal(&H64, dwVal, 1)
'这句表示从&H64端口读取一个字节并把读出的数据放到变量dwVal中
'GetPortVal函数的用法是GetPortVal 端口号,存放读出数据的变量,读入的长度
Loop While (dwVal And &H2)
End Sub
Public Const KBC_KEY_CMD = &H64 '键盘命令端口
Public Const KBC_KEY_DATA = &H60 '键盘数据端口
Sub MyKeyDown(ByVal vKeyCoad As Int32)
'这个用来模拟按下键,参数vKeyCoad传入按键的虚拟码
Dim btScancode As Int32
btScancode = MapVirtualKey(vKeyCoad, 0)
KBCWait4IBE() '发送数据前应该先等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
'SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, btScancode, 1) '写入按键信息,按下键
End Sub
Sub MyKeyUp(ByVal vKeyCoad As Int32)
'这个用来模拟释放键,参数vKeyCoad传入按键的虚拟码
Dim btScancode As Int32
btScancode = MapVirtualKey(vKeyCoad, 0)
KBCWait4IBE() '等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, (btScancode Or &H80), 1) '写入按键信息,释放键
End Sub
Sub MyKeyDownEx(ByVal vKeyCoad As Int32) '模拟扩展键按下,参数vKeyCoad是扩展键的虚拟码
Dim btScancode As Int32
btScancode = MapVirtualKey(vKeyCoad, 0)
KBCWait4IBE() '等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, &HE0, 1) '写入扩展键标志信息
KBCWait4IBE() '等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, btScancode, 1) '写入按键信息,按下键
End Sub
Sub MyKeyUpEx(ByVal vKeyCoad As Int32) '模拟扩展键弹起
Dim btScancode As Int32
btScancode = MapVirtualKey(vKeyCoad, 0)
KBCWait4IBE() '等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, &HE0, 1) '写入扩展键标志信息
KBCWait4IBE() '等待键盘缓冲区为空
SetPortVal(KBC_KEY_CMD, &HD2, 1) '发送键盘写入命令
KBCWait4IBE()
SetPortVal(KBC_KEY_DATA, (btScancode Or &H80), 1) '写入按键信息,释放键
End Sub
在From_Load事件加载驱动,Form_FormClosing卸载驱动:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If InitializeWinIo = False Then
'用InitializeWinIo函数加载驱动程序,如果成功会返回true,否则返回false
MsgBox("驱动程序加载失败!")
Me.Close()
End If
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
ShutdownWinIo()
End Sub
调用方法:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MyKeyDown(Keys.NumLock)
MyKeyUp(Keys.NumLock)
End Sub
试试看NumLock灯是不是有变化?
将按键改成 Keys.Sleep 就可以休眠了。
原文地址:http://hi.baidu.com/skyue4me/blog/item/bbf913588d57e584810a180d.html
里面还有 keybd_event 、PostMessage 的VB6用法。
PS:有网友说要程序,这就奉上。
https://files.cnblogs.com/mx1700/休眠.rar