首页
社区
课程
招聘
[原创]用vc实现OO消息群发的关键代码解析
2006-6-9 16:04 8234

[原创]用vc实现OO消息群发的关键代码解析

2006-6-9 16:04
8234
寒假时做的一个QQ消息发送器,请各位见谅,由于我=级不够,不能将整个代码和图片传上来,所以现在将它的一些核心部分的技术拿出来细讲以下,希望能对读者来一点思路,做出更好的东西。
感谢网上的所有高手将自己的经验分享出来让我做了许多的参考
感谢班主任杨老师的指导

做QQ消息发送器,最重要的是要先找到QQ聊天的窗口,然后将自己想说的话写到QQ消息发送框里,在模拟键盘输入按下“发送”的按扭,这样就可以搞定了(呵呵,是不是很简单的啊),那好,现在就让我们来动手做吧。

<1>找窗口
想要找到QQ聊天的窗口,我们要用到2个函数FindWindowEx()和GetWindowText(),首先我们用FindWindowEx()函数找到所有桌面的窗口,当然,我们只需要QQ的聊天窗口,其他的对我们没用,FindWindowEx()只能找到一个窗口,怎么才能找到所有的窗口然后我们在去判断是不是QQ的聊天窗口呢?这就要用到vc++给我们提供的一个很好的函数GetWindow()了,让我们看看下面的代码:
HWND hwnd=FindWindowEx(NULL,NULL,"#32770",NULL);
While (hWnd != NULL)
{
   If ()
     {
        //……..
     }
Else
{
           hwnd=::GetWindow(hwnd,GW_HWNDNEXT);
}
}
用以上的代码就可以将桌面上的窗口一个一个的找到,然后我们就对一个一个的窗口的名字进行判断,如果含有”与”(因为QQ聊天窗口的名字都是”与XX聊天中”);
<2>由于桌面上的窗口按照那个Z序列放置的,如果按照找到一个窗口,发送一句话,然后在找个窗口,在发送一句话的思路回出错的(我做的时候就是这出错了,感谢我的班主任杨老师的指导使我明白了这个问题)所以我们就要想个方法避免上面哪个思路了,我在这用到了数组,在找到窗口后先保存起来,在找完所有的窗口后在集体实行发送消息
CTypedPtrArray<CObArray, CWnd*> myArray;
这句就是我创建了一个窗口的array(如果您对上面这句话不理解,请查阅MSDN)
OK
这就是整个的思想
现在我将核心代码拿来让大家看看

void CQQView::OnButton1()
{
        // TODO: Add your control notification handler code here
        
        CTypedPtrArray<CObArray, CWnd*> myArray;
    // 这个m_edit是Edit Box窗口的一个变量,它存放您想发送的那句话
        // 如果m_edit为空,说明您还没写您想发送的话,它提示您先写上您想发送的话
                if(m_edit.IsEmpty())
                {
                        MessageBox("please enter what do you want to say!!!",
                                           "Attention",
                                           MB_OK |  MB_ICONWARNING);
                        return;
                }
                HWND hwnd=FindWindowEx(NULL,NULL,"#32770",NULL);
                while(hwnd)
                {
                        CString string;
                        char a[100];
                        HWND send,pro,pro1,message;
                        // 得到窗口名称
                        ::GetWindowText(hwnd,a,100);
                        string.Format("%s",a);
                        // 如果含有"与"(因为QQ聊天窗口的名字都是"与XX聊天中");说明是QQ窗口
                        if(string.Find("与")>-1)
                        {
                                pro=FindWindowEx(hwnd,NULL,"#32770",NULL);
                                CWnd *pWnd=CWnd::FromHandle(pro);
                                pro1=FindWindowEx(pWnd->m_hWnd,NULL,"AfxWnd42",NULL);
                                CWnd *child=CWnd::FromHandle(pro1);
                // 找到QQ窗口的哪个写消息的文本框
                                message=FindWindowEx(child->m_hWnd,NULL,"RICHEDIT",NULL);
                                          if(message)
                                          {
                                                         CRichEditCtrl* rich
                                                                                  =  (CRichEditCtrl*)(CWnd::FromHandle(message));
                                                         rich->ReplaceSel(m_edit);
                                          }
                                          else
                                          {
                                                         return;
                                          }
                                send=FindWindowEx(pWnd->m_hWnd,NULL,NULL,NULL);
                                string="";
                                          while(send)
                                          {
                                                        child=CWnd::FromHandle(send);
                                                        child->GetWindowText(string);
                                                        if(string.Find("发送")>-1)
                                                        {
                               //加入指针数组
                                                                myArray.Add(child);

                                                                 send=NULL;
                                                        }
                                                        else
                                                        {
                                                                 send=FindWindowEx(pWnd->m_hWnd,send,NULL,NULL);
                                                        }
                                          }
                                hwnd=::GetWindow(hwnd,GW_HWNDNEXT);
                        }
                        else
                                hwnd=::GetWindow(hwnd,GW_HWNDNEXT);
                }
        // 按照窗口数组里的窗口进行逐个发送信息
                for(int count=0;count<myArray.GetSize();count++)
                {
                        CWnd* p=myArray.GetAt(count);
                        p->SendMessage(BM_CLICK);
                }
        // 清空数组
                myArray.RemoveAll();
        // 将m_edit清空,因为下一次您要写上您想发送的话
                SetDlgItemText(IDC_EDIT1,"");
                m_edit="";
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞7
打赏
分享
最新回复 (11)
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-9 19:23
2
0
好文章~~~~~~顶一下``````````
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-10 12:11
3
0
问几个问题````````
我做了一个测试,就是关闭所有打开的聊天窗口
    HWND hwnd,hwnd1;
    hwnd = ::FindWindowEx(NULL,NULL,"#32770",NULL);
    while(hwnd != NULL)
    {
        hwnd1 = ::FindWindowEx(hwnd,NULL,"#32770",NULL);
        ::SendMessage(hwnd1,WM_CLOSE,0,0);
        hwnd = ::GetWindow(hwnd,GW_HWNDNEXT);
    }
上面的代码执行成功
为什么下面这样写不行?
    HWND hwnd;
    hwnd = ::FindWindowEx(NULL,NULL,"#32770",NULL);
    while(hwnd != NULL)
    {
        ::SendMessage(hwnd,WM_CLOSE,0,0);
        hwnd = ::GetWindow(hwnd,GW_HWNDNEXT);
    }

还有,在使用::FindWindowEx(hwnd,NULL,"RICHEDIT",NULL)
得到写消息文本框的句柄后,为什么不能通过SetWindowText()
来设置消息内容,是否QQ做了特殊处理,所以不行?
望解答````````````
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-6-10 13:14
4
0
你同哪个SPY++看看QQ窗口
其实它分为2个大的"#32770"
我估计就算你点击哪个X的时候,是将关闭的信息穿到了里面的哪个"#32770"然后由里面的在关闭外面的哪个"#32770"(当然,这个只是我的估计,)
关于你这个SetWindowText()问题
MSDN里的话就是答案

The SetWindowText function changes the text of the specified window's title bar (if it has one). If the specified window is a control, the text of the control is changed.(注意) However, SetWindowText cannot change the text of a control in another application.
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-10 13:39
5
0
多谢楼主解答,两个大的是在上和下吗?
这次我注意到了
移动到最下边的时候和最上边句柄是不一样的~~~~~~~~~~~
那还可以用其他API函数来更改内容吗?
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-6-10 13:47
6
0
至于有没有其他的我不太清楚了
以前在做这个发送器的时候还有一个思想就是运用粘贴的技术,也就是模拟键盘输入,事先你可以先复制一段话,然后在哪个编辑窗口中模拟ctrl+v将它粘贴
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-10 14:23
7
0
这个方法我倒是没想到
谢谢了```````
我把数据粘贴到Clipboard后
使用SendMessage(hRich,WM_PASTE,0,0)
没有成功,希望楼主讲解````
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-11 20:01
8
0
顶一下,让楼主看到
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-6-11 20:52
9
0
这个我没试过
但是我要说的是先要激活哪个控件
另外这个WM_PASTE消息好象只对edit和combox的控件有用,其它的就不行了
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-11 22:11
10
0
最初由 红火蚁 发布
这个我没试过
但是我要说的是先要激活哪个控件
另外这个WM_PASTE消息好象只对edit和combox的控件有用,其它的就不行了


但是我要说的是先要激活哪个控件
这句话没看懂````什么意思````
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-6-11 22:19
11
0
呵呵
这个是说
你在给一个控件,如EDIT上粘贴东西时你先要确保这个控件是当前最前面的active控件
以前做过许多这样的事
有时他可能虽然具有哪个光标(就是输入时哪个一闪一闪的|)
但它不是最前面的active窗口或控件
那给它粘贴东西就不行,回失败的
懂了吗?
雪    币: 221
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
vlit 2006-6-12 12:16
12
0
I see...
游客
登录 | 注册 方可回帖
返回