新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 如何用Visual C++对QQ界面进行模拟? 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3916 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 如何用Visual C++对QQ界面进行模拟? 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     葛靖青001 美女呀,离线,快来找我吧!水瓶座1984-2-14
      
      
      等级:大三(研究MFC有点眉目了!)
      文章:168
      积分:595
      门派:XML.ORG.CN
      注册:2010/11/2

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给葛靖青001发送一个短消息 把葛靖青001加入好友 查看葛靖青001的个人资料 搜索葛靖青001在『 C/C++编程思想 』的所有贴子 点击这里发送电邮给葛靖青001 引用回复这个贴子 回复这个贴子 查看葛靖青001的博客楼主
    发贴心情 如何用Visual C++对QQ界面进行模拟?

    【转自互联网】

    大凡用过电脑,上过网的朋友都用过QQ,对QQ的一些交互界面可能垂慕已久,的确,无论是其生动的企鹅形象,还是“滴滴的”消息声音,以及“刷”的菜单等功能,简单单的消息发送,以及快速的回显和众多卡通的QQ头像等铸就了其在网络的良好地位,本人对其研究虽不够透彻,但也做一些探索性的尝试,并简单的实现了比较突出的功能,在模拟的过程中,主要实现了以下几部分的功能:

      QQ菜单,也称抽屉菜单(也有的叫导航菜单);

      QQ头像的列表显示;

      简易的消息发送模拟;

      简易的上线,隐身模拟;

      悬挂QQ;


      

      当然啦,现在的QQ功能强大,如QQ直播,联系人,个人设置等功能,视频聊天等众多强悍功能,本人能力不及,并没有实现!下面,就开始QQ模拟之旅吧!

      一、准备

      在实现QQ界面之前,有一些准备工作,请确定你已经有如下知识:

      1.具备C,C++,VC的初步知识!

      2.具备一定的思考能力!

      3.要有一定的想法

      4.熟悉QQ界面

      5.具备一些软件工具:如Visual C++, Resource Hack(这个可以找到.exe、.dll 文件的资源,包括对话框和控件的属性.

      二、剖析QQ界面

      1.QQ头像和图标

      这是QQ做的特别好的地方,大家如果留心的话会发现QQ附带的功能实在强悍,可以视频聊天,截图,发送文件,记录我的好友等信息,等这些功能全部仅在一个对话框或一个设置框中实现,给人很轻松的感觉,企鹅的形象深入民心,获取关键的图标是很必要的。

      用Resource Hacker对你安装的QQ.exe进行资源导出吧,这样获取的图标文件.ico为你所用,不要再为没有形象ICO而烦恼啦!

      在你的QQ安装目录下面有个QQface,里面有QQ所需要用到的所有QQ头像,如果你不知道的话,也可以直接下载本人的源代码,里面已经将100张QQ头像嵌在里面啦,直接用,不要客气!

      2.登陆界面

      QQ的登陆界面简单易了,风格明朗,本人已尝试做了一个,可以到知识库里下一下看,做的并不好,但长的蛮像的!本人并未实现网络登陆功能,以至很多朋友有被欺骗的感觉,本人在这说明:已经在程序说明部分说明并未实现网络功能,如果对登陆器,或外挂比较感兴趣可以从网络上搜索一些资料,应该有的下载!

      3.登陆时任务栏图标

      这个可能对网速慢的朋友可能会注意到,这又是QQ花心思的地方。

      4.上线时的声音及消息显示时的人物跳动

      任务栏的图标也跟着改变啦,可以近ctrl+alt+z快捷键迅速查看留言啦!

      5.快捷方便的抽屉菜单

      我个人非常欣赏该功能,所以讲解的过程中本人会做最详细的阐述!

      6.发送消息对话框

      消息来时候的很清脆的声音及快速的回显!

      7.在桌面顶端上悬挂QQ

      这使QQ占用很少的桌面空间,值得注意!

      将在下面重点讲述实现3到7功能,并逐一实现!
     三、登陆时任务栏图标的动态显示

      网络上关于在任务栏上添加图标的代码说明不少,本人也是参考了书书籍和借签了一部分代码后,并做了以下模拟处理。

      基础部分:

    NOTIFYICONDATA nid;
    //此处在类中定义

    void CMyQQDlg::DisplayInTask()
    {
    if(isDisplayInTask)
    {
    //初始化nid
    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.hWnd =this->m_hWnd;
    nid.uID = IDR_QQMENU;
    nid.uFlags = NIF_ICON | NIF_TIP|NIF_MESSAGE ;
    nid.hIcon = m_hIcon;
    strcpy (nid.szTip, "任务栏图标");
    nid.uCallbackMessage=WM_DISPLAYTASKICON;
    Shell_NotifyIcon(NIM_ADD,&nid);
    isDisplayInTask=FALSE;
    }
    else
    {
    Shell_NotifyIcon(NIM_DELETE,&nid);
    isDisplayInTask=true;
    }
    }
    关于Shell_NotifyIcon这个函数共有三种操作,分别为NIM_ADD, NIM_MODIFY, NIM_DELETE,为系统函数,大家对这个不熟悉也不要紧,也就是实现在任务栏上显示的功能,在程序的OnInitDialog函数中添加如下代码:

    isDisplayInTask=true;
    DisplayInTask(); //显示到任务栏里面去;
    Sleep(500);
    OnOutline();
    Sleep(500);
    OnHidden();
    Sleep(500);
    OnOutline();
    Sleep(500);
    OnHidden();

      仅仅是个模拟,并没有考虑到程序的具体操作过程,也可以定义一个时间,然后用 KillTime 函数终止也可以!

      四、上线时的声音及消息显示时的人物跳动

      本人并未实现人物跳动,并不知道是切换图片,还是更改图片的位置,所以此功能有待各位的指点!

      五、动感十足的抽屉菜单

      我对QQ的这个菜单印象特深,犹其是配的“刷”的声音,充分体验到QQ的生动!下面就详细介绍自己是如何一步步实现的:
        

      说明:

      在程序的一开始就获得最顶端按钮的位置:

    // 将该对话框放置到右上角;
    GetWindowRect(&dlgrect);
    MoveWindow(GetSystemMetrics(SM_CXSCREEN)-dlgrect.Width()-20, 0,
    dlgrect.Width(), dlgrect.Height(), true);
    //////////////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////////////////
    // 获取得第一个按钮和最后一个按钮的位置
    GetDlgItem(IDC_QQFRIEND)->GetWindowRect(&rect0);
    ScreenToClient(&rect0);
    GetDlgItem(IDC_QQQUN)->GetWindowRect(&rect1);
    ScreenToClient(&rect1);

      用一个重要的函数分别处理当按下不同铵钮时的反应:

    void CMyQQDlg::ChangeView()
    {
     // 开始对按钮进行各个处理

     if(TopButtonNum!=1&&clicknum==1)
     {
      //////////////////////////////////////////////////////////////////////////
      // QQ好友按钮已经置于最上层
      // 所以无需移动
      // 其余全置于下面
      m_QQothers.MoveWindow(0, rect1.bottom,
      rect0.Width(), rect0.Height(), true);
      m_QQqun.MoveWindow(0, rect1.bottom-rect0.Height(),
      rect0.Width(), rect0.Height(), true);
     
      //////////////////////////////////////////////////////////////////////////
      // QQ好友
      if(isBigFace)
      {
       m_List1.SetImageList(&m_imagelist2, LVSIL_SMALL);
      }
      else
      {
       m_List1.SetImageList(&m_imagelist1, LVSIL_SMALL);
      }
      m_List1.DeleteAllItems();
      for(int i=1; i<34; i++)
      {
       m_List1.InsertItem(0xffff,"", -1);
       m_List1.InsertItem(0xffff,"\n"+myClass[i-1], i);
      }
      m_List1.InsertItem(0xffff,"", -1);
      //////////////////////////////////////////////////////////////////////////
      // 显示该栏目的下的QQ好友, 隐藏其它栏目;
      m_List1.ShowWindow(SW_SHOW);
      m_List2.ShowWindow(SW_HIDE);
      treeCtrl.ShowWindow(SW_HIDE);
      return;
     }

     if(TopButtonNum!=2&&clicknum==2)
     {
      // 先将排在它上面的按钮置上不闻;
      m_QQqun.MoveWindow(0, rect0.bottom,
      rect0.Width(), rect0.Height(), true);
      // 将排在它后面的按钮置后;
      m_QQothers.MoveWindow(0, rect1.bottom,
      rect0.Width(), rect0.Height(), true);

      // 显示该栏目的下的QQ群, 隐藏其它栏目;
      m_List1.ShowWindow(SW_HIDE);
      m_List2.ShowWindow(SW_HIDE);
      treeCtrl.ShowWindow(SW_SHOW);
      return;
     }

     //////////////////////////////////////////////////////////////////////////
     //* ignoring these codes;
     if(TopButtonNum!=3&&clicknum==3)
     {
      // 全部挤到上面去
      m_QQfriend.MoveWindow(0, rect0.top,
      rect0.Width(), rect0.Height(), true);

      m_QQqun.MoveWindow(0, rect0.bottom,
      rect0.Width(), rect0.Height(), true);

      m_QQothers.MoveWindow(0, rect0.bottom+rect0.Height(),
      rect0.Width(), rect0.Height(), true);

      //////////////////////////////////////////////////////////////////////////
      // 随机产生最近联系人
      m_List2.DeleteAllItems();
      for(int i=1; i<18; i++)
      {
       int j=rand()%33;
       m_List2.InsertItem(0xffff,"", -1);
       m_List2.InsertItem(0xffff,"\n我的朋友"+i, j);
      }
      m_List2.InsertItem(0xffff,"", -1);
      // 显示该栏目的下的QQ联系人或其它, 隐藏其它栏目;
      m_List1.ShowWindow(SW_HIDE);
      treeCtrl.ShowWindow(SW_HIDE);
      m_List2.ShowWindow(SW_SHOW);
      return;
     }
     //*/
     //////////////////////////////////////////////////////////////////////////
    另外大家在处理的过程中,可以在QQ好友和最后一个菜单,这里是最近联系人,可以加一个picture控件,将其设置成很细小,且不可视,定制在对话框的最上和最下位置,这样你就可以随时获得你所需要的按钮移向的位置,另外每个按钮的长宽相同,方便啦处理!

      六、发送消息对话框

      在这里只讲两部分:

      1.动态产生消息对话框

      2.按Ctrl+Enter键发送消息

      动态产生对话框,一般是先在资源中建立一个对话框模板,用Create函数产生一个对话框实例, 本程序是这样实现的:

    void CMyQQDlg::OnDblclkMyFriend(NMHDR* pNMHDR, LRESULT* pResult)
    {
     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
     int m_nCurrentSel = pNMListView->iItem;
     CString str;
     str=m_List1.GetItemText(m_nCurrentSel, NULL);

     CQQSendMessage *dlg=new CQQSendMessage;
     dlg->msg=str;

     dlg->Create(IDD_QQ_MESSAGE);
     dlg->SetWindowText("你正在与"+str+"聊天当中");
     dlg->SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), false);
     dlg->ShowWindow(SW_SHOW);

     *pResult = 0;
    }

      第2个键盘发送可以做如下处理:

    BOOL CQQSendMessage::PreTranslateMessage(MSG* pMsg)
    {
     // TODO: Add your specialized code here and/or call the base class
     if(pMsg->message==WM_KEYDOWN)
     {
      if(pMsg->wParam==VK_RETURN && GetKeyState(VK_CONTROL)&0x80)
      {
       {
        //处理发送对话的内容
        OnSend();
        return 1;
       }
      }
     }
     return CDialog::PreTranslateMessage(pMsg);
    }

      这样你按下Ctrl+Enter键后就会处理OnSend()函数,这样就可以实现快捷键发送消息啦!

      七、在桌面顶端上悬挂QQ

      这样的实现不知道满意不满意,可以用一个时间片,时刻测试鼠标的坐标,并判断它所处的范围,以判断是否悬挂对话框!

      悬挂QQ,并不是让其隐藏而是要留下只剩下一根细线,当鼠标移到这根细线的时候,就立刻反显示!悬挂代码如下:

    LPPOINT pt=new CPoint;
    GetCursorPos(pt);
    CRect rect;
    GetWindowRect(&rect);
    if(rect.PtInRect(*pt))
    {
     if(rect.top<=2)
     {
      MoveWindow(rect.left, rect.top,
      dlgrect.Width(), dlgrect.Height(), true);
     }
    }
    else
    {
     if(rect.top<=2)
     {
      MoveWindow(rect.left, 0, rect.Width(), 3, true);
     }
    }
    delete pt;


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    ---人之所以能,是相信能!!

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2010/11/16 11:40:00
     
     GoogleAdSense水瓶座1984-2-14
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 点击这里发送电邮给Google AdSense 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/25 16:24:11

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    109.375ms