⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csdn_文档中心_myicq情景分析.htm

📁 csdn10年中间经典帖子
💻 HTM
📖 第 1 页 / 共 5 页
字号:
            name=第一个情景></A>1.第一个情景:用户注册<BR>这个情景主要用到的数据结构:<BR>(1)IcqUser<BR>让我们先来看IcqUser的代码,<BR>class 
            IcqUser : public IcqInfo {<BR>public:<BR>IcqUser();<BR><BR>void 
            load(DBInStream &amp;in);<BR>void save(DBOutStream 
            &amp;out);<BR><BR>string passwd;<BR>uint8 auth;<BR>};<BR>class 
            IcqInfo : public ContactInfo, public DBSerialize 
            {<BR>public:<BR>IcqInfo();<BR>virtual ~IcqInfo() {}<BR><BR>void 
            save(DBOutStream &amp;out);<BR>void load(DBInStream 
            &amp;in);<BR>};<BR>class ContactInfo {<BR>public:<BR>QID 
            qid;<BR>string nick;<BR>uint8 face;<BR>uint8 gender;<BR>uint8 
            age;<BR>string country;<BR>string province;<BR>string 
            city;<BR><BR>string email;<BR>string address;<BR>string 
            zipcode;<BR>string tel;<BR><BR>string name;<BR>uint8 
            blood;<BR>string college;<BR>string profession;<BR>string 
            homepage;<BR>string intro;<BR><BR>uint32 status;<BR>};<BR>class 
            DBSerialize {<BR>public:<BR>virtual void save(DBOutStream &amp;out) 
            = 0;<BR>virtual void load(DBInStream &amp;in) = 
            0;<BR>};<BR>很明显可以看出它是用来存储人员基本信息的数据结构,它有两个方法save和load,我们来看看它们的代码,<BR>可以想出它是用来将数据成员存入数据库和从数据库读出.DBSerialize是一个抽象类。 
            <BR>void IcqUser::load(DBInStream 
            &amp;in)<BR>{<BR>IcqInfo::load(in);<BR><BR>in &gt;&gt; passwd 
            &gt;&gt; auth;<BR>}<BR><BR>void IcqUser::save(DBOutStream 
            &amp;out)<BR>{<BR>IcqInfo::save(out);<BR><BR>out &lt;&lt; passwd 
            &lt;&lt; auth;<BR>}<BR>void IcqInfo::load(DBInStream 
            &amp;in)<BR>{<BR>in &gt;&gt; face &gt;&gt; nick &gt;&gt; age 
            &gt;&gt; gender &gt;&gt; country &gt;&gt; province &gt;&gt; 
            city;<BR>in &gt;&gt; email &gt;&gt; address &gt;&gt; zipcode 
            &gt;&gt; tel;<BR>in &gt;&gt; name &gt;&gt; blood &gt;&gt; college 
            &gt;&gt; profession &gt;&gt; homepage &gt;&gt; 
            intro;<BR>}<BR><BR>void IcqInfo::save(DBOutStream 
            &amp;out)<BR>{<BR>out &lt;&lt; face &lt;&lt; nick &lt;&lt; age 
            &lt;&lt; gender &lt;&lt; country &lt;&lt; province &lt;&lt; 
            city;<BR>out &lt;&lt; email &lt;&lt; address &lt;&lt; zipcode 
            &lt;&lt; tel;<BR>out &lt;&lt; name &lt;&lt; blood &lt;&lt; college 
            &lt;&lt; profession &lt;&lt; homepage &lt;&lt; 
            intro;<BR>}<BR>/*<BR>* Utility class that reads from or writes to a 
            data block<BR>*/<BR>class DBOutStream {<BR>public:<BR>DBOutStream() 
            {<BR>cursor = data;<BR>}<BR>char *getData() {<BR>return 
            data;<BR>}<BR>int getSize() {<BR>return (cursor - 
            data);<BR>}<BR><BR>DBOutStream &amp;operator &lt;&lt;(uint8 
            b);<BR>DBOutStream &amp;operator &lt;&lt;(uint16 w);<BR>DBOutStream 
            &amp;operator &lt;&lt;(uint32 dw);<BR>DBOutStream &amp;operator 
            &lt;&lt;(const char *str);<BR>DBOutStream &amp;operator 
            &lt;&lt;(StrList &amp;strList);<BR>DBOutStream &amp;operator 
            &lt;&lt;(const string &amp;str) {<BR>return operator 
            &lt;&lt;(str.c_str());<BR>}<BR>DBOutStream &amp;operator 
            &lt;&lt;(const QID &amp;qid) {<BR>return (*this &lt;&lt; qid.uin 
            &lt;&lt; qid.domain);<BR>}<BR><BR>private:<BR>char 
            data[MAX_BLOCK_SIZE];<BR>char *cursor;<BR>};<BR>class DBInStream 
            {<BR>public:<BR>DBInStream(void *d, int n) {<BR>cursor = data = 
            (char *) d;<BR>datalen = n;<BR>}<BR>DBInStream &amp;operator 
            &gt;&gt;(uint8 &amp;b);<BR>DBInStream &amp;operator &gt;&gt;(uint16 
            &amp;w);<BR>DBInStream &amp;operator &gt;&gt;(uint32 
            &amp;dw);<BR>DBInStream &amp;operator &gt;&gt;(string 
            &amp;str);<BR>DBInStream &amp;operator &gt;&gt;(StrList 
            &amp;strList);<BR>DBInStream &amp;operator &gt;&gt;(QID &amp;qid) 
            {<BR>return (*this &gt;&gt; qid.uin &gt;&gt; 
            qid.domain);<BR>}<BR><BR>private:<BR>char *data;<BR>char 
            *cursor;<BR>int datalen;<BR>};<BR><BR>(2)IcqOption<BR>class 
            IcqOption : public DBSerialize 
            {<BR>public:<BR>IcqOption();<BR>virtual ~IcqOption();<BR><BR>void 
            load(DBInStream &amp;in);<BR>void save(DBOutStream 
            &amp;out);<BR>void playSound(int sound, IcqContact *c = 
            NULL);<BR><BR>bitset&lt;NR_USER_FLAGS&gt; flags; // System option 
            flags<BR>uint32 hotKey;<BR>string soundFiles[NR_SOUNDS];<BR>string 
            host;<BR>uint16 port;<BR>string autoReplyText;<BR>string 
            quickReplyText;<BR>uint32 autoStatus;<BR>uint32 
            autoStatusTime;<BR>string skin;<BR><BR>// Proxy stuff<BR>uint8 
            proxyType;<BR>ProxyInfo 
            proxy[NR_PROXY_TYPES];<BR><BR>private:<BR>bool playSound(const char 
            *file);<BR>};<BR>存储各种选项<BR><BR>在这个情景里,我们假定用户已经点击网络设置那一页的下一步按钮。进入以下代码中:<BR>BOOL 
            CRegFinishDlg::OnSetActive() <BR>{<BR>206 CRegWizard *wiz = 
            (CRegWizard *) GetParent();<BR>207 
            wiz-&gt;getData(&amp;icqLink-&gt;myInfo, 
            &amp;icqLink-&gt;options);<BR><BR>首先206行取到上个窗口的指针,就是属性表的指针,进而调用它的函数getData。进入代码:<BR>CRegFinishDlg::OnSetActive()--&gt;CRegWizard::getData()<BR><BR>54 
            void CRegWizard::getData(IcqUser *info, IcqOption *options) <BR>55 { 
            <BR>56 if (modeDlg.m_mode == 0) <BR>57 info-&gt;qid = qid; <BR>58 
            else { <BR>59 info-&gt;qid.uin = modeDlg.m_uin; <BR>60 
            info-&gt;qid.domain = finishDlg.domain; <BR>61 } <BR>62 <BR>63 
            info-&gt;face = basicDlg.m_pic; <BR>64 info-&gt;age = 
            basicDlg.m_age; <BR>65 info-&gt;nick = basicDlg.m_nick; <BR>66 
            info-&gt;gender = basicDlg.m_gender; <BR>67 info-&gt;country = 
            basicDlg.m_country; <BR>68 info-&gt;province = basicDlg.m_province; 
            <BR>69 info-&gt;city = basicDlg.m_city; <BR>70 <BR>71 info-&gt;email 
            = commDlg.m_email; <BR>72 info-&gt;address = commDlg.m_address; 
            <BR>73 info-&gt;zipcode = commDlg.m_zipcode; <BR>74 info-&gt;tel = 
            commDlg.m_tel; <BR>75 <BR>76 info-&gt;name = miscDlg.m_name; <BR>77 
            info-&gt;blood = miscDlg.m_blood; <BR>78 info-&gt;college = 
            miscDlg.m_college; <BR>79 info-&gt;profession = 
            miscDlg.m_profession; <BR>80 info-&gt;homepage = miscDlg.m_homepage; 
            <BR>81 info-&gt;intro = miscDlg.m_intro; <BR>82 <BR>83 
            info-&gt;passwd = (modeDlg.m_mode == 0 ? basicDlg.m_passwd : 
            modeDlg.m_passwd);<BR>84 <BR>85 if (options) { <BR>86 
            options-&gt;host = networkDlg.m_host; <BR>87 options-&gt;port = 
            networkDlg.m_port; <BR>88 options-&gt;flags.set(UF_USE_PROXY, 
            networkDlg.m_useProxy); <BR>89 options-&gt;proxyType = 
            networkDlg.m_proxyType; <BR>90 for (int i = 0; i &lt; 
            NR_PROXY_TYPES; ++i) <BR>91 options-&gt;proxy[i] = 
            networkDlg.proxyInfo[i]; <BR>92 } <BR>93 
            }<BR>此方法传入两个结构IcqUser和IcqOption以上有说明<BR>第56行到第61行,主要给qid赋值,modeDlg.m_mode如选中新申请一个QQ号则为0,选中已有QQ号为1,本情景为0,也就是将info-&gt;qid 
            = qid; qid是IcqWindow的一个公有变量QID qid</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">class QID 
            {<BR>public:<BR>QID() {<BR>uin = 0;<BR>}<BR>bool operator ==(const 
            QID &amp;qid) {<BR>return (uin == qid.uin &amp;&amp; 
            !strcasecmp(domain.c_str(), qid.domain.c_str()));<BR>}<BR>bool 
            isAdmin() {<BR>return (uin == ADMIN_UIN &amp;&amp; 
            domain.empty());<BR>}<BR>char *toString();<BR>bool parse(const char 
            *qid);<BR><BR>uint32 uin;<BR>string 
            domain;<BR>};<BR>剩下的代码就是根据这几个对话框所添入的东东给全局变量icqLink中的IcqUser和IcqOption的各成员变量赋值.<BR>回到RegFinishDlg::OnSetActive() 
            中第208行开始,<BR>208 wiz-&gt;qid.uin = 0;<BR>209<BR>210 CString 
            str;<BR>211 str.LoadString(IDS_PLEASE_WAIT);<BR>212 
            SetDlgItemText(IDC_STATUS, str);<BR>213 
            str.LoadString(IDS_REG_REGISTERING);<BR>214 
            SetDlgItemText(IDC_STATUS_DETAIL, str);<BR>215 
            wiz-&gt;SetWizardButtons(PSWIZB_DISABLEDFINISH);<BR>216<BR>217 
            m_faceLabel.start();<BR>218<BR>219 resolveHost();<BR>220<BR>221 
            return 
            CPropertyPage::OnSetActive();<BR>}<BR>这行将MyIcq号赋为0,211-218设置一些状态,219进入CRegFinishDlg::resolveHost()</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void 
            CRegFinishDlg::resolveHost()<BR>{<BR>172&nbsp;&nbsp; CRegWizard *wiz 
            = (CRegWizard *) GetParent();<BR>173&nbsp;&nbsp; const char *host = 
            wiz-&gt;networkDlg.m_host;<BR>174<BR>175&nbsp;&nbsp; if 
            (wiz-&gt;networkDlg.m_useProxy &amp;&amp; 
            !wiz-&gt;networkDlg.m_proxyResolve)<BR>176&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            getUdpSession()-&gt;connect(host, 
            wiz-&gt;networkDlg.m_port);<BR>177&nbsp;&nbsp; else 
            {<BR>178&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct in_addr 
            addr;<BR>179&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addr.s_addr = 
            inet_addr(host); 
            //将x.x.x.x转换为无符号整数给addr.s_addr<BR>180&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            if (addr.s_addr != 
            INADDR_NONE)<BR>181&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            onHostFound(addr);<BR>182&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            else<BR>183&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            ((CIcqDlg *) 
            AfxGetMainWnd())-&gt;getHostByName(host);<BR>&nbsp;&nbsp;&nbsp; 
            }<BR>}</P>
            <P 
            style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">175行看出在网络设置对话框中有没有选使用代理服务器,本情景中没选到178行将用户选定的地址作为参数传给onHostFound(addr);进入onHostFound</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void 
            CRegFinishDlg::onHostFound(struct in_addr 
            &amp;addr)<BR>{<BR>163&nbsp;&nbsp; if (addr.s_addr != INADDR_NONE) 
            {<BR>164&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRegWizard *wiz = 
            (CRegWizard *) 
            GetParent();<BR>165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            getUdpSession()-&gt;connect(inet_ntoa(addr), 
            wiz-&gt;networkDlg.m_port);<BR>166&nbsp;&nbsp; } 
            else<BR>167&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
onTimeout();<BR>}</P>
            <P 
            style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">在165行调用函数getUpdSession()-&gt;connect传入参数是用户输入的地址和端口。</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">inline UdpSession 
            *getUdpSession()<BR>{<BR>&nbsp;&nbsp;&nbsp; return 
            icqLink-&gt;udpSession;<BR>}</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void 
            UdpSession::connect(const char *host, uint16 
            port)<BR>{<BR>090&nbsp;&nbsp; IcqOption &amp;options = 
            icqLink-&gt;options;<BR>091<BR>092&nbsp;&nbsp; // Connect using 
            proxy<BR>093&nbsp;&nbsp; if (options.flags.test(UF_USE_PROXY)) 
            {<BR>094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (options.proxyType 
            == 
            PROXY_SOCKS)<BR>095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            socksProxy.start(options.proxy[PROXY_SOCKS], 
            sock);<BR>096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if 
            (options.proxyType == 
            PROXY_HTTP)<BR>097&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            httpProxy.start(host, options.proxy[PROXY_HTTP]);&nbsp;&nbsp; } 
            <BR>099&nbsp;&nbsp; else{&nbsp;&nbsp; //not use proxy</P>
            <P 
            style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            sockaddr_in addr;<BR>101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            socklen_t len = 
            sizeof(addr);<BR>103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            memset(&amp;addr, 0, 
            sizeof(addr));<BR>104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            addr.sin_family = 
            AF_INET;<BR>105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addr.sin_port = 
            htons(port);<BR>106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            addr.sin_addr.s_addr = 
            inet_addr(host);<BR>107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            ::connect(sock, (sockaddr *) &amp;addr, 
            len);<BR>109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getsockname(sock, 
            (sockaddr *) &amp;addr, 
            &amp;len);<BR>110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; realIP = 
            ntohl(addr.sin_addr.s_addr);<BR>112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            icqLink-&gt;onConnect(true);</P>
            <P 
            style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            }<BR>}</P>
            <P 
            style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">首先判断有没有用proxy本情景中没有用所以到100行调用几个SOCKET函数连接传入的服务器及端口,将真实IP存放在realIP中,然后调用icqLink-&gt;onConnect(true);这个函数是一个虚函数,</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">CicqDlg类改写了它 
            ,所以程序进入CIcqDlg::onConnect</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">void 
            CIcqDlg::onConnect(bool success)<BR>{<BR>292 IcqWindow *win = 
            findWindow(WIN_REG_WIZARD);</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">进入findWindow</P>
            <P style="MARGIN-BOTTOM: 0px; MARGIN-TOP: 0px">IcqWindow 
            *IcqLink::findWindow(int type, QID *qid, uint32 
            seq)<BR>{<BR>&nbsp;&nbsp;&nbsp; PtrList::iterator 
            it;<BR>&nbsp;&nbsp;&nbsp; for (it = windowList.begin(); it != 
            windowList.end(); ++it) 
            {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IcqWindow *win = 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -