我是一个初学者,我在书上看到好多关于句柄的函数,大家可以说一下,
  如何理解和使用它吗? 还有就是如何获取句柄。可否总结一下?
   多谢了!

解决方案 »

  1.   

    我自己写的一稿:(是刚学的时候写的,很是肤浅.对查句柄还是有点作用了.请不要见笑)
    QQ聊天机器人
    前几日,看到杂志上有一篇关于开发QQ聊天机器人的文章。谈到了对QQ循环发送消息
    内容,感觉倒也很好玩,于是拿起Delphi开始了我的QQ聊天机器人之路。
      首先要明白自己要做什么,大家都用过QQ,知道给别人发送消息的整个过程吧!要实现循环发送消息的功能该有以下几个条件:
    1. 必须是在聊天模式里进行。这样发送完一条消息后,QQ窗体还存在。
    2. 其次是要找到QQ文本窗体的句柄。
    3. 向QQ文本窗体中贴上你想说的话。然后自己点击发送按钮。
    思路很简单,接着我们就要开始实施了。
      首先要找到QQ文本窗体的句柄。这时我用到了SPY来查看QQ的窗体。结果如下图:
    本人网站上有:http://www.cnhui.com/user1/fengjun/myweb 
    这样思路就出来了。要找到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;
           edit1.CopyToClipboard;             //拷贝到剪切板
           sendmessage(hmemo1,WM_PASTE,0,0);  //对QQ输入文本窗体发送粘贴消息。
           sendmessage(hbutton,BM_CLICK,0,0);  //点击发送按钮
           i:=i+1;   
      end;
      if checkbox1.Checked=false then  //没有点击了循环发送复选框。
      begin
        edit1.Text:=combobox1.Text;
        edit1.SelectAll;
        edit1.CopyToClipboard;
        sendmessage(hmemo1,WM_PASTE,0,0);
        sendmessage(hbutton,BM_CLICK,0,0);
      end;
    end;
    后记:
    以上代码是针对QQ2003版本。虽然网上有如:飘叶千夫指的好工具。不过作为一个小小菜鸟。但又喜欢编程的人来说。自己DIY(do it youtself)一个也是很爽的一件事吧!我自己也参照飘叶千夫指做了一个,感觉具备了它的使用功能吧!还不错。其实也没有太多技术性的东西,只是运用了几个API函数而已。只希望对刚刚学DeLphi的朋友有所帮助,当然高手是用不着的了。
    有需要朋友到我的网站去下载(位于我的作品里):
    http://www.cnhui.com/user1/fengjun/myweb/index.asp
    Blue.Wind  2003-10-29  于山西太原
    --由于本人不善表达。未表达清楚这处还请原谅!