📄 vb摸拟键盘 - aqbeyond的专栏 - csdnblog.htm
字号:
般发生在WM_KEYDOWN消息之后。WM_CHAR消息的lParam参数的含义与其它键盘消息一样,而它的wParam则表示相应字符的ASCII
编码(可以输入中文的哦^_^),现在你可以写出一个完整的向记事本里自动写入字符的程序了,下面是一个例子,并附有这些消息常数的具体值:<BR>Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long<BR>Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long</P>
<P>Public Const WM_KEYDOWN = &H100<BR>Public Const WM_KEYUP = &H101<BR>Public Const WM_CHAR = &H102<BR>Public Const VK_A = &H41 </P>
<P>Function MakeKeyLparam(ByVal VirtualKey As Long, ByVal flag As Long) As Long<BR> Dim s As String<BR> Dim Firstbyte As String 'lparam参数的24-31位<BR> If flag = WM_KEYDOWN Then '如果是按下键<BR> Firstbyte = "00"<BR> Else<BR> Firstbyte = "C0" '如果是释放键<BR> End If<BR> Dim Scancode As Long<BR> '获得键的扫描码<BR> Scancode = MapVirtualKey(VirtualKey, 0)<BR> Dim Secondbyte As String 'lparam参数的16-23位,即虚拟键扫描码<BR> Secondbyte = Right("00" & Hex(Scancode), 2)<BR> s = Firstbyte & Secondbyte & "0001" '0001为lparam参数的0-15位,即发送次数和其它扩展信息<BR> MakeKeyLparam = Val("&H" & s)<BR>End Function</P>
<P>Private Sub Form_Load()<BR> dim hwnd as long<BR> hwnd = XXXXXX 'XXXXX表示记事本编辑框的句柄<BR> PostMessage hwnd,WM_KEYDOWN,VK_A,MakeKeyLparam(VK_A,WM_KEYDOWN) '按下A键<BR> PostMessage hwnd,WM_CHAR,ASC("A"),MakeKeyLparam(VK_A,WM_KEYDOWN) '输入字符A<BR> PostMessage hwnd,WM_UP,VK_A,MakeKeyLparam(VK_A,WM_UP) '释放A键<BR>End Sub</P>
<P>这 就是通过局部键盘消息来模拟按键。这个方法有一个极大的好处,就是:它可以实现后台按键,也就是说他对你的前台操作不会有什么影响。比如,你可以用这个方
法做个程序在游戏中模拟按键来不断地执行某些重复的操作,而你则一边喝茶一边与QQ上的MM们聊得火热,它丝毫不会影响你的前台操作。无论目标程序是否获
得焦点都没有影响,这就是后台模拟按键的原理啦~~~~</P>
<P><BR>2.全局级模拟</P>
<P> 你会发现,用上面的方法模拟按键并不
是对所有程序都有效的,有的程序啊,你向它发了一大堆消息,可是它却一点反应也没有。这是怎么回事呢?这就要看具体的情况了,有些程序(特别是一些游戏)
出于某些原因,会禁止用户对它使用模拟按键程序,这个怎么实现呢?比如可以在程序中检查一下,如果发现自己不是活动窗口,就不接受键盘消息。或者仔细检查
一下收到的键盘消息,你会发现真实的按键和模拟的按键消息总是有一些小差别,从这些小差别上,目标程序就能判断出:这是假的!是伪造的!!因此,如果用
PostMessage发送局部消息模拟按键不成功的话,你可以试一试全局级的键盘消息,看看能不能骗过目标程序。<BR>模拟全局键盘消息常见的可以有以下一些方法:<BR>(1) 用API函数keybd_event,这个函数可以用来模拟一个键盘事件,它的VB声明为:<BR>Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)<BR>参数bVk表示要模拟的按键的虚拟码,bScan表示该按键的扫描码(一般可以传0),dwFlags表示是按下键还是释放键(按下键为0,释放键为2),dwExtraInfo是扩展标志,一般没有用。比如要模拟按下A键,可以这样:<BR>Const KEYEVENTF_KEYUP = &H2<BR>keybd_event VK_A, 0, 0, 0 '按下A键<BR>keybd_event VK_A, 0, KEYEVENTF_KEYUP, 0 '释放A键<BR>注意有时候按键的速度不要太快,否则会出问题,可以用API函数Sleep来进行延时,声明如下:<BR>Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)<BR>参数dwMilliseconds表示延时的时间,以毫秒为单位。<BR>那么如果要模拟按下功能键怎么做呢?比如要按下Ctrl+C实现拷贝这个功能,可以这样:<BR>keybd_event VK_Ctrl, 0, 0, 0 '按下Ctrl键<BR>keybd_event VK_C, 0, 0, 0 '按下C键<BR>Sleep 500 '延时500毫秒<BR>keybd_event VK_C, 0, KEYEVENTF_KEYUP, 0 '释放C键<BR>keybd_event VK_Ctrl, 0, KEYEVENTF_KEYUP, 0 '释放Ctrl键<BR>好
了,现在你可以试试是不是可以骗过目标程序了,这个函数对大部分的窗口程序都有效,可是仍然有一部分游戏对它产生的键盘事件熟视无睹,这时候,你就要用上
bScan这个参数了。一般的,bScan都传0,但是如果目标程序是一些DirectX游戏,那么你就需要正确使用这个参数传入扫描码,用了它可以产生
正确的硬件事件消息,以被游戏识别。这样的话,就可以写成这样:<BR>keybd_event VK_A, MapVirtualKey(VK_A, 0), 0, 0 '按下A键<BR>keybd_event VK_A, MapVirtualKey(VK_A, 0), KEYEVENTF_KEYUP, 0 '释放A键<BR>以上就是用keybd_event函数来模拟键盘事件。除了这个函数,SendInput函数也可以模拟全局键盘事件。SendInput可以直接把一条消息插入到消息队列中,算是比较底层的了。它的VB声明如下:<BR>Declare Function SendInput Lib "user32.dll" (ByVal nInputs As Long, pInputs As GENERALINPUT, ByVal cbSize As Long) As Long<BR>参数: <BR>nlnprts:定义plnputs指向的结构的数目。<BR>plnputs:指向INPUT结构数组的指针。每个结构代表插人到键盘或鼠标输入流中的一个事件。<BR>cbSize:定义INPUT结构的大小。若cbSize不是INPUT结构的大小,则函数调用失败。<BR>返回值:函数返回被成功地插人键盘或鼠标输入流中的事件的数目。若要获得更多的错误信息,可以调用GetlastError函数。<BR>备注:Sendlnput函数将INPUT结构中的事件顺序地插入键盘或鼠标的输入流中。这些事件与用户插入的(用鼠标或键盘)或调用keybd_event,mouse_event,或另外的Sendlnput插人的键盘或鼠标的输入流不兼容。<BR>嗯,这个函数用起来蛮复杂的,因为它的参数都是指针一类的东西。要用它来模拟键盘输入,先要构造一组数据结构,把你要模拟的键盘消息装进去,然后传给它。为了方便起见,把它做在一个过程里面,要用的时候直接调用好了,代码如下:<BR>Declare Function SendInput Lib "user32.dll" (ByVal nInputs As Long, pInputs As GENERALINPUT, ByVal cbSize As Long) As Long<BR>Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)<BR> Type GENERALINPUT<BR> dwType As Long<BR> xi(0 To 23) As Byte<BR> End Type</P>
<P> Type KEYBDINPUT<BR> wVk As Integer<BR> wScan As Integer<BR> dwFlags As Long<BR> time As Long<BR> dwExtraInfo As Long<BR> End Type</P>
<P>Const INPUT_KEYBOARD = 1</P>
<P>Sub MySendKey(bkey As Long)<BR>'参数bkey传入要模拟按键的虚拟码即可模拟按下指定键<BR>Dim GInput(0 To 1) As GENERALINPUT<BR>Dim KInput As KEYBDINPUT<BR> KInput.wVk = bkey '你要模拟的按键<BR> KInput.dwFlags = 0 '按下键标志<BR> GInput(0).dwType = INPUT_KEYBOARD<BR> CopyMemory GInput(0).xi(0), KInput, Len(KInput) '这个函数用来把内存中KInput的数据复制到GInput<BR> KInput.wVk = bkey <BR> KInput.dwFlags = KEYEVENTF_KEYUP ' 释放按键<BR> GInput(1).dwType = INPUT_KEYBOARD ' 表示该消息为键盘消息<BR> CopyMemory GInput(1).xi(0), KInput, Len(KInput)<BR>'以上工作把按下键和释放键共2条键盘消息加入到GInput数据结构中<BR> SendInput 2, GInput(0), Len(GInput(0)) '把GInput中存放的消息插入到消息列队<BR>End Sub</P>
<P>
除了以上这些,用全局钩子也可以模拟键盘消息。如果你对windows中消息钩子的用法已经有所了解,那么你可以通过设置一个全局HOOK来模拟键盘消
息,比如,你可以用WH_JOURNALPLAYBACK这个钩子来模拟按键。WH_JOURNALPLAYBACK是一个系统级的全局钩子,它和
WH_JOURNALRECORD的功能是相对的,常用它们来记录并回放键盘鼠标操作。WH_JOURNALRECORD钩子用来将键盘鼠标的操作忠实地
记录下来,记录下来的信息可以保存到文件中,而WH_JOURNALPLAYBACK则可以重现这些操作。当然亦可以单独使用
WH_JOURNALPLAYBACK来模拟键盘操作。你需要首先声明SetWindowsHookEx函数,它可以用来安装消息钩子:<BR>Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long,ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long<BR>先
安装WH_JOURNALPLAYBACK这个钩子,然后你需要自己写一个钩子函数,在系统调用它时,把你要模拟的事件传递给钩子参数lParam所指向
的EVENTMSG区域,就可以达到模拟按键的效果。不过用这个钩子模拟键盘事件有一个副作用,就是它会锁定真实的鼠标键盘,不过如果你就是想在模拟的时
候不会受真实键盘操作的干扰,那么用用它倒是个不错的主意。<BR>3.驱动级模拟</P>
<P> 如果上面的方法你都试过了,可是你发现目标程序却仍然顽固的不接受你模拟的消息,寒~~~~~~~~~还好,我还剩下最后一招,这就是驱动级模拟:直接读写键盘的硬件端口!<BR>
有一些使用DirectX接口的游戏程序,它们在读取键盘操作时绕过了windows的消息机制,而使用DirectInput.这是因为有些游戏对实时
性控制的要求比较高,比如赛车游戏,要求以最快速度响应键盘输入。而windows消息由于是队列形式的,消息在传递时会有不少延迟,有时1秒钟也就传递
十几条消息,这个速度达不到游戏的要求。而DirectInput则绕过了windows消息,直接与键盘驱动程序打交道,效率当然提高了不少。因此也就
造成,对这样的程序无论用PostMessage或者是keybd_event都不会有反应,因为这些函数都在较高层。对于这样的程序,只好用直接读写键
盘端口的方法来模拟硬件事件了。要用这个方法来模拟键盘,需要先了解一下键盘编程的相关知识。<BR> 在DOS时代,当用户按下或者放开一个键
时,就会产生一个键盘中断(如果键盘中断是允许的),这样程序会跳转到BIOS中的键盘中断处理程序去执行。打开windows的设备管理器,可以查看到
键盘控制器由两个端口控制。其中&H60是数据端口,可以读出键盘数据,而&H64是控制端口,用来发出控制信号。也就是,从&
H60号端口可以读此键盘的按键信息,当从这个端口读取一个字节,该字节的低7位就是按键的扫描码,而高1位则表示是按下键还是释放键。当按下键时,最高
位为0,称为通码,当释放键时,最高位为1,称为断码。既然从这个端口读数据可以获得按键信息,那么向这个端口写入数据就可以模拟按键了!用过
QbASIC4.5的朋友可能知道,QB中有个OUT命令可以向指定端口写入数据,而INP函数可以读取指定端口的数据。那我们先看看如果用QB该怎么写
代码:<BR>假如你想模拟按下一个键,这个键的扫描码为&H50,那就这样<BR>OUT &H64,&HD2 '把数据&HD2发送到&H64端口。这是一个KBC指令,表示将要向键盘写入数据<BR>OUT &H60,&H50 '把扫描码&H50发送到&H60端口,表示模拟按下扫描码为&H50的这个键<BR>那么要释放这个键呢?像这样,发送该键的断码:<BR>OUT &H64,&HD2 '把数据&HD2发送到&H64端口。这是一个KBC指令,表示将要向键盘写入数据<BR>OUT &H60,(&H50 OR &H80) '把扫描码&H50与数据&H80进行或运算,可以把它的高位置1,得到断码,表示释放这个键<BR>
好了,现在的问题就是在VB中如何向端口写入数据了。因为在windows中,普通应用程序是无权操作端口的,于是我们就需要一个驱动程序来帮助我们实
现。在这里我们可以使用一个组件WINIO来完成读写端口操作。什么是WINIO?WINIO是一个全免费的、无需注册的、含源程序的
WINDOWS2000端口操作驱动程序组件(可以到<A href="http://www.internals.com/"
target=_blank>http://www.internals.com/</A>上
去下载)。它不仅可以操作端口,还可以操作内存;不仅能在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函数声明:</P>
<P>Declare Function MapPhysToLin Lib "WinIo.dll" (ByVal PhysAddr As Long, ByVal PhysSize As Long, ByRef PhysMemHandle) As Long<BR>Declare Function UnmapPhysicalMemory Lib "WinIo.dll" (ByVal PhysMemHandle, ByVal LinAddr) As Boolean<BR>Declare Function GetPhysLong Lib "WinIo.dll" (ByVal PhysAddr As Long, ByRef PhysVal As Long) As Boolean<BR>Declare Function SetPhysLong Lib "WinIo.dll" (ByVal PhysAddr As Long, ByVal PhysVal As Long) As Boolean<BR>Declare Function GetPortVal Lib "WinIo.dll" (ByVal PortAddr As Integer, ByRef PortVal As Long, ByVal bSize As Byte) As Boolean<BR>Declare Function SetPortVal Lib "WinIo.dll" (ByVal PortAddr As Integer, ByVal PortVal As Long, ByVal bSize As Byte) As Boolean<BR>Declare Function InitializeWinIo Lib "WinIo.dll" () As Boolean<BR>Declare Function ShutdownWinIo Lib "WinIo.dll" () As Boolean<BR>Declare Function InstallWinIoDriver Lib "WinIo.dll" (ByVal DriverPath As String, ByVal Mode As Integer) As Boolean<BR>Declare Function RemoveWinIoDriver Lib "WinIo.dll" () As Boolean</P>
<P>' ------------------------------------以上是WINIO函数声明-------------------------------------------</P>
<P>Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long</P>
<P>'-----------------------------------以上是WIN32 API函数声明-----------------------------------------</P>
<P>再添加下面这个过程:<BR>Sub KBCWait4IBE() '等待键盘缓冲区为空<BR>Dim dwVal As Long<BR> Do<BR> GetPortVal &H64, dwVal, 1<BR>'这句表示从&H64端口读取一个字节并把读出的数据放到变量dwVal中<BR>'GetPortVal函数的用法是GetPortVal 端口号,存放读出数据的变量,读入的长度<BR> Loop While (dwVal And &H2)<BR>End Sub<BR>上面的是一个根据KBC规范写的过程,它的作用是在向键盘端口写入数据前等待一段时间,后面将会用到。<BR>然后再添加如下过程,这2个过程用来模拟按键:</P>
<P>Public Const KBC_KEY_CMD = &H64 '键盘命令端口<BR>Public Const KBC_KEY_DATA = &H60 '键盘数据端口</P>
<P>Sub MyKeyDown(ByVal vKeyCoad As Long) <BR>'这个用来模拟按下键,参数vKeyCoad传入按键的虚拟码<BR>Dim btScancode As Long<BR>btScancode = MapVirtualKey(vKeyCoad, 0)<BR> <BR> KBCWait4IBE '发送数据前应该先等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR>'SetPortVal函数用于向端口写入数据,它的用法是SetPortVal 端口号,欲写入的数据,写入数据的长度<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, btScancode, 1 '写入按键信息,按下键<BR> <BR>End Sub</P>
<P> Sub MyKeyUp(ByVal vKeyCoad As Long) <BR>'这个用来模拟释放键,参数vKeyCoad传入按键的虚拟码<BR>Dim btScancode As Long<BR>btScancode = MapVirtualKey(vKeyCoad, 0)<BR> <BR> KBCWait4IBE '等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, (btScancode Or &H80), 1 '写入按键信息,释放键</P>
<P>End Sub</P>
<P><BR>定义了上面的过程后,就可以用它来模拟键盘输入了。在窗体模块中添加一个定时器控件,然后加入以下代码:</P><BR>
<TABLE cellSpacing=1 cellPadding=4 width="80%" align=center>
<TBODY>
<TR>
<TD class=quote>Private Sub Form_Load()
<P> If InitializeWinIo = False Then <BR> '用InitializeWinIo函数加载驱动程序,如果成功会返回true,否则返回false<BR> MsgBox "驱动程序加载失败!"<BR> Unload Me<BR> End If<BR>Timer1.Interval=3000<BR>Timer1.Enabled=True<BR>End Sub</P>
<P>Private Sub Form_Unload(Cancel As Integer)<BR> ShutdownWinIo '程序结束时记得用ShutdownWinIo函数卸载驱动程序<BR>End Sub</P>
<P>Private Sub Timer1_Timer()<BR>Dim VK_A as Long = &H41 <BR>MyKeyDown VK_A <BR>MyKeyUp VK_A '模拟按下并释放A键<BR>End Sub<BR>[/quote]<BR>运行上面的程序,就会每隔3秒钟模拟按下一次A键,试试看,怎么样,是不是对所有程序都有效果了?<BR>需要注意的问题:<BR>要在VB的调试模式下使用WINIO,需要把那3个文件拷贝到VB的安装目录中。<BR>键盘上有些键属于扩展键(比如键盘上的方向键就是扩展键),对于扩展键不应该用上面的MyKeyDown和MyKeyUp过程来模拟,可以使用下面的2个过程来准确模拟扩展键:<BR>[quote]Sub MyKeyDownEx(ByVal vKeyCoad As Long) '模拟扩展键按下,参数vKeyCoad是扩展键的虚拟码<BR>Dim btScancode As Long<BR>btScancode = MapVirtualKey(vKeyCoad, 0)</P>
<P> KBCWait4IBE '等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, &HE0, 1 '写入扩展键标志信息<BR> <BR> <BR> KBCWait4IBE '等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, btScancode, 1 '写入按键信息,按下键<BR> <BR> <BR>End Sub</P>
<P><BR>Sub MyKeyUpEx(ByVal vKeyCoad As Long) '模拟扩展键弹起<BR>Dim btScancode As Long<BR>btScancode = MapVirtualKey(vKeyCoad, 0)</P>
<P> KBCWait4IBE '等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, &HE0, 1 '写入扩展键标志信息<BR> <BR> <BR> KBCWait4IBE '等待键盘缓冲区为空<BR> SetPortVal KBC_KEY_CMD, &HD2, 1 '发送键盘写入命令<BR> KBCWait4IBE<BR> SetPortVal KBC_KEY_DATA, (btScancode Or &H80), 1 '写入按键信息,释放键<BR> <BR>End Sub<BR>[/quote]<BR>还
应该注意的是,如果要从扩展键转换到普通键,那么普通键的KeyDown事件应该发送两次。也就是说,如果我想模拟先按下一个扩展键,再按下一个普通键,
那么就应该向端口发送两次该普通键被按下的信息。比如,我想模拟先按下左方向键,再按下空格键这个事件,由于左方向键是扩展键,空格键是普通键,那么流程
就应该是这样的:<BR>[quote]MyKeyDownEx VK_LEFT '按下左方向键<BR>Sleep 200 '延时200毫秒<BR>MyKeyUpEx VK_LEFT '释放左方向键</P>
<P>Sleep 500<BR>MyKeyDown VK_SPACE '按下空格键,注意要发送两次<BR>MyKeyDown VK_SPACE<BR>Sleep 200<BR>MyKeyUp VK_SPACE '释放空格键<BR></P></TD></TR></TBODY></TABLE><BR><BR>好了,相信到这里,你的模拟按键程序也就差不多了,测试一下,是不是很有效呢,嘿嘿~~~~<BR>WINIO组件的下载地址:<A
href="http://www.114vip.com.cn/download/winio.zip"
target=_blank>http://www.114vip.com.cn/download/winio.zip</A><BR>4.骨灰级模拟<BR> 方法3算是很底层的模拟了,我现在还没有发现有它模拟无效的程序。但是如果你用尽上面所有的方法,仍然无效的话,那么还有最后一个方法,绝对对任何程序都会有效,那就是:把键盘拿出来,老老实实地按下去吧。~~~~<BR><BR>我用WINIO在VB下模拟鼠标左键点击,具体代码如下:<BR>Private Sub XR()<BR> Dim Result As Boolean<BR> <BR> Result = SetPortVal(Val("&H64"), Val("&HD3"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> Sleep 100<BR> Result = SetPortVal(Val("&H64"), Val("&Hf4"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H09"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H00"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H00"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H08"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H00"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR> <BR> Result = SetPortVal(Val("&H60"), Val("&H00"), 1)<BR> <BR> If (Result = False) Then<BR> MsgBox "Whoops ! There is a problem with SetPortByte.", vbOKOnly + vbCritical, "VBDumpPort32"<BR> Unload FrmVBDumpPort32<BR> End If<BR>End Sub
<P class="right articalinfo">发表于 @ <A title=permalink
href="http://blog.csdn.net/aqbeyond/articles/1553055.aspx">2007年04月05日
16:01:00</A>|<A title=评论
href="http://blog.csdn.net/aqbeyond/articles/1553055.aspx#FeedBack">评论(<SPAN
id=FeedbackCount_1553055>loading...</SPAN>
<SCRIPT type=text/javascript>AddFeedbackCountStack("1553055")</SCRIPT>
)</A>|<A title=编辑
href="http://writeblog.csdn.net/PostEdit.aspx?entryId=1553055">编辑</A></P><SPAN
id=Post.ascx_ViewPost_PreviousAndNextEntriesDown>
<H3> | </H3></SPAN></DIV>
<DIV id=Post.ascx_TagAd_palTagAd>
<DIV class=tagadfornews id=csdn_tag_adstyle></DIV></DIV></DIV>
<DIV class=commentslist><SPAN id=Anthem_Post.ascx_Comments_ltlComments__><SPAN
id=Post.ascx_Comments_ltlComments>
<DIV id=commentslist>
<H3>评论:没有评论。</H3></DIV></SPAN></SPAN></DIV>
<DIV class=spacecommment>
<DIV id=Anthem_Post.ascx_PostComment_CommentUpdatePanel__>
<DIV id=Post.ascx_PostComment_CommentUpdatePanel>
<FIELDSET><LEGEND>发表评论</LEGEND>
<UL>
<LI>姓 名:<INPUT id=Post.ascx_PostComment_tbName maxLength=32
size=40 name=Post.ascx:PostComment:tbName><SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -