找回密码
 加入
搜索
查看: 21084|回复: 18

[AU3基础] PostMessage到底能不能发送组合键?

  [复制链接]
发表于 2009-5-21 07:49:54 | 显示全部楼层 |阅读模式
最近在写一个向指定窗口发送按键的UDF,打算用PostMessage完全实现Send函数所有功能。但是被组合键郁闷到了。
比如发送大写字母A,应该是先WM_KEYDOWN一次VK_SHIFT,再WM_KEYDOWN一次VK_A,最后WM_KEYUP释放两个键。但是最终结果,窗口只出现一个小写字母a。也就是说,窗口根本不管之前发送的VK_SHIFT。
用Spy++查看键盘消息,发现手动按键和程序发送一模一样(见下)。就是结果不一样。。。
google一下“PostMessage 组合键”,发现csdn,看雪,vbgood几个地方早有人讨论这个问题,结论是PostMessage按键时,窗口是直接读取当前VK_SHIFT状态,而不管之前是否收到VK_SHIFT的WM_KEYDOWN消息。解决方法有几个。一是keybd_event(SendInput,或者au3的Send也行)先发送一个VK_SHIFT按下消息,再发送按键,缺点是这会影响到同时运行的别的程序。还有更复杂的,hook几个返回键盘状态的api,让它们返回VK_SHIFT已被按下的假象,缺点就不用说了,太复杂,从效率来说还不如直接Send。
没信心了,现在在尝试WM_HOTKEY。如果有朋友也研究过这个问题,请指点一下。

Spy++拦截到的消息,模拟对象为记事本。WM_CHAR是自动产生的,可以看出结果不一样。
手动按键:
<00001> 00020470 P WM_KEYDOWN nVirtKey:VK_SHIFT cRepeat:1 ScanCode:2A fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000010 lParam:002A0001 time:1:23:59.968]
<00002> 00020470 P WM_KEYDOWN nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000041 lParam:001E0001 time:1:24:00.187]
<00003> 00020470 P WM_CHAR chCharCode:'0041' (65) cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000041 lParam:001E0001 time:1:24:00.187]
<00004> 00020470 P WM_KEYUP nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000041 lParam:C01E0001 time:1:24:00.328]
<00005> 00020470 P WM_KEYUP nVirtKey:VK_SHIFT cRepeat:1 ScanCode:2A fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000010 lParam:C02A0001 time:1:24:00.375]

程序发送:
<00006> 00020470 P WM_KEYDOWN nVirtKey:VK_SHIFT cRepeat:1 ScanCode:2A fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000010 lParam:002A0001 time:1:24:20.046]
<00007> 00020470 P WM_KEYDOWN nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000041 lParam:001E0001 time:1:24:20.062]
<00008> 00020470 P WM_CHAR chCharCode:'0061' (97) cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000061 lParam:001E0001 time:1:24:20.062]
<00009> 00020470 P WM_KEYUP nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000041 lParam:C01E0001 time:1:24:20.078]
<00010> 00020470 P WM_KEYUP nVirtKey:VK_SHIFT cRepeat:1 ScanCode:2A fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000010 lParam:C02A0001 time:1:24:20.093]
 楼主| 发表于 2009-5-21 13:28:17 | 显示全部楼层
http://blogs.msdn.com/oldnewthing/archive/2005/05/30/423202.aspx
You can't simulate keyboard input with PostMessage

汗~~~几天前搜索相关资料时就发现这篇文章了,只是英文基础太差,当时就没细看。今天又读了一遍,才明白这个问题无解。原来这几天我是在扮演阿汤哥,上演一出“不可能的任务”。。。
发表于 2009-5-22 01:55:04 | 显示全部楼层
额 不用封装了 有人写好了 直接用就是了
http://www.shynd.com/scripts/PostMessage_UDF.au3
至于组合键 你看下里面好像有shift的
 楼主| 发表于 2009-5-22 02:46:11 | 显示全部楼层
3# sxd


PostMessage_UDF写得太简单了。比如功能键,它只支持ENTER、TAB、ESC、F5、F12这5个,还有4个不兼容Send的光标键。组合键只考虑SHIFT,而且经测试是无效的。按键等待,它只用1而不用au3定义的SendKeyDelay等参数。
它上面的注释写明了Written by Shynd for use with DA,这个DA是Dark Ages,一款2D网游。所以它里面那些_MouseUseSpell等函数其实是针对Dark Ages游戏里操作设计的,我刚开始还想了大半天,搞不懂它为什么要去点547, 400这个坐标。里面可用的就是_MouseClick、_SendKeys、_SendText这3个,而且还都存在一些问题。
我就是看了PostMessage_UDF才想到写一个能完全实现Send函数所有功能的UDF。为此还创建了一个包含Send定义、按键虚拟码、扫描码对应关系的190项数组,完成了扩展键、ALT键、重复按键、发送ASC字符、保持CapsLock状态等一大堆杂七杂八的功能。只是没想到会卡在组合键上,最后才知道这是PostMessage做不到的事。。。白白浪费了3天时间啊。。。
发表于 2009-5-22 18:04:17 | 显示全部楼层
是的 那些他针对da用的 usespell的 就无视了

把你写好的发上来吧
 楼主| 发表于 2009-5-22 23:03:34 | 显示全部楼层
如果做不到组合键,能起的作用实在太小,废品就不发了。。。
发表于 2009-5-22 23:55:24 | 显示全部楼层
不小啊 后台按键 后台鼠标 都是游戏要用到的功能 加上后台找色 一个简单的辅助 就完成了
不过我用shynd写的那个UDF也能实现后台按键 鼠标 至于你说的 写的太简单 是说的哪方面呢?
 楼主| 发表于 2009-5-23 14:22:13 | 显示全部楼层
7# sxd

额,我还是放出代码吧。组合键暂时用Send发送组合键消息来代替。代码只是半成品,还没怎么优化,感觉太复杂了,我自己都头晕。。。
#include-once

#include <WinAPI.au3>


Func _WinMouseClick($hWnd, $sButton = "left", $iX = "", $iY = "", $iClicks = 1)
        Local $hUser32, $ilParam, $bButton, $bButtonDown, $bButtonUp
        Local $aPos, $iMode, $iDelay, $iDownDelay
        Local Const $MK_LBUTTON = 0x0001
        Local Const $MK_RBUTTON = 0x0002
        Local Const $MK_MBUTTON = 0x0010
        Local Const $WM_MOUSEMOVE = 0x0200
        Local Const $WM_LBUTTONDOWN = 0x0201
        Local Const $WM_LBUTTONUP = 0x0202
        Local Const $WM_RBUTTONDOWN = 0x0204
        Local Const $WM_RBUTTONUP = 0x0205
        Local Const $WM_MBUTTONDOWN = 0x0207
        Local Const $WM_MBUTTONUP = 0x0208

        If NOT IsHWnd($hWnd) OR NOT WinExists($hWnd) Then Return SetError(1, 0, 0)
        Switch StringLower($sButton)
                Case "left", ""
                        $bButton = $MK_LBUTTON
                        $bButtonDown = $WM_LBUTTONDOWN
                        $bButtonUp = $WM_LBUTTONUP
                Case "right"
                        $bButton = $MK_RBUTTON
                        $bButtonDown = $WM_RBUTTONDOWN
                        $bButtonUp = $WM_RBUTTONUP
                Case "middle"
                        $bButton = $MK_MBUTTON
                        $bButtonDown = $WM_MBUTTONDOWN
                        $bButtonUp = $WM_MBUTTONUP
                Case Else
                        Return SetError(2, 0, 0)
        EndSwitch
        If NOT StringIsInt($iX) OR NOT StringIsInt($iY) Then
                $iMode = Opt("MouseCoordMode", 0)
                $aPos = MouseGetPos()
                Opt("MouseCoordMode", $iMode)
                $iX = $aPos[0]
                $iY = $aPos[1]
        EndIf
        $ilParam = _WinAPI_MakeLong($iX, $iY)
        $iClicks = Int($iClicks)
        If $iClicks < 1 Then $iClicks = 1

        $iDelay = Opt("MouseClickDelay", 10)
        Opt("MouseClickDelay", $iDelay)
        $iDownDelay = Opt("MouseClickDownDelay", 10)
        Opt("MouseClickDownDelay", $iDownDelay)

        $hUser32 = DllOpen("user32.dll")
        If $hUser32 = -1 Then Return SetError(3, 0, 0)

        For $i = 1 To $iClicks
                _PostMessage($hWnd, $WM_MOUSEMOVE, 0, $ilParam, $hUser32)
                _PostMessage($hWnd, $bButtonDown, $bButton, $ilParam, $hUser32)
                Sleep($iDownDelay)
                _PostMessage($hWnd, $bButtonUp, $bButton, $ilParam, $hUser32)
                If $i < $iClicks Then Sleep($iDelay)
        Next

        DllClose($hUser32)
        Return 1
EndFunc   ;==>_WinMouseClick

Func _WinSendKeys($hWnd, $sKeys, $iMode = 1)
        Local $hUser32, $ilParam, $iVKCode, $iVSCCode, $iExtend, $iModifier = 0, $iIndex
        Local $iCapslock, $iDelay, $iDownDelay, $iKeyState, $fAltDown = False, $sRepeat, $sStr = ""
        Local Const $bAltDown = 0x20000000, $bRepeat = 0x40000000, $bKeyUp = 0x80000000
        Local Const $WM_KEYDOWN = 0x0100
        Local Const $WM_KEYUP = 0x0101
        Local Const $WM_CHAR = 0x0102
        Local Const $WM_SYSKEYDOWN = 0x0104
        Local Const $WM_SYSKEYUP = 0x0105
        Local Const $WM_HOTKEY = 0x0312

        If NOT IsHWnd($hWnd) OR NOT WinExists($hWnd) Then Return SetError(1, 0, 0)
        If $sKeys == "" Then Return SetError(2, 0, 0)
        If $iMode <> 2 Then $iMode = 1

        $hUser32 = DllOpen("user32.dll")
        If $hUser32 = -1 Then Return SetError(3, 0, 0)

        Local Const $aVKList = _MakeVKList()

        $iCapslock = Opt("SendCapslockMode", 1)
        $iVKCode = $aVKList[23][1]
        $iKeyState = BitAND(_GetKeyState($iVKCode, $hUser32), 1)
        $iCapslock = BitAND($iCapslock, $iKeyState)
        If $iCapslock = 1 Then
                Opt("SendCapslockMode", 0)
                Send("{CAPSLOCK off}")
                Opt("SendCapslockMode", 1)
        EndIf
        $iDelay = Opt("SendKeyDelay", 0)
        $iDownDelay = Opt("SendKeyDownDelay", 0)

        For $j = 1 To StringLen($sKeys)
                $sRepeat = "1"
                $sStr &= StringMid($sKeys, $j, 1)
                If StringLeft($sStr, 1) = "{" Then
                        If StringRight($sStr, 1) <> "}" Then ContinueLoop

                        If StringRegExp($sStr, "(?i)^{[[:graph:]]+ (\d+|down|up|on|off|toggle)}$") Then
                                $sRepeat = StringRegExpReplace($sStr, "^({[[:graph:]]+) (.+)(})$", "\2")
                                $sStr = StringRegExpReplace($sStr, "^({[[:graph:]]+) (.+)(})$", "\1\3")
                                $sRepeat = StringLower($sRepeat)
                        EndIf
                        If StringRegExp($sStr, "^{[^!#\+\^\{\}]}$") Then
                                $sStr = StringRegExpReplace($sStr, "^{(.)}$", "\1")
                        Else
                                $sStr = StringUpper($sStr)
                        EndIf
                        If $sStr = "{ASC}" AND NOT StringIsDigit($sRepeat) Then ContinueLoop
                EndIf

                For $iIndex = 0 To UBound($aVKList) - 1
                        If $sStr == $aVKList[$iIndex][0] Then ExitLoop
                Next
                $sStr = ""
                If $iIndex > UBound($aVKList) - 1 Then ContinueLoop

                $iModifier = BitOR($iModifier, $aVKList[$iIndex][4])
                Switch $iIndex
                        Case 0 To 3 ; modifier key
                                ContinueLoop
                        Case 4 To 13 ; modifier key down or up
                                $iModifier = 0
                                $sRepeat = StringRegExpReplace($aVKList[$iIndex][0], "^{[[:graph:]]+(DOWN|UP)}$", "\1")
                                $sRepeat = StringLower($sRepeat)
                        Case 14 ; send the ASCII characters
                                $iModifier = $aVKList[$iIndex][4]
                        Case 23, 71, 72 ; toggled key
                                If StringRegExp($sRepeat, "^on|off|toggle$") Then
                                        $sRepeat = " " & $sRepeat
                                Else
                                        $sRepeat = ""
                                EndIf
                        Case Else
                                If NOT StringRegExp($sRepeat, "^\d+|down|up$") Then $sRepeat = "1"
                EndSwitch

                If ($iModifier <> 0 AND $iMode = 1) OR $iIndex = 14 Then
                        If BitAND($iModifier, 8) Then Send("{LWINDOWN}")
                        If BitAND($iModifier, 4) Then Send("{SHIFTDOWN}")
                        If BitAND($iModifier, 2) Then Send("{CTRLDOWN}")
                        If BitAND($iModifier, 1) Then
                                Send("{ALTDOWN}")

                                $iVKCode = $aVKList[0][1]
                                $iVSCCode = $aVKList[0][2]
                                $ilParam = BitOR(_WinAPI_MakeLong(1, $iVSCCode), $bAltDown)
                                _PostMessage($hWnd, $WM_SYSKEYDOWN, $iVKCode, $ilParam, $hUser32)
                                $fAltDown = True
                        EndIf
                        Sleep($iDownDelay)
                EndIf

                Select
                        Case $iIndex = 14 ; send the ASCII characters
                                For $i = 1 To StringLen($sRepeat)
                                        $iIndex = Number(StringMid($sRepeat, $i, 1))
                                        $iIndex += 44
                                        $iVKCode = $aVKList[$iIndex][1]
                                        $iVSCCode = $aVKList[$iIndex][2]
                                        $iExtend = $aVKList[$iIndex][3]
                                        $ilParam = BitOR(_WinAPI_MakeLong(1, $iVSCCode), $iExtend, $bAltDown)

                                        _PostMessage($hWnd, $WM_SYSKEYDOWN, $iVKCode, $ilParam, $hUser32)
                                        Sleep($iDownDelay)
                                        _PostMessage($hWnd, $WM_SYSKEYUP, $iVKCode, BitOR($ilParam, $bRepeat, $bKeyUp), $hUser32)
                                        Sleep($iDelay)
                                Next
                        Case $iIndex = 23 OR $iIndex = 71 OR $iIndex = 72 ; toggled key
                                $sRepeat = StringTrimRight($aVKList[$iIndex][0], 1) & $sRepeat & "}"
                                Send($sRepeat)
                        Case $iModifier <> 0 AND $iMode = 2 ; post WM_HOTKEY message
                                $iVKCode = $aVKList[$iIndex][1]
                                $ilParam = _WinAPI_MakeLong($iModifier, $iVKCode)
                                If StringIsDigit($sRepeat) Then
                                        $iIndex = Number($sRepeat)
                                Else
                                        $iIndex = 1
                                EndIf

                                For $i = 1 To $iIndex
                                        _PostMessage($hWnd, $WM_HOTKEY, 0, $ilParam, $hUser32)
                                        Sleep($iDelay)
                                Next
                        Case Else
                                $iVKCode = $aVKList[$iIndex][1]
                                $iVSCCode = $aVKList[$iIndex][2]
                                $iExtend = $aVKList[$iIndex][3]
                                $ilParam = BitOR(_WinAPI_MakeLong(1, $iVSCCode), $iExtend)
                                If $fAltDown Then $ilParam = BitOR($ilParam, $bAltDown)
                                If StringIsDigit($sRepeat) Then
                                        $iIndex = Number($sRepeat)
                                Else
                                        $iIndex = 1
                                EndIf

                                For $i = 1 To $iIndex
                                        If $sRepeat <> "up" Then
                                                If $fAltDown Then
                                                        _PostMessage($hWnd, $WM_SYSKEYDOWN, $iVKCode, $ilParam, $hUser32)
                                                Else
                                                        _PostMessage($hWnd, $WM_KEYDOWN, $iVKCode, $ilParam, $hUser32)
                                                EndIf
                                                Sleep($iDownDelay)
                                        EndIf
                                        If $sRepeat <> "down" Then
                                                If $fAltDown Then
                                                        _PostMessage($hWnd, $WM_SYSKEYUP, $iVKCode, BitOR($ilParam, $bRepeat, $bKeyUp), $hUser32)
                                                Else
                                                        _PostMessage($hWnd, $WM_KEYUP, $iVKCode, BitOR($ilParam, $bRepeat, $bKeyUp), $hUser32)
                                                EndIf
                                                Sleep($iDelay)
                                        EndIf
                                Next
                EndSelect

                If ($iModifier <> 0 AND $iMode = 1) OR $iIndex = 14 Then
                        If BitAND($iModifier, 1) Then
                                $iVKCode = $aVKList[0][1]
                                $iVSCCode = $aVKList[0][2]
                                $ilParam = BitOR(_WinAPI_MakeLong(1, $iVSCCode), $bRepeat, $bKeyUp)
                                _PostMessage($hWnd, $WM_SYSKEYUP, $iVKCode, $ilParam, $hUser32)
                                $fAltDown = False

                                Send("{ALTUP}")
                        EndIf
                        If BitAND($iModifier, 2) Then Send("{CTRLUP}")
                        If BitAND($iModifier, 4) Then Send("{SHIFTUP}")
                        If BitAND($iModifier, 8) Then Send("{LWINUP}")
                        Sleep($iDownDelay)
                        $iModifier = 0
                EndIf
        Next

        Opt("SendKeyDelay", $iDelay)
        Opt("SendKeyDownDelay", $iDownDelay)
        If $iCapslock = 1 Then
                Opt("SendCapslockMode", 0)
                Send("{CAPSLOCK on}")
                Opt("SendCapslockMode", 1)
        EndIf

        DllClose($hUser32)
        Return 1
EndFunc   ;==>_WinSendKeys

Func _WinSendText($hWnd, $sText)
        Local $hUser32, $ilParam, $iVSCCode, $iDelay, $sChr, $iAsc, $iIndex
        Local Const $WM_CHAR = 0x0102

        If NOT IsHWnd($hWnd) OR NOT WinExists($hWnd) Then Return SetError(1, 0, 0)
        If $sText == "" Then Return SetError(2, 0, 0)

        $hUser32 = DllOpen("user32.dll")
        If $hUser32 = -1 Then Return SetError(3, 0, 0)

        Local Const $aVKList = _MakeVKList()

        $iDelay = Opt("SendKeyDelay", 5)
        Opt("SendKeyDelay", $iDelay)

        For $i = 1 To StringLen($sText)
                $sChr = StringMid($sText, $i, 1)
                $iAsc = Asc($sChr)
                If $iAsc < 32 OR $iAsc > 126 Then ContinueLoop

                If StringRegExp($sChr, "^[!#\+\^\{\}]$") Then $sChr = "{" & $sChr & "}"
                For $iIndex = 97 To UBound($aVKList) - 1
                        If $sChr == $aVKList[$iIndex][0] Then ExitLoop
                Next

                $iVSCCode = $aVKList[$iIndex][2]
                $ilParam = _WinAPI_MakeLong(1, $iVSCCode)
                _PostMessage($hWnd, $WM_CHAR, $iAsc, $ilParam, $hUser32)
                Sleep($iDelay)
        Next

        DllClose($hUser32)
        Return 1
EndFunc   ;==>_WinSendText

Func _MakeVKList()
        Local $hUser32, $sChar, $iVKCode, $iVSCCode, $iHiWord
        Local Const $MAPVK_VK_TO_VSC = 0
        Local Const $MAPVK_VSC_TO_VK = 1
        Local Const $bExtend = 0x1000000

        Local $aVKList[191][5] = [ _
                        ["!", 0x12, 0, 0, 1], _ ; MOD_ALT
                        ["+", 0x10, 0, 0, 4], _ ; MOD_SHIFT
                        ["^", 0x11, 0, 0, 2], _ ; MOD_CONTROL
                        ["#", 0x5B, 0, 0, 8], _ ; MOD_WIN
                        ["{ALTDOWN}", 0x12], _ ; VK_MENU
                        ["{ALTUP}", 0x12], _ ; VK_MENU
                        ["{SHIFTDOWN}", 0x10], _ ; VK_SHIFT
                        ["{SHIFTUP}", 0x10], _ ; VK_SHIFT
                        ["{CTRLDOWN}", 0x11], _ ; VK_CONTROL
                        ["{CTRLUP}", 0x11], _ ; VK_CONTROL
                        ["{LWINDOWN}", 0x5B, 0, $bExtend], _ ; VK_LWIN
                        ["{LWINUP}", 0x5B, 0, $bExtend], _ ; VK_LWIN
                        ["{RWINDOWN}", 0x5C, 0, $bExtend], _ ; VK_RWIN
                        ["{RWINUP}", 0x5C, 0, $bExtend], _ ; VK_RWIN
                        ["{ASC}", 0x12, 0, 0, 1], _ ; VK_MENU
                        ["{BREAK}", 0x03, 0, $bExtend, 2], _ ; VK_CANCEL
                        ["{BACKSPACE}", 0x08], _ ; VK_BACK
                        ["{BS}", 0x08], _ ; VK_BACK
                        ["{TAB}", 0x09], _ ; VK_TAB
                        ["{ENTER}", 0x0D], _ ; VK_RETURN
                        ["{NUMPADENTER}", 0x0D, 0, $bExtend], _ ; VK_RETURN
                        ["{ALT}", 0x12], _ ; VK_MENU
                        ["{PAUSE}", 0x13], _ ; VK_PAUSE
                        ["{CAPSLOCK}", 0x14], _ ; VK_CAPITAL
                        ["{ESCAPE}", 0x1B], _ ; VK_ESCAPE
                        ["{ESC}", 0x1B], _ ; VK_ESCAPE
                        ["{SPACE}", 0x20], _ ; VK_SPACE
                        ["{PGUP}", 0x21, 0, $bExtend], _ ; VK_PRIOR
                        ["{PGDN}", 0x22, 0, $bExtend], _ ; VK_NEXT
                        ["{END}", 0x23, 0, $bExtend], _ ; VK_END
                        ["{HOME}", 0x24, 0, $bExtend], _ ; VK_HOME
                        ["{LEFT}", 0x25, 0, $bExtend], _ ; VK_LEFT
                        ["{UP}", 0x26, 0, $bExtend], _ ; VK_UP
                        ["{RIGHT}", 0x27, 0, $bExtend], _ ; VK_RIGHT
                        ["{DOWN}", 0x28, 0, $bExtend], _ ; VK_DOWN
                        ["{PRINTSCREEN}", 0x2C], _ ; VK_SNAPSHOT
                        ["{INSERT}", 0x2D, 0, $bExtend], _ ; VK_INSERT
                        ["{INS}", 0x2D, 0, $bExtend], _ ; VK_INSERT
                        ["{DELETE}", 0x2E, 0, $bExtend], _ ; VK_DELETE
                        ["{DEL}", 0x2E, 0, $bExtend], _ ; VK_DELETE
                        ["{LWIN}", 0x5B, 0, $bExtend], _ ; VK_LWIN
                        ["{RWIN}", 0x5C, 0, $bExtend], _ ; VK_RWIN
                        ["{APPSKEY}", 0x5D, 0, $bExtend], _ ; VK_APPS
                        ["{SLEEP}", 0x5F], _ ; VK_SLEEP
                        ["{NUMPAD0}", 0x60], _ ; VK_NUMPAD0
                        ["{NUMPAD1}", 0x61], _ ; VK_NUMPAD1
                        ["{NUMPAD2}", 0x62], _ ; VK_NUMPAD2
                        ["{NUMPAD3}", 0x63], _ ; VK_NUMPAD3
                        ["{NUMPAD4}", 0x64], _ ; VK_NUMPAD4
                        ["{NUMPAD5}", 0x65], _ ; VK_NUMPAD5
                        ["{NUMPAD6}", 0x66], _ ; VK_NUMPAD6
                        ["{NUMPAD7}", 0x67], _ ; VK_NUMPAD7
                        ["{NUMPAD8}", 0x68], _ ; VK_NUMPAD8
                        ["{NUMPAD9}", 0x69], _ ; VK_NUMPAD9
                        ["{NUMPADMULT}", 0x6A], _ ; VK_MULTIPLY
                        ["{NUMPADADD}", 0x6B], _ ; VK_ADD
                        ["{NUMPADSUB}", 0x6D], _ ; VK_SUBTRACT
                        ["{NUMPADDOT}", 0x6E], _ ; VK_DECIMAL
                        ["{NUMPADDIV}", 0x6F, 0, $bExtend], _ ; VK_DIVIDE
                        ["{F1}", 0x70], _ ; VK_F1
                        ["{F2}", 0x71], _ ; VK_F2
                        ["{F3}", 0x72], _ ; VK_F3
                        ["{F4}", 0x73], _ ; VK_F4
                        ["{F5}", 0x74], _ ; VK_F5
                        ["{F6}", 0x75], _ ; VK_F6
                        ["{F7}", 0x76], _ ; VK_F7
                        ["{F8}", 0x77], _ ; VK_F8
                        ["{F9}", 0x78], _ ; VK_F9
                        ["{F10}", 0x79], _ ; VK_F10
                        ["{F11}", 0x7A], _ ; VK_F11
                        ["{F12}", 0x7B], _ ; VK_F12
                        ["{NUMLOCK}", 0x90, 0, $bExtend], _ ; VK_NUMLOCK
                        ["{SCROLLLOCK}", 0x91], _ ; VK_SCROLL
                        ["{LSHIFT}", 0xA0], _ ; VK_LSHIFT
                        ["{RSHIFT}", 0xA1], _ ; VK_RSHIFT
                        ["{LCTRL}", 0xA2], _ ; VK_LCONTROL
                        ["{RCTRL}", 0xA3, 0, $bExtend], _ ; VK_RCONTROL
                        ["{LALT}", 0xA4], _ ; VK_LMENU
                        ["{RALT}", 0xA5, 0, $bExtend], _ ; VK_RMENU
                        ["{BROWSER_BACK}", 0xA6], _ ; VK_BROWSER_BACK
                        ["{BROWSER_FORWARD}", 0xA7], _ ; VK_BROWSER_FORWARD
                        ["{BROWSER_REFRESH}", 0xA8], _ ; VK_BROWSER_REFRESH
                        ["{BROWSER_STOP}", 0xA9], _ ; VK_BROWSER_STOP
                        ["{BROWSER_SEARCH}", 0xAA], _ ; VK_BROWSER_SEARCH
                        ["{BROWSER_FAVORITES}", 0xAB], _ ; VK_BROWSER_FAVORITES
                        ["{BROWSER_HOME}", 0xAC], _ ; VK_BROWSER_HOME
                        ["{VOLUME_MUTE}", 0xAD], _ ; VK_VOLUME_MUTE
                        ["{VOLUME_DOWN}", 0xAE], _ ; VK_VOLUME_DOWN
                        ["{VOLUME_UP}", 0xAF], _ ; VK_VOLUME_UP
                        ["{MEDIA_NEXT}", 0xB0], _ ; VK_MEDIA_NEXT_TRACK
                        ["{MEDIA_PREV}", 0xB1], _ ; VK_MEDIA_PREV_TRACK
                        ["{MEDIA_STOP}", 0xB2], _ ; VK_MEDIA_STOP
                        ["{MEDIA_PLAY_PAUSE}", 0xB3], _ ; VK_MEDIA_PLAY_PAUSE
                        ["{LAUNCH_MAIL}", 0xB4], _ ; VK_LAUNCH_MAIL
                        ["{LAUNCH_MEDIA}", 0xB5], _ ; VK_LAUNCH_MEDIA_SELECT
                        ["{LAUNCH_APP1}", 0xB6], _ ; VK_LAUNCH_APP1
                        ["{LAUNCH_APP2}", 0xB7]] ; VK_LAUNCH_APP2

        $hUser32 = DllOpen("user32.dll")
        If $hUser32 = -1 Then Return SetError(1, 0, 0)

        For $i = 0 To 96
                $aVKList[$i][2] = _MapVirtualKey($aVKList[$i][1], $MAPVK_VK_TO_VSC, $hUser32)
                $aVKList[$i][3] = BitOR($aVKList[$i][3], 0)
                $aVKList[$i][4] = BitOR($aVKList[$i][4], 0)
        Next
        $aVKList[22][2] = $aVKList[71][2] ; PAUSE key scan code is equal to NUM LOCK key

        For $i = 33 To 126 ; printing characters, excluding space
                $iVSCCode = _OemKeyScan($i, $hUser32)
                If $iVSCCode = -1 Then ContinueLoop
                $iHiWord = _WinAPI_HiWord($iVSCCode)
                $iVSCCode = _WinAPI_LoWord($iVSCCode)

                $iVKCode = _MapVirtualKey($iVSCCode, $MAPVK_VSC_TO_VK, $hUser32)
                If $iVKCode = 0 Then ContinueLoop

                $sChar = Chr($i)
                If StringRegExp($sChar, "^[!#\+\^\{\}]$") Then $sChar = "{" & $sChar & "}"
                $aVKList[$i - 33 + 97][0] = $sChar
                $aVKList[$i - 33 + 97][1] = $iVKCode
                $aVKList[$i - 33 + 97][2] = $iVSCCode
                $aVKList[$i - 33 + 97][3] = 0
                $aVKList[$i - 33 + 97][4] = 0
                If BitAND($iHiWord, 1) Then $aVKList[$i - 33 + 97][4] = BitOR($aVKList[$i - 33 + 97][4], 4) ; SHIFT key is pressed
                If BitAND($iHiWord, 2) Then $aVKList[$i - 33 + 97][4] = BitOR($aVKList[$i - 33 + 97][4], 2) ; CTRL key is pressed
                If BitAND($iHiWord, 4) Then $aVKList[$i - 33 + 97][4] = BitOR($aVKList[$i - 33 + 97][4], 1) ; ALT key is pressed
        Next

        DllClose($hUser32)
        Return $aVKList
EndFunc   ;==>_MakeVKList


Func _PostMessage($hWnd, $iMsg, $iwParam, $ilParam, $vUser32 = "user32.dll")
        Local $aResult

        $aResult = DllCall($vUser32, "int", "PostMessage", "hwnd", $hWnd, "uint", $iMsg, "wparam", $iwParam, "lparam", $ilParam)
        If @error Then Return SetError(@error, 0, 0)
        Return $aResult[0]
EndFunc   ;==>_PostMessage

Func _MapVirtualKey($iuCode, $iuMapType = 0, $vUser32 = "user32.dll")
        Local $aResult

        $aResult = DllCall($vUser32, "uint", "MapVirtualKey", "uint", $iuCode, "uint", $iuMapType)
        If @error Then Return SetError(@error, 0, 0)
        Return $aResult[0]
EndFunc   ;==>_MapVirtualKey

Func _OemKeyScan($iwOemChar, $vUser32 = "user32.dll")
        Local $aResult

        $aResult = DllCall($vUser32, "dword", "OemKeyScan", "short", $iwOemChar)
        If @error Then Return SetError(@error, 0, 0)
        Return $aResult[0]
EndFunc   ;==>_OemKeyScan

Func _GetKeyState($inVirtKey, $vUser32 = "user32.dll")
        Local $aResult

        $aResult = DllCall($vUser32, "short", "GetKeyState", "int", $inVirtKey)
        If @error Then Return SetError(@error, 0, 0)
        Return $aResult[0]
EndFunc   ;==>_GetKeyState

评分

参与人数 1贡献 +5 收起 理由
lynfr8 + 5

查看全部评分

发表于 2009-5-23 18:45:19 | 显示全部楼层
有个问题  我用postmessage的时候 无法实现双击 click设置2的话 只是快速点2下 无法形成双击
如何解决呢
 楼主| 发表于 2009-5-23 19:28:55 | 显示全部楼层
本帖最后由 sensel 于 2009-5-23 19:38 编辑

9# sxd

确实如此。有一个折衷的办法,直接发送WM_LBUTTONDBLCLK之类的消息产生双击。
但是如果$iClicks = 3该怎么办呢?是发送一个双击再跟一个单击,还是直接发送3个单击?
PostMessage限制实在太多了,我总觉得不实用。
 楼主| 发表于 2009-5-23 20:22:30 | 显示全部楼层
改了一下_WinMouseClick,用BUTTONDBLCLK发送双击。使用先双击再单击的方法。
Func _WinMouseClick($hWnd, $sButton = "left", $iX = "", $iY = "", $iClicks = 1)
        Local $hUser32, $ilParam, $bButton, $bButtonDown, $bButtonUp, $bButtonDblClk
        Local $aPos, $iMode, $iDelay, $iDownDelay
        Local Const $MK_LBUTTON = 0x0001
        Local Const $MK_RBUTTON = 0x0002
        Local Const $MK_MBUTTON = 0x0010
        Local Const $WM_MOUSEMOVE = 0x0200
        Local Const $WM_LBUTTONDOWN = 0x0201
        Local Const $WM_LBUTTONUP = 0x0202
        Local Const $WM_LBUTTONDBLCLK = 0x0203
        Local Const $WM_RBUTTONDOWN = 0x0204
        Local Const $WM_RBUTTONUP = 0x0205
        Local Const $WM_RBUTTONDBLCLK = 0x0206
        Local Const $WM_MBUTTONDOWN = 0x0207
        Local Const $WM_MBUTTONUP = 0x0208
        Local Const $WM_MBUTTONDBLCLK = 0x0209

        If NOT IsHWnd($hWnd) OR NOT WinExists($hWnd) Then Return SetError(1, 0, 0)
        Switch StringLower($sButton)
                Case "left", ""
                        $bButton = $MK_LBUTTON
                        $bButtonDown = $WM_LBUTTONDOWN
                        $bButtonUp = $WM_LBUTTONUP
                        $bButtonDblClk = $WM_LBUTTONDBLCLK
                Case "right"
                        $bButton = $MK_RBUTTON
                        $bButtonDown = $WM_RBUTTONDOWN
                        $bButtonUp = $WM_RBUTTONUP
                        $bButtonDblClk = $WM_RBUTTONDBLCLK
                Case "middle"
                        $bButton = $MK_MBUTTON
                        $bButtonDown = $WM_MBUTTONDOWN
                        $bButtonUp = $WM_MBUTTONUP
                        $bButtonDblClk = $WM_MBUTTONDBLCLK
                Case Else
                        Return SetError(2, 0, 0)
        EndSwitch
        If NOT StringIsInt($iX) OR NOT StringIsInt($iY) Then
                $iMode = Opt("MouseCoordMode", 0)
                $aPos = MouseGetPos()
                Opt("MouseCoordMode", $iMode)
                $iX = $aPos[0]
                $iY = $aPos[1]
        EndIf
        $ilParam = _WinAPI_MakeLong($iX, $iY)
        $iClicks = Int($iClicks)
        If $iClicks < 1 Then $iClicks = 1

        $iDelay = Opt("MouseClickDelay", 10)
        Opt("MouseClickDelay", $iDelay)
        $iDownDelay = Opt("MouseClickDownDelay", 10)
        Opt("MouseClickDownDelay", $iDownDelay)

        $hUser32 = DllOpen("user32.dll")
        If $hUser32 = -1 Then Return SetError(3, 0, 0)

        For $i = 1 To Int($iClicks / 2)
                _PostMessage($hWnd, $WM_MOUSEMOVE, 0, $ilParam, $hUser32)
                _PostMessage($hWnd, $bButtonDblClk, $bButton, $ilParam, $hUser32)
                Sleep($iDelay)
        Next
        If Mod($iClicks, 2) Then
                _PostMessage($hWnd, $WM_MOUSEMOVE, 0, $ilParam, $hUser32)
                _PostMessage($hWnd, $bButtonDown, $bButton, $ilParam, $hUser32)
                Sleep($iDownDelay)
                _PostMessage($hWnd, $bButtonUp, $bButton, $ilParam, $hUser32)
        EndIf

        DllClose($hUser32)
        Return 1
EndFunc   ;==>_WinMouseClick
发表于 2009-5-24 02:18:00 | 显示全部楼层
au3 往游戏辅助 外挂 方面发展下 还是有必要的
希望可以研究下 后台找图 找色
发表于 2010-5-25 01:35:23 | 显示全部楼层
正在研究QQ农场的后台操作,这个flash的类句柄怎么获得啊?
发表于 2010-5-25 20:07:43 | 显示全部楼层
alt+组合键可以吗?
发表于 2010-5-25 22:52:10 | 显示全部楼层
人气太淡了。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-23 07:52 , Processed in 0.083636 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表