制作QQ消息炸弹[1]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 hottey 的 blog

qq聊天机器人随想

原作:hottey(阿风)

  前几日,看到杂志上有一篇关于开发qq聊天机器人的文章。谈到了对qq循环发送消息内容,感觉倒也很好玩,于是拿起delphi开始了我的qq聊天机器人之路。
  首先要明白自己要做什么,大家都用过qq,知道给别人发送消息的整个过程吧!要实现循环发送消息的功能该有以下几个条件:
  1.必须是在聊天模式里进行。这样发送完一条消息后,qq窗体还存在。
  2.其次是要找到qq文本窗体的句柄。
  3.向qq文本窗体中贴上你想说的话。然后自己点击发送按钮。
  思路很简单,接着我们就要开始实施了。
  首先要找到qq文本窗体的句柄。这时我用到了spy来查看qq的窗体。结果如下图:这样思路就出来了。要找到qq文本窗体的句柄就得先找到它的父类即:标志为00620252 class name:afxwnd42 control id:00000000。而要找到它就必须找到qq消息对话框即:006b294“冷问梅 - 发送消息”#32770〔dialog〕的句柄。
这时要用到几个api函数:
1.findwindowex(
    hwnd1:long, //在其中查找子的父窗口,如设为0,表示使用桌面窗口(通常说的顶级窗口都认为是桌面的子窗口)
    hwnd2:long, //从这个窗口后开始查找。如设为0,表示对第一个子窗口开始搜索。
    lpsz1:string, //欲搜索的类名,0表示忽略。
    lpsz2:string //欲搜索的类名,0表示忽略。
  );
2.getwindow(
    hwnd:long, //源窗口。
    wcmd:long //指定结果窗口与源窗口的关系(这里用gw_child)表示寻找源窗口的第一个子窗口。
      );
3. getdlgitem(
     hwnd:long, //源窗口的句柄。
     int: niddlgitem //要在其中查找的窗口的id号
   );
  其实刚开始找qq对话窗口时,我先想到的是findwindow(),这个函数可以直接通过窗口标题名来查找窗体句柄。
  我是这样找的:
var hparent:hwnd;
hparent:=findwindow(nil, '发送信息'); //这对2003以前的版本还是很有效的^_^
  结果却是返回错误。why?
  后来仔细一看,发现每次qq2003的标题都在变:如上图是:冷问梅 - 发送消息,要是你又对一个人发信息就会变成:蓝色的风 ╟ 发送消息(举个例子)。
  这也许是qq2003采取的一种安全措施吧!呵呵!你们也许会看见网上针对qq2003发送消息炸弹的工具有时要是输入对方的昵称的原因。(便于通过昵称得到窗体句柄)。
  不过有没有更好的方法呢!有!这时就要用到findwindowex()了。仔细看一下它的参数,关键是第二个hwnd2——我们可以通过它来多次调用findwindowex找到符合条件的子窗口。以下是我的代码:
var hparent:hwnd; //定义为全局变量。来记录每次调用findwindowex()后找到的窗体的句柄。
procedure tform1.formcreate(sender: tobject);
begin
  hparent:=0; //初始化,查找桌面所有的顶级窗口开始。
end;
procedure tform1.timer1timer(sender: tobject);
var hbutton,hbutton1:hwnd;
begin
  repeat
    hparent:=findwindowex(0,hparent,'#32770',nil); //qq对话框的类为#32770,这样循环调用findwindowex()就能每次时钟生效时更新hparent的值。从已查找的句柄为hparent的窗体后查找符合要求的窗体。
    hbutton:=findwindowex(hparent,0,nil,'发送(&s)'); //每次判断找到的窗口的句柄,看这个窗体中是否存在'发送(&s)'按钮。存在即找到了正确的qq对话框。
  until  hbutton<>0; //找到qq对话框后跳出循环。
  hbutton1:=findwindowex(hparent,0,nil,'聊天模式(&t)') ; //找到qq对话窗体后,查找聊天模式按钮句柄。  
  if hbutton1<>0 then //若此时存在聊天模式按钮即现在qq窗体处于消息模式状态。
    sendmessage(hbutton1,bm_click,0,0); //给聊天模式按钮发送单击消息。将窗体转换为聊天模式。
end;
  这样我们就成功的找到的qq对话框。和成功设置对话框为聊天模式了。任务总算先完成了一些,呵呵!更郁闷我的还在后头了。
  接着,就要开始查找qq输入文本的那个窗体的句柄了。这时我用到的是getdlgitem()大家知道一个窗体中某一类控件的control id在这个窗体类中是不变的(除去一些静态文体外)过spy我获知qq输入文本的那个窗体的control id为0000037e。于是我写了下面的语句。
var hmemo:hwnd;
hmemo:=getdlgitem(hparent,$0000037e);
  结果发现写得东东完全没有自己预想的效果。呵呵!还是拿起spy,哈!发现竟然不止一个控件的id为0000037e。并且我们想要得到qq输入文本的那个窗体的位置也不是最前一个(要是最前一个,通过上面的语句也是可以找到的^_^)。郁闷了不是。没办法还是从它的父类开始吧!可不能在一步求成了。仔细看看上图。发现了吧!
  标志为00620252 class name:afxwnd42 control id:00000000的即是qq输入文本的那个窗体的父类,并且它是所有class name:afxwnd42中位置最前的那一个。于是我们就可以找到它的句柄。跑不掉了。有了它,qq输入文本的那个窗体的句柄也就很容易找到了,哈哈!以下是我的代码:
var hmemo,hmemo1:hwnd;
hmemo=getdlgitem(hparent,$00000000); //找到父类。
hmemo1=getwindow(hmemo1,gw_child); //得到父类下的第一个子窗口句柄(hmemo1即qq输入文本的那个窗体的句柄^_^大功告成)
  这里顺便说一下getwindow()用法:
getwindow(
  hwnd:long, //源窗口句柄。
  wcnd:long //指定结果窗口与源窗口的关系。(gw_child为得到源窗体下的第一个子窗口句柄)
)
  更多的常数关系你们就去查看msdn吧!这里就不必占用寒泉的空间了。哈!
  到此,qq对话框和qq输入文本窗口的句柄我们都已经得到了,以下的步骤就是把你要写的话,贴进qq输入文本窗口,点一下发送,就郁闷别人吧!
  现在贴出我的一段代码以供大家参考:
procedure tform1.formcreate(sender: tobject);
begin
  i:=0;
  //导入文件内容到combobox控件。
  combobox1.items.loadfromfile(extractfilepath(application.exename)+'text.txt');
  combobox1.text:=combobox1.items.strings[0];
end;
procedure tform1.timer1timer(sender: tobject);
var hmemo1:hwnd; //hmemo1为找到的qq文本输入框句柄
begin
  if checkbox1.checked then //点击了循环发送复选框。
  begin
    if i>combobox1.items.count-1 then
      i:=0;
    edit1.text:=combobox1.items.strings[i];
    edit1.selectall;

本文关键:QQ
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top