﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-&amp;豪-文章分类-MFC</title><link>http://www.cppblog.com/qywyh/category/5228.html</link><description>豪-&gt;blog</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 17:23:13 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 17:23:13 GMT</pubDate><ttl>60</ttl><item><title>【转】MFC时候使用全局变量</title><link>http://www.cppblog.com/qywyh/articles/33003.html</link><dc:creator>豪</dc:creator><author>豪</author><pubDate>Thu, 27 Sep 2007 03:39:00 GMT</pubDate><guid>http://www.cppblog.com/qywyh/articles/33003.html</guid><wfw:comment>http://www.cppblog.com/qywyh/comments/33003.html</wfw:comment><comments>http://www.cppblog.com/qywyh/articles/33003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qywyh/comments/commentRss/33003.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qywyh/services/trackbacks/33003.html</trackback:ping><description><![CDATA[来自:http://zhidao.baidu.com/question/4090232.html<br><br>用MFC制作的工程由很多文件构成，它不能象一般C++程序那样随意在类外定义全局变量，在这里要想定义能被工程内多个文件共享的全局变量和函数必须用一些特殊方法才行。实际上有多种方法可以实现，这里只介绍两种方法。 <br><br>一、在应用程序类中定义 <br><br>用MFC生成的工程中都有一个名为CxxxApp的类，它派生于CWinApp类。这个类主要进行程序的初始化，生成文档、视图对象等工作。我们可以把需要全局访问的变量和函数定义为这个类的成员变量和成员函数，就可以实现全局访问了。 <br><br>从严格意义上讲，这种变量和函数并不是全局的，因为它仍然只是类中的成员，只是由于我们很容易获得CxxxApp类的指针，所以我们可以在文档、视图、对话框以及各种自定义类中访问到它们，达到与全局变量类似的效果。访问时用函数&#8220;AfxGetApp()&#8221;获得CxxxApp类的指针，用&#8220;AfxGetApp()-&gt;成员&#8221;访问变量或函数。 <br><br>例： <br><br>Test.h：（应用程序类头文件） <br><br>class CTestApp : public CWinApp <br>{ <br>public: <br>int x; //全局变量 <br>int f(int y); //全局函数 <br>&#8230;&#8230;&#8230;&#8230; <br>}; <br><br>Test.cpp：（应用程序类程序文件） <br><br>int CTestApp::f(int y) //全局函数定义 <br>{ <br>y++; <br>return y; <br>} <br><br>定义在CTestApp类中的变量和函数可以在其它类中被访问。比如在视图的某函数中要访问变量x和函数f()： <br><br>void CTestView::xyz() <br>{ <br>CTestApp *app = (CTestApp *)AfxGetApp(); //生成指向应用程序类的指针 <br>app-&gt;x = 0; //访问变量x <br>int z = app-&gt;f(1); //访问函数f() <br>&#8230;&#8230;&#8230;&#8230; <br>} <br><br>这样，变量x和函数f()可以视作为全局的。 <br><br>用这种方法实现的全局变量和全局函数虽比较简单，但也有缺点，一是访问不太方便，每次都需要获取应用程序类的指针；再就是把一些与应用程序类本身无关的变量和函数放在里面，使这个类看上去怪怪的，破坏了类的封装。 <br><br>二、用静态变量和静态函数实现 <br><br>很喜欢API函数的那种调用方法，不论在哪个类中只要用&#8220;::API函数&#8221;就可以调用了。合理利用静态类型(static)可以实现与此相似的全局变量和全局函数。 <br><br>静态变量和静态函数有如下性质： <br><br>若在一个类中用关键字static声明数据成员，则这个数据成员就只存在一个拷贝，无论该类创建了多少个实例，它始终只存在一个，即使该类的实例一个也没创建，它也存在。 <br><br>若在一个类中用关键字static声明函数，该函数可以用&#8220;类名::函数名&#8221;方式访问，无需引用该类的实例，甚至这个类的实例可以不存在。 <br><br>利用这个性质实现的全局变量和函数使用起来很方便。 <br><br>值得注意的是，全局变量和全局函数最好集中封装，不要在文档、视图等类内部定义，这样用起来才有全局的感觉。 <br><br>例： <br><br>1、添加一个没有基类的新类，设类名起为CPublic，姑且称之为公用类 <br><br>单击&#8220;Insert&#8221;菜单下的&#8220;New Class&#8221;命令，选择&#8220;Class type&#8221;为&#8220;Generic Class&#8221;，在&#8220;Name&#8221;栏中填入类名&#8220;CPublic&#8221;，单击&#8220;OK&#8221;，则新类建立完毕。 <br><br>2、包含公用类的头文件，使各个类都能访问它 <br><br>CPublic的头文件应包含在应用程序类的头文件中，这样在其它类中引用CPublic类时就不需要再包含了。 <br><br>Test.h：（应用程序类头文件） <br><br>#include "Public.h" //包含公用类头文件 <br><br>class CTestApp : public CWinApp <br>{ <br>&#8230;&#8230;&#8230;&#8230; <br>}; <br><br>3、在公用类中定义全局变量和全局函数，均使用static修饰，静态变量还必须在类外定义和初始化 <br><br>Public.h：（公用类头文件） <br><br>class CPublic <br>{ <br>public: <br>CPublic(); <br>virtual ~CPublic(); <br><br>public: <br>static int x; //全局变量 <br>static int time; //全局变量 <br>static int f(int y); //全局函数 <br>&#8230;&#8230;&#8230;&#8230; <br>} <br><br>在公用类中对静态变量进行初始化和定义函数体： <br><br>Public.cpp：（公用类程序文件） <br><br>int CPublic::x = 0; //初始化全局变量 <br>int CPublic::time; //定义全局变量 <br><br>CPublic::CPublic() <br>{ <br><br>} <br><br>CPublic::~CPublic() <br>{ <br><br>} <br><br>int CPublic::f(int y) //全局函数，这里不要再加static <br>{ <br>y++; <br>return y; <br>} <br><br>4、全局量的使用 <br><br>使用变量：CPublic::变量名 <br><br>使用函数：CPublic::函数() <br><br>如在视图的某函数中访问变量x和函数f()： <br><br>void CTestView::xyz() <br>{ <br>CPublic::x = 0; //访问变量x <br>CPublic::time = CPublic::f(1); //访问函数f() <br>&#8230;&#8230;&#8230;&#8230; <br>} <br><br>在其它类中访问x、time和f()的方法与此相同。 <br><br>5、几点注意： <br><br>① 由于静态量可独立于类存在，不需要生成CPublic类的实例。 <br><br>② 静态数据成员的定义和初始化必须在类外进行，如例中x的初始化；变量time虽然没有初始化，但也必须在类外进行定义。由于没有生成CPublic类的实例，所以它的构造函数和析构函数都不会被执行，在里面做什么工作都没有什么意义。 <br><br>③ 如果静态函数需要访问CPublic类内的变量，这些变量也必须为静态的。因为非静态量在不生成实例时都不会存在。 如： <br><br>class CPublic <br>{ <br>public: <br>int x; //内部变量 <br>static int f(int y) //全局函数 <br>{ <br>x++; <br>return x; <br>}; <br>&#8230;&#8230;&#8230;&#8230; <br>}; <br><br>这里x虽为类内成员，但如果不生成CPublic类的实例，就会出现函数f()存在，而变量x不存在的问题。 <br><br>总之，用没有实例的类管理全局量是一个不错的选择，它具有集中管理，使用方便的好处。当然，除非特别必要，全局量还是少用为好，一个好的编程者决不会随意滥用全局量的，一个封装做得不好的程序，在修改维护时会让你吃足苦头。 
<img src ="http://www.cppblog.com/qywyh/aggbug/33003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qywyh/" target="_blank">豪</a> 2007-09-27 11:39 <a href="http://www.cppblog.com/qywyh/articles/33003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】在MFC中使用Tab Control</title><link>http://www.cppblog.com/qywyh/articles/32869.html</link><dc:creator>豪</dc:creator><author>豪</author><pubDate>Tue, 25 Sep 2007 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/qywyh/articles/32869.html</guid><wfw:comment>http://www.cppblog.com/qywyh/comments/32869.html</wfw:comment><comments>http://www.cppblog.com/qywyh/articles/32869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qywyh/comments/commentRss/32869.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qywyh/services/trackbacks/32869.html</trackback:ping><description><![CDATA[<p>转自：<a href="http://hi.baidu.com/blue_never_died/blog/item/04398694249ef71ed21b7007.html"><font color=#0066a7>http://hi.baidu.com/blue_never_died/blog/item/04398694249ef71ed21b7007.html</font></a> <br><br>说实话，我刚开始看见Tab Control的时候，觉得很简单。哪知道用了一下，才发现自己错了。</p>
<p>要用好它，还是需要一些技巧的。经过网上搜索资料，以及我自己的摸索，把一些要点记录在这里。</p>
<p>Tab Control的运行效果有点像Property Sheet，但两者还是有一些区别。我的理解就是Property Sheet主要用在对话框中，对数据进行进行分类管理。而Tab Control使用范围更广一些，既可以用在对话框，也可以用在视图中，除了可以管理配置数据外，还可以对软件的组织进行规划，比如可以通过它来切换不同的视图等等。</p>
<p>当然这不是没有代价的，Tab Control的编程就比Property Sheet的复杂很多。</p>
<p>&nbsp;我最初有点搞不懂，如何在Tab Control中使用不同的Page，就象Property Page一样，Tab Control并没有提供便利的机制让你轻松做到这一点。还好，VC是最棒的，撒花～通过变通的方法还是可以做到这一点。</p>
<p>不罗嗦了，上代码。</p>
<p>假如我现在有个SDI程序，View是Form View，想在上面放个Tab Control，包含两个Page。现在让我们来看看应该怎样处理。</p>
<p>首先当然要增加一个Tab Control资源，然后利用Class Wizard，在View中增加一个Control变量。</p>
<p>接着建立两个对话框资源，别忘了把Style改为Child，Border改为None。然后就可以在上面加其他控件了。</p>
<p>接着利用Class Wizard，分别为这两个对话框建立两个类，比如CPage1和CPage2。</p>
<p>然后在View类头文件中，加入这两个对话框对象。同时增加一个变量int m_CurSelTab，用了表明是哪个Page即将被切换。</p>
<p>为了避免用户在切换Tab时，程序对Tab Index的枚举，可以利用数组来做这个事情。</p>
<p>在View的初始化函数中需要把CPage1、CPage2和Tab Control关联起来，并保存页面地址，设置初始页面，等等。</p>
<p>void CTab_testView::OnInitialUpdate()<br>{<br>&nbsp;&nbsp; CFormView::OnInitialUpdate();<br>&nbsp;&nbsp; GetParentFrame()-&gt;RecalcLayout();<br>&nbsp;&nbsp; ResizeParentToFit();<br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //为Tab Control增加两个页面<br>&nbsp;&nbsp;&nbsp; m_tab.InsertItem(0, _T("First"));<br>&nbsp;&nbsp;&nbsp; m_tab.InsertItem(1, _T("Second"));<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //创建两个对话框<br>&nbsp;&nbsp;&nbsp; m_page1.Create(IDD_DIALOG1, &amp;m_tab);<br>&nbsp;&nbsp;&nbsp; m_page2.Create(IDD_DIALOG2, &amp;m_tab);</p>
<p>&nbsp;&nbsp;&nbsp; //设定在Tab内显示的范围<br>&nbsp;&nbsp;&nbsp; CRect rc;<br>&nbsp;&nbsp;&nbsp; m_tab.GetClientRect(rc);<br>&nbsp;&nbsp;&nbsp; rc.top += 20;<br>&nbsp;&nbsp;&nbsp; rc.bottom -= 8;<br>&nbsp;&nbsp;&nbsp; rc.left += 8;<br>&nbsp;&nbsp;&nbsp; rc.right -= 8;</p>
<p>&nbsp;&nbsp;&nbsp; m_page1.MoveWindow(&amp;rc);<br>&nbsp;&nbsp;&nbsp; m_page2.MoveWindow(&amp;rc);</p>
<p>&nbsp;&nbsp;&nbsp; //把对话框对象指针保存起来<br>&nbsp;&nbsp;&nbsp; pDialog[0] = &amp;m_page1;<br>&nbsp;&nbsp;&nbsp; pDialog[1] = &amp;m_page2;</p>
<p>&nbsp;&nbsp;&nbsp; //显示初始页面<br>&nbsp;&nbsp;&nbsp; pDialog[0]-&gt;ShowWindow(SW_SHOW);<br>&nbsp;&nbsp;&nbsp; pDialog[1]-&gt;ShowWindow(SW_HIDE);</p>
<p>&nbsp;&nbsp;&nbsp; //保存当前选择<br>&nbsp;&nbsp;&nbsp; m_CurSelTab = 0;<br>}</p>
<p>这里面需要注意的是，我用了一个CDialog指针数组来进行保存，数组的大小是Tab Control页面的个数，数组下标对应着每个页面的索引（这样方便快速存取）。</p>
<p>用户切换时，需要响应相关的消息。</p>
<p>void CTab_testView::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) <br>{<br>&nbsp;// TODO: Add your control notification handler code here<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pDialog[m_CurSelTab]-&gt;ShowWindow(SW_HIDE);<br>&nbsp;&nbsp;&nbsp; m_CurSelTab = m_tab.GetCurSel();<br>&nbsp;&nbsp;&nbsp; pDialog[m_CurSelTab]-&gt;ShowWindow(SW_SHOW);</p>
<p>&nbsp;*pResult = 0;<br>}</p>
<p>首先我们先把当前的页面隐藏起来，然后得到新的页面索引，最后就把相关页面显示出来即可。这比一个个去枚举简单多了。</p>
<p>还有一点比较有意思，那就是DDX/DDV机制的运用。要想获得Tab Control各个页面的数据，可以利用DDX/DDV机制，但需要注意，因为这是多个页面，所以需要显式调用多次。</p>
<p>void CTab_testView::OnButton1() <br>{<br>&nbsp;// TODO: Add your control notification handler code here<br>&nbsp;&nbsp;&nbsp; m_page1.UpdateData();<br>&nbsp;&nbsp;&nbsp; m_page2.UpdateData();<br>&nbsp;&nbsp;&nbsp; CString str1 = m_page1.m_str1;<br>&nbsp;&nbsp;&nbsp; CString str2 = m_page2.m_str2;<br>&nbsp;&nbsp;&nbsp; AfxMessageBox(str1);<br>&nbsp;&nbsp;&nbsp; AfxMessageBox(str2);<br>}</p>
<p>经过这几步处理，基本上我们就可以利用Tab Control的强大功能了。<br></p>
<img src ="http://www.cppblog.com/qywyh/aggbug/32869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qywyh/" target="_blank">豪</a> 2007-09-25 23:37 <a href="http://www.cppblog.com/qywyh/articles/32869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>