看流星社区

 找回密码
 注册账号
查看: 4407|回复: 11

自编的延时函数无效,老是不停嗑药?[武林外传]

[复制链接]

该用户从未签到

发表于 2011-3-22 09:45:10 | 显示全部楼层 |阅读模式
大大们,能帮我看下,下面这个函数错在什么地方了吗?

//自编的延时函数 因为用sleep()会造成程序假死
procedure Delay(msecs:integer);
var
FirstTickCount:longint;
begin
FirstTickCount:=GetTickCount;
repeat
Application.ProcessMessages;
until ((GetTickCount-FirstTickCount) >= Longint(msecs));
end;

//加血代码放在一个Timer内
procedure TForm1.jiaxueTimer(Sender: TObject);
begin
  hwd:=findwindow(nil,'Element Client');
  if hwd<>0 then
  begin
    GetWindowThreadProcessId(hwd,pid);
    hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
    ReadProcessMemory(hProcess,pointer(address),@base, 4, num);
    ReadProcessMemory(hProcess,pointer(base + $24), @base, 4, num);//得到为人物基地址
  ReadProcessMemory(hProcess,pointer(base + $254), @hp, 4, num); //得到生命值
    if  hp < strtoint(edit1.Text) then
    begin
    sendmessage(hwd,WM_KEYDOWN,VK_F1,0);
    sendmessage(hwd,WM_KEYUP,VK_F1.HotKey,0);
    delay(6000); //延时6秒,但是好像不管用,还是不停吃药,换成sleep可以,但是程序会假死,郁闷
    end;
  end;
end;

该用户从未签到

发表于 2011-3-22 09:45:17 | 显示全部楼层
不是按键函数,是自编的延时函数

该用户从未签到

发表于 2011-3-22 09:45:25 | 显示全部楼层
你说是不是因为没使
CloseHandle(PHND);的原因哪。有时候我这个放错了顺序  在for里。也会假死

该用户从未签到

发表于 2011-3-22 09:45:33 | 显示全部楼层
是不是msecs没定义或没正确赋值啊?很久没用DELPHI了,说错了别见怪。
until ((GetTickCount-FirstTickCount) >= Longint(msecs));
-----------
哦,刚才没看到这里procedure Delay(msecs:integer);已经有定义了。SORRY

该用户从未签到

发表于 2011-3-22 09:45:44 | 显示全部楼层
procedure TForm1.jiaxueTimer(Sender: TObject);
begin
  hwd:=findwindow(nil,'Element Client');
  if hwd<>0 then
  begin
    GetWindowThreadProcessId(hwd,pid);
    hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
    ReadProcessMemory(hProcess,pointer(address),@base, 4, num);
    ReadProcessMemory(hProcess,pointer(base + $24), @base, 4, num);//得到为人物基地址
  ReadProcessMemory(hProcess,pointer(base + $254), @hp, 4, num); //得到生命值
    if  hp < strtoint(edit1.Text) then
    begin
    sendmessage(hwd,WM_KEYDOWN,VK_F1,0);
    sendmessage(hwd,WM_KEYUP,VK_F1.HotKey,0);
    delay(6000); //延时6秒,但是好像不管用,还是不停吃药,换成sleep可以,但是程序会假死,郁闷
    end;
  end;
end;
问题有几点如下
一  
sendmessage(hwd,WM_KEYDOWN,VK_F1,0);
sendmessage(hwd,WM_KEYUP,VK_F1.HotKey,0);
你的这个VK_F1.HotKey是什么?这里应该就是VK_F1
你不停吃药的原因是sendmessage(hwd,WM_KEYDOWN,VK_F1,0);这里按下了,
sendmessage(hwd,WM_KEYUP,VK_F1.HotKey,0);但这里放开的不是VK_F1,所以是F1一直按下的原因

二,你这段代码本身就有问题,
你在每一次timer被处发的时候都会做如下的事
就是OpenProcess,这部分你完全可以放在外面,readprocessmemory只接收你的ProcessHandle就行了,这个OpenProcess的代码放到外面,程序运行一次做一次就行,不要在timer中执行.

三,
还有timer本身就是有延迟,你为啥要在timer里用延迟函数呢?
如果你要让你的代码延迟6秒你就把timer的Interval这个设置成6000把那个delay去掉......
因为你的delay不断的在调用Application.ProcessMessages它做让主线程的消息列队得到响应,所以,
当你的timer的Interval小于你的Delay中的参数时,那么刚一进延迟函数(delay)就会给主线程得到响应,这个时候主线程可能又收到你的 WM_TIMER消息,则又进入了Timer的函数,所以你要把delay去掉就让Timer去延迟,我已经把代码帮你改过.记得设置timer的 Interval
var
  hProcess: DWORD;    //这个可以使用全局变量
  hwd: HWND;
procedure initProcess;
var
  pid: DWORD;
begin
  hwd:=findwindow(nil,'Element Client');
  if hwn <> 0 then
  begin
      GetWindowThreadProcessId(hwd,pid);
      hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
  end;
end;

procedure TForm1.jiaxueTimer(Sender: TObject);
begin
    ReadProcessMemory(hProcess,pointer(address),@base, 4, num);
    ReadProcessMemory(hProcess,pointer(base + $24), @base, 4, num);//得到为人物基地址
  ReadProcessMemory(hProcess,pointer(base + $254), @hp, 4, num); //得到生命值
  if  hp < strtoint(edit1.Text) then
    begin
      sendmessage(hwd,WM_KEYDOWN,VK_F1,0);
      sendmessage(hwd,WM_KEYUP,VK_F1,0);
  end;
  end;
end;
在窗口的OnCreate中或Button的OnClick调用initProcess
再窗口的Close中调用CloseHandle(hProcess);

该用户从未签到

发表于 2011-3-22 09:45:53 | 显示全部楼层
sleep这个函数会把主线程的消息列队挂起(阻塞),这样就会让界面死掉,一般sleep用在线程中使用
因为他的代码是在timer中执行,虽然timer可以看作是一个线程,但它不是真正意义上的,它的实现是在主线程的消息列队中插入WM_TIMER消息来实现的,所以使用sleep会使界面死掉.

该用户从未签到

发表于 2011-3-22 09:46:06 | 显示全部楼层
楼主,今天刚刚学习delphi,刚好写了个延时函数,是按照原来那个vb的延时函数写的。呵呵。共享下:
procedure TForm1.WaitingSeconds(seconds: real);
var
FirstTickCount,tmpNow : longint;
begin
  tmpNow := GetTickCount;    //记下开始时的时间
  while (GetTickCount<seconds*1000+tmpNow) do
          Application.ProcessMessages;
end;

vb6中的代码是

Public Sub WaitingSeconds(ByVal seconds As Double)
        Dim tmpNow As Double
        tmpNow = timeGetTime  '记下开始时的时间
        While timeGetTime < seconds * 1000 + tmpNow
          DoEvents
        Wend
End Sub

反正都是一样的机制。。今天感觉delphi咋和vb这么象呢。。

该用户从未签到

发表于 2011-3-22 09:46:32 | 显示全部楼层
其实这个问题不难解决,用timer自己做定时就行了
我做的挂里是这么实现的,只是多用了两个全局变量,这样可以自己设保护时间
bIsEatHp:boolean; //吃hp的标志
iHpDealy:integer;  //hp保护计数
在timer事件里
if bIsEatHp then
begin
  inc(iHpDelay);
  if iHpDelay>(吃药保护时间 div timer触发间隔) then
  begin
      iHpDealy:=0; //计数值复位
  bIsEatHp:=false; //保护时间到,清除标志
  end;
end
else iHpDealy:=0;

if (not bIsEatHp) and (hp小于设定值) then
begin
  bIsEatHp:=true; //设定标志,在标志未清除的时候是不会再吃药的
吃药;
end;

该用户从未签到

发表于 2011-3-22 09:46:46 | 显示全部楼层
我就是用的楼上的方法。另外一个timer控制这些开关。主循环里检查这些开关。但是sleep始终是要卡界面的。
unit Unit2;

interface

uses
  Classes;

type
  TGua = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  public
  constructor create;
  end;

implementation


{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure TGua.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TGua }
uses unit1;

constructor TGua.create;
begin
  inherited create(false);//false表示线程建立后马上唤醒
end;
procedure TGua.Execute;
begin
  { Place thread code here }

  form1.GuaJi;

end;

end.
这个是my50的建立线程代码。他用线程解决的可能好些

该用户从未签到

发表于 2011-3-22 09:46:51 | 显示全部楼层
还是建立线程好好用些,在timer中加延时函数 可能会出现异常情况,大概是timer的时间完成了 还在延时函数中循环,软件会死掉(我刚开始用vb学辅助的时候就是这样)  
用线程控制就方便多了 直接使用sleep()函数,并且为了控制吃药速度 ,我的解决方法是
if  (hp< 500 ) and (GetTickCount()-ctme>3000)  then  // 控制在3秒之类只吃一次
begin
//吃药
ctme:=GetTickCount()
end;  

这样避免了误食毒品,当然以上是针对挂机用的,对于PK  可以调整 3000的速度或手动得了
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-26 19:08

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

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