佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

楼主: BillyG

四个 VB 问题~

[复制链接]
发表于 1-6-2006 10:17 AM | 显示全部楼层

回复 #20 BillyG 的帖子

呵呵。。。

AttachThreadInput好像用不到。。。我试了很久。。都没成功。。。
别方法应该有了。。。不过我还在研究中。。。

另外,你有试过GetKeyState和GetAsyncKeyState吗?

至于,把东西放在systray嘛。。。有时间时再告诉你。。。

你是在写什么外挂?游戏外挂?
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 1-6-2006 02:31 PM | 显示全部楼层

回复 #21 meemee 的帖子

嗯 , 我在写 “海天英雄传” 的外挂(按键模拟--不算外挂)目前用着 按键精灵(QuickMacro) 和 按键大师(ScriptExpert)。

现在最主要的问题是,我上面给的 example 里的 Form_KeyDown function 只有在form1 是 active 时才会“听” key-event,当 form1 inactive 时便不会“听” key-event。

在 msdn search 到 brackgroundworker 的东东,但还不大明白它怎样运作的。

再一个问题便是, 我的 mouseclick() [#16 楼帖] 的运作是全屏的,不是限于 test_DC。 而我要的是局限于 test_DC 的。因为有打算多开,所以会有超过一个“海天英雄转” window 所以必修锁定个别 window。这也是我前面用 findwindow() 的原因了。

抓色能用 hDC,不知 mouseclick/setcursorpos 是不是也能用 hDC 呢?


GetKeyState和GetAsyncKeyState。。。 我search search 看。。

[ 本帖最后由 BillyG 于 1-6-2006 02:42 PM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 1-6-2006 08:15 PM | 显示全部楼层
meemee,

刚刚发现 SetCursorPos 是全屏运作的。。

找到下面的 code(ScreenToClient/ClientToScreen) 虽然不完全是我要的不过接近了
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Private Type POINTAPI
    x As Long
    y As Long
End Type

Sub MoveMouse(x As Single, y As Single)
    Dim pt As POINTAPI
    pt.x = x
    pt.y = y
    ClientToScreen hwnd, pt
    SetCursorPos pt.x, pt.y
End Sub
回复

使用道具 举报

 楼主| 发表于 10-6-2006 12:07 AM | 显示全部楼层
至 meemee,

谢谢你的指点。

问题2 已解决。 用 GetAsyncKeyState 解决了。所以 systemtray 不需要了。

谢谢你,
这个帖让我学到了

findwindow,
getdc,
GetWindowDC,
setcursorpos,
getcursorpos,
doevents,
Form_Activate() 的相关次序,
FindWindowEx,
ReleaseDC,
SendKeys,
SendInput,
brackgroundworker,
ScreenToClient/ClientToScreen。。。
等等。。

从我发帖时对 VB API 的一无所知到现在有大致上的了解。
我的 program 基本上已能运作了。现在在除 bug 和优化,因为运作起来有些慢。

现在就只剩 setcursorpos/getcursorpos 从屏幕换去窗体 或找替代 systax.
有问题的话我会发新帖问的。
谢谢。
回复

使用道具 举报

发表于 10-6-2006 10:17 AM | 显示全部楼层
原帖由 BillyG 于 10-6-2006 12:07 AM 发表
至 meemee,

谢谢你的指点。

问题2 已解决。 用 GetAsyncKeyState 解决了。所以 systemtray 不需要了。

谢谢你,
这个帖让我学到了

findwindow,
getdc,
GetWindowDC,
setcursorpos,
getcurso ...


呵呵。。。这些都是你认真学习的结果。。。
我只教你简单的syntax和捉一些虫吧了,也没帮到什么,都是你自己努力的结果。。。

除了,GetAsyncKeyState,你可以用setwindowshookex,只不过setwindowshookex太过高难度了,所以没教你。。。因为,需要制作dll,把dll里的function放进memory,然后找出它的pointer,再作“键盘钩子”,钩去那个function pointer。。。我自己也正在试着写,不过出现非常奇怪的问题。。。

程序运行得慢,应该是调用太多api,还有因为你做了infinite loop,而且一直用GetAsyncKeyState pull着你的hardware。。。

有一个忧化的方式可以试试,就是把所有用到的api写成MIDL,然后compile成type library。
网上也有现成的type library,如果我没记错。。。Bruce McKinney应该有写过,你可以去找找看,或去这个网站下载:
http://brucem.mystarband.net/mckinney2a.htm

[ 本帖最后由 meemee 于 10-6-2006 10:24 AM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 13-6-2006 07:11 AM | 显示全部楼层
search 了一下 setwindowshookex
看了注释 再回看你的帖 应该明白了功能运作。
就是把 键盘“功能”(个别按键本应该有的function)从缓存(memory)里给摒除/挡掉不让运作。

是咯,我用了一个 stand alone 的 timer 每秒跑一次 GetAsyncKeyStat 和 调用了 10个 api

去了 Bruce McKinney 的站以下很长要慢慢看,先收做 favorite.谢谢了。


这里有个问题,

在 VB 里一个 loop 通常用时几秒?1/1000? 或更快?
我想改写我的 delay sub function. 看能不能加快一些些速度。
Sub Delay(pdblSeconds As Integer)
' delay for x secodns
' this sub used very little CPU resouces
    Const OneSecond As Double = 1# / (1440# * 60#)
    Dim dblWaitUntil As Date
    dblWaitUntil = Now + OneSecond * pdblSeconds
    Do Until Now > dblWaitUntil '<--- 想改掉这个
        DoEvents ' Allow windows message to be processed
    Loop
End Sub
回复

使用道具 举报

Follow Us
发表于 13-6-2006 11:18 AM | 显示全部楼层
原帖由 BillyG 于 13-6-2006 07:11 AM 发表
search 了一下 setwindowshookex
看了注释 再回看你的帖 应该明白了功能运作。
就是把 键盘“功能”(个别按键本应该有的function)从缓存(memory)里给摒除/挡掉不让运作。

是咯,我用了一个 stand alone 的 t ...


关于setwindowshookex,你可以看看我post的贴:

一个奇怪的DLL问题

在 VB 里一个 loop 通常用时几秒?1/1000? 或更快?
呵呵,不知道呦。。。因为它是跟CPU cycle和machine code关连,所以算不出。。。

不过,你可以用Timer来比较。。。

Sub Delay(pdblSeconds As Integer)
' delay for x secodns
' this sub used very little CPU resouces

        Dim MyTimer as single
        MyTimer = Timer + pdblSeconds
               
        Do while Timer < MyTimer
                DoEvents ' Allow windows message to be processed
        Loop
End Sub


以上的coding我还没compile过,如果有bug的话,你自己试试debug。
回复

使用道具 举报

 楼主| 发表于 14-6-2006 06:50 AM | 显示全部楼层
有,我复完26楼的 post 后就发现你的帖,看了。。 但还没看出 program flow ,需要多看几遍。

好的, 我会试试 27 楼的方法。谢谢。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 15-6-2006 06:40 AM | 显示全部楼层
to meemee,

27 楼 方法有用,速度没问题了。

不过发现有新问题,下面的 code 运行是,它只 print 了 " call 1 0 " 然后就没动静直到我在 form1 上面 click 一下它才会继续不停的 print
" call 1 1 "
" call 1 2 "
" call 1 3 "
.....

为舍么它会在 " call 1 0 " 后停下来等我去 click form1?(我猜想问题出在 print " call 1 0 " 后的 delay 那里, 可里不出头绪来。)


Dim btnDown As Boolean
Dim u As Integer

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Private Sub Timer1_Timer()
    btnDown = GetAsyncKeyState(vbKeyF10)
    If btnDown = True Then
        Call process
    End If
End Sub

Sub Delay(pdblSeconds As Integer)
    Dim MyTimer As Single
    MyTimer = Timer + (pdblSeconds)
    Do While Timer < MyTimer
        DoEvents
    Loop
MyExit3:
End Sub

Sub process()
loop1:
    btnDown = GetAsyncKeyState(vbKeyF12)
    If btnDown = True Then
        Debug.Print "stop by user in loop 1"
        MsgBox "stoped in loop 1"
        GoTo exit1
    End If
    Call a
        Debug.Print "call 1  " & u
        u = u + 1
        Call
    Delay 1
    DoEvents
    GoTo loop1
exit1:
End Sub

Sub a()
End Sub

Sub b()
End Sub
回复

使用道具 举报

发表于 16-6-2006 08:40 AM | 显示全部楼层
应该是两个GetAsyncKeyState和DoEvents在做怪。。。

我发现到,其中一个GetAsyncKeyState拿掉或者那两个DoEvents拿掉,就会正常,不过我还没想到需要如何解决。。。
回复

使用道具 举报

发表于 19-6-2006 04:05 PM | 显示全部楼层

回复 #29 BillyG 的帖子

真正停顿的地方是在DoEvents那里。。。应该是DoEvents内部的结构导致的问题。。。后来我编写一个DoEvents的function想解决掉这个问题。。。结果,更加糟糕。。。

暂时找到的解决方法是把,form deactivated掉,就是把别的window/form或desktop window active起来(用SetForegroundWindow),然后再执行DoEvents,之后再把form activate回来。。。
在DoEvents之前deactivate,在DoEvents之后activate回来。。。这个deactivate和activate的步骤应该执行一次就够了。。。
回复

使用道具 举报

 楼主| 发表于 23-6-2006 12:10 PM | 显示全部楼层

回复 #31 meemee 的帖子

meemee,

我回来了,
好几天没上来看看了。
这个问题对我的 program 影响不大,只是无意间发现好奇罢了。我的 program 多数时间是 deactivate(后台运作)的。

这几天找 SetCursorPos 的替代方法 找到一个因该能用,但不肯定.

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long


SendMessage function 好像能模拟 mouse click 和 keystroke。

sendmessage function 所接收的 parameter 里的 的 wMsg, wParam, lParam 找不大有。
所以,不大明白该怎用。

meemee, 能帮我解释一点点关于 sendmessage function 吗?
1.)sendmessage function 是不是能锁定 mouse click 和 keystroke 模拟在一个window 里?(setcursorpos 不真正能, setcursorpos 是用屏幕来算的)

2.)WM_LBUTTONDBLCLK vs WM_LBUTTONDOWN + WM_LBUTTONUP

EM_ , 等于 舍么 意思?

还有那些 简单的 wMsg 能用的?

wParam 有哪些?

3.)sendmessage function 能抓色吗?

这里有哪些 wMsg parameter 但没 wParam 。
http://www.csee.umbc.edu/~squire/download/WinUser.h

谢谢。
回复

使用道具 举报

发表于 26-6-2006 05:36 PM | 显示全部楼层

回复 #32 BillyG 的帖子

1,
对,SendMessage可以用来模拟keyboard和mouse(但是,你的cursor是不会动)。我有试过模拟一个flash游戏的mouse click。那个flash有需要在指定的时间按,停止timer。但是,我每次玩时,timer都不能在指定的时间停,于是,我就作弊,用vb写program,叫program帮我click。。。有时间时我再把program放上,给你参考。

2,
这些东西,我很少去上网找,如果你有msdn,用msdn找,自己分析会更加容易。然后再跟API Text Viewer一起用,看它的declaration。

e.g.,在msdn,用index找,WM_LBUTTONDOWN,你可以找到类似的东西:
WM_LBUTTONDOWN Notification

The WM_LBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.

A window receives this message through its WindowProc function.

Syntax

WM_LBUTTONDOWN

    WPARAM wParam
    LPARAM lParam;
   
Parameters

wParam
Indicates whether various virtual keys are down. This parameter can be one or more of the following values.
MK_CONTROL
The CTRL key is down.
MK_LBUTTON
The left mouse button is down.
MK_MBUTTON
The middle mouse button is down.
MK_RBUTTON
The right mouse button is down.
MK_SHIFT
The SHIFT key is down.
MK_XBUTTON1
Windows 2000/XP: The first X button is down.
MK_XBUTTON2
Windows 2000/XP: The second X button is down.
lParam
The low-order word specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.

The high-order word specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.
Return Value

If an application processes this message, it should return zero.

Remarks

Use the following code to obtain the horizontal and vertical position:

xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);

You can also use the MAKEPOINTS macro to convert the lParam parameter to a POINTS structure.

To detect that the ALT key was pressed, check whether GetKeyState(VK_MENU) < 0. Note, this must not be GetAsyncKeyState.

Notification Requirements

Minimum DLL Version None
Header Declared in Winuser.h, include Windows.h
Minimum operating systems Windows 95, Windows NT 3.1

See Also

Mouse Input Overview, GET_X_LPARAM, GET_Y_LPARAM, GetCapture, GetKeyState, MAKEPOINTS, POINTS, SetCapture, WM_LBUTTONDBLCLK, WM_LBUTTONUP

[ 本帖最后由 meemee 于 26-6-2006 05:40 PM 编辑 ]
回复

使用道具 举报

发表于 26-6-2006 05:46 PM | 显示全部楼层

continue from top...

如果,我没记错,SendMessage里的hwnd,wmsg,lparam,wparam都是4 bytes (long)。不过,API Text Viewer和你给的declaration的lparam却是用any,而且还是用default,pass by reference。感觉上怪怪的。。。

WM_LBUTTONDOWN就是你的wmsg

wParam的,你可以用API Text Viewer找。如果,你厉害的话,就直接从visual c/c++的header看。。。
这个是在winuser.h
#define MK_LBUTTON          0x0001
#define MK_RBUTTON          0x0002
#define MK_SHIFT            0x0004
#define MK_CONTROL          0x0008
#define MK_MBUTTON          0x0010
#define MK_XBUTTON1         0x0020
#define MK_XBUTTON2         0x0040


如果是WM_LBUTTONUP,wParam就是0。
用这个方法,作wParam。
wParam = MK_CONTROL And MK_LBUTTON;这一行表示你的按click时,你也按着control key。

lParam就是mouse的位置。
前2 bytes是y,后2 bytes是x。你可以用这方法来convert x,y去lParam。
lParam = y * &H10000 + x

所以,整个SendMessage就是:
SendMessage myHwnd,WM_LBUTTONDOWN,MK_CONTROL And MK_LBUTTON,byval (y * &H10000 + x)

除了,sendmessage,还有PostThreadMessage,PostMessage。。。不过你用sendmessage就够了。


EM_ 的完整应该是edit message,也就是text box咚咚。

3,应该不能捉色。。。

[ 本帖最后由 meemee 于 26-6-2006 05:47 PM 编辑 ]
回复

使用道具 举报

发表于 27-6-2006 09:46 AM | 显示全部楼层
Option Explicit

Private Type POINTAPI
        x As Long
        y As Long
End Type

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal
lParam As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_SETCURSOR = &H20
Private Const WM_MOUSEACTIVATE = &H21

Private Const MK_LBUTTON = &H1

Private Const HTCLIENT = 1&

Dim HwndFlash As Long

Private Sub Command1_Click()

Dim Timer1 As Single
Dim MousePos As Long
Dim HitTest As Long

Dim OldPt As POINTAPI
Dim TargetPt As POINTAPI
Dim TemPt As POINTAPI

TargetPt.x = 85
TargetPt.y = 218
MousePos = TargetPt.y * &H10000 + TargetPt.x
TemPt.x = TargetPt.x
TemPt.y = TargetPt.y

Timer1 = Timer

'这个部分是第一个click
'SendMessage的最后一个parameter必须用ByVal,不过PostMessage的可以省掉
'在WM_LBUTTONDOWN之前,我还send两个WM_MOUSEMOVE和一个WM_SETCURSOR
'骗那个flash,我的cursor已经move到那里了

PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
HitTest = WM_MOUSEMOVE * &H10000 + HTCLIENT
SendMessage HwndFlash, WM_SETCURSOR, HwndFlash, ByVal HitTest
PostMessage HwndFlash, WM_LBUTTONDOWN, MK_LBUTTON, ByVal MousePos
PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
PostMessage HwndFlash, WM_LBUTTONUP, 0&, ByVal MousePos

'这里我delay一段时间
Do While (Timer - Timer1) < Text1
DoEvents
Loop

'这个部分是第二个click
PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
HitTest = WM_MOUSEMOVE * &H10000 + HTCLIENT
SendMessage HwndFlash, WM_SETCURSOR, HwndFlash, ByVal HitTest
PostMessage HwndFlash, WM_LBUTTONDOWN, MK_LBUTTON, ByVal MousePos
PostMessage HwndFlash, WM_MOUSEMOVE, 0&, ByVal MousePos
PostMessage HwndFlash, WM_LBUTTONUP, 0&, ByVal MousePos

End Sub

Private Sub Form_Activate()
HwndFlash = FindWindow("ShockwaveFlash", "Flash")
If HwndFlash = 0 Then
    MsgBox "Problem"
    End
End If
End Sub

'这里HiWord和LoWord的作用是把long integer分成两段
Function HiWord(ByVal Num As Long) As Long
HiWord = Num And &HFFFF0000 / &H10000
End Function

Function LoWord(ByVal Num As Long) As Long
LoWord = Num And &HFFFF
End Function

Sub Delay(ByVal Second As Single)
Dim time1 As Single

Do While Timer < (time1 + Second)
DoEvents
Loop
End Sub



[ 本帖最后由 meemee 于 27-6-2006 09:49 AM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 10-7-2006 12:05 PM | 显示全部楼层
谢谢 meemee,

又是几天没上来,都忙着追看球赛
你的恢复很好,我有些概念了,但还是要 "消化消化" 先

还有写了一个计算机(calculator),写计算机让我学会了用 listview .



有问题再问你。谢谢。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 6-8-2006 06:54 PM | 显示全部楼层

回复 #33, #34, #35 meemee 的帖子

谢谢 meemee.
用了这么久终于消化完了

#33, #34 和 #35 的回帖 帮我弄明白了 sendmessage & postmessage function, 也解决了我 setcursorpot 的问题。
有个问题:
我用 sendmessage 没有 mouse click(mouse 有到目的地但没按下) ,用 PostMessage 就有 mouse click. why?
SendMessage test_hwnd, WM_LBUTTONDOWN, MK_LBUTTON, ByVal (pt.y * &H10000 + pt.x)
PostMessage test_hwnd, WM_LBUTTONDOWN, MK_LBUTTON, ByVal (pt.y * &H10000 + pt.x)



另外一个问题,

FindWindowEx vs EnumChildWindows

我想在"母窗口"找 "子窗口" ,可不知一共有几个"子窗口",也不知"子窗口"的classname.(只是找当前"母窗口"下的"子窗口",不是"子窗口"下的"子窗口"...)

用 ∶
client_hwnd = FindWindowEx(Me.hwnd, 0, 这里该放?, vbNullChar)

还是 用:
hChild = FindWindowEx(hParent, 0, 0, 0)

这又是怎用:
EnumChildWindow hParent, 0
EnumChildWindows hParent, AddressOf EnumChildWindow, 0


之所以要找"子窗口"是因为要用以下的 command 在游戏里喊话(说话)
SendMessage test_hwnd, WM_SETTEXT, 0, testString

[ 本帖最后由 BillyG 于 6-8-2006 06:57 PM 编辑 ]
回复

使用道具 举报

发表于 6-8-2006 10:17 PM | 显示全部楼层
我的project是做database application
我选择VB。。。。。。



但上面的东动我一个都不懂。
回复

使用道具 举报

发表于 7-8-2006 12:36 PM | 显示全部楼层

回复 #38 haroldlbc 的帖子

上面的东西都是调用api。。。如果,你的program只涉及到database,那么,你用到它的机会就很少。。。

如果你有做screen saver,game,捉图程序或installer之类的东西,那么api肯定需要。。。

api的用途很广。。。像楼上用的这个指令
SendMessage me.hwnd, WM_SETTEXT, 0, byval testString


跟这个的效果是一样的。。。
me.caption = testString
回复

使用道具 举报

发表于 7-8-2006 01:56 PM | 显示全部楼层

回复 #37 BillyG 的帖子

SendMessage和PostMessage,的不同点是前者,必须等到那个被SendMessage的对象process完那个指令才执行下一个指令,后者,不需要等。。。就直接执行下一个指令。。。另一个不同点是SendMessage把Message发给window,PostMessage是发给thread。。。

懂得用microsoft spyxx吗?它是vc++ sdk的tool,可以用来看window name和class。。。

EnumChildWindows有些复杂。。。需要用到module。。。把EnumChildProc的function declare在module里
用的指令应该是这样:
EnumChildWindows hParent, AddressOf EnumChildProc, 0

我相信,WindowFromPoint和ChildWindowFromPoint可以做到你要的东西。。。你试试看。。。

这条指令好像也不对。。。应该要有byval在testString之前。。。
SendMessage test_hwnd, WM_SETTEXT, 0, testString

应该是这样:
SendMessage test_hwnd, WM_SETTEXT, 0, byval testString

[ 本帖最后由 meemee 于 7-8-2006 02:00 PM 编辑 ]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 26-7-2025 01:40 PM , Processed in 0.122765 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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