<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://wdllstudio.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fwdllstudio.spaces.live.com%2fcategory%2f%e8%ae%a1%e7%ae%97%e6%9c%ba%e4%b8%8e%2bInternet%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>WDLL Studio: 计算机与 Internet</title><description /><link>http://wdllstudio.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=cat%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA%25E4%25B8%258E%2bInternet</link><language>en-US</language><pubDate>Fri, 29 Aug 2008 04:31:09 GMT</pubDate><lastBuildDate>Fri, 29 Aug 2008 04:31:09 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://wdllstudio.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>449534861986366027</live:id><live:alias>wdllstudio</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>VC制作拉帘按钮</title><link>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!165.entry</link><description>&lt;div&gt;
&lt;p&gt;大家一定都用过Oicq，是不是觉得里面的拉帘按钮很炫，就是当我们点击好友，陌生人或黑名单时所需的内容就会自动出现在主窗口中，其中按钮有一种被拉起或拉下的感觉。现在我就叫大家作这种特效。
&lt;p&gt;第一：创建
&lt;p&gt;启动Visual C++ =〉New Project =&amp;gt; MFC AppWizard(exe) 假定AppName为Oicq
&lt;p&gt;在Step 1中选SDI,在Step 4中不选tool bar,status bar,printing选项，因为用不着。其余各步均按默认选项，创建了一个标准的SDI模板。
&lt;p&gt;第二：设计初始大小和窗口风格
&lt;p&gt;在CMainFrame::PreCreateWindow(CREATESTRUCT&amp;amp; cs)函数中加如下语句
&lt;p&gt;cs.style=WS_OVERLAPPEDWINDOW;//标准窗口类型&lt;br&gt;cs.lpszName=_T(&amp;quot;QQ&amp;quot;);        //标题&lt;br&gt;cs.hMenu=NULL;               //取消菜单&lt;br&gt;cs.cx=100;                   //初始宽100pixels&lt;br&gt;cs.cy=700;                   //初始长700pixels
&lt;p&gt;真么样，有点样子了吧，这只是刚开始，好戏还在后头，慢慢来。
&lt;p&gt;第三：添加按钮
&lt;p&gt;在COicqView中加入三个Button变量
&lt;p&gt;CButton myButton1;&lt;br&gt;CButton myButton2;&lt;br&gt;CButton myButton3;
&lt;p&gt;在COicqView中添加消息函数OnCreate(LPCREATESTRUCT lpCreateStruct),添加方法不在详述，利用ClassWizard。以后的消息函数均由ClassWizard添加。在OnCreate中加入下列语句 
&lt;p&gt;myButton1.Create(_T(&amp;quot;好友&amp;quot;), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,&lt;br&gt;CRect(0,0,100,20),this,IDC_BUTTON_GOODFRIEND);&lt;br&gt;//创建好友按钮&lt;br&gt;myButton2.Create(_T(&amp;quot;陌生人&amp;quot;), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,&lt;br&gt;CRect(0,20,100,40),this,IDC_BUTTON_STRANGER);&lt;br&gt;//创建陌生人按钮&lt;br&gt;myButton3.Create(_T(&amp;quot;黑名单&amp;quot;), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,&lt;br&gt;CRect(0,40,100,60),this,IDC_BUTTON_BLACKLIST);&lt;br&gt;//创建黑名单按钮
&lt;p&gt;记住在Resource.h中定义&lt;br&gt;#define IDC_BUTTON_GOODFRIEND 150&lt;br&gt;#define IDC_BUTTON_STRANGER 151&lt;br&gt;#define IDC_BUTTON_BLACKLIST 152
&lt;p&gt;下面加入按钮消息映射，在COicqView中加入三个函数GoodFriend(),Stranger(),BlackList(),分别处理单击三个按钮的消息。&lt;br&gt;afx_msg void GoodFriend();&lt;br&gt;afx_msg void BlackList();&lt;br&gt;afx_msg void Stranger();
&lt;p&gt;在OicqView.cpp中加映射 &lt;br&gt;ON_BN_CLICKED(IDC_BUTTON_GOODFRIEND, GoodFriend)&lt;br&gt;ON_BN_CLICKED(IDC_BUTTON_STRANGER, Stranger)&lt;br&gt;ON_BN_CLICKED(IDC_BUTTON_BLACKLIST, BlackList)&lt;br&gt;注意添加位置，在BEGIN_MESSAGE_MAP(COicqView, CView)和END_MESSAGE_MAP()之间。
&lt;p&gt;第四：准备移动
&lt;p&gt;这一步是关键的一步，它为以后的工作打好基础，在我看来这是非常重要的，要想清楚以后的需要。&lt;br&gt;1.添加相关宏定义到OicqView.h&lt;br&gt;#define UP 1        //定义按钮状态&lt;br&gt;#define DOWN 2&lt;br&gt;2.添加状态变量&lt;br&gt;int GoodFriendState;&lt;br&gt;int BlackListState;&lt;br&gt;int StrangerState;&lt;br&gt;3.添加三个CRect变量来表示三个按钮的位置&lt;br&gt;CRect Button1_Rect;&lt;br&gt;CRect Button2_Rect;&lt;br&gt;CRect Button3_Rect;&lt;br&gt;4.添加一个CSize的变量来表示客户区大小&lt;br&gt;SIZE OldClientSize;&lt;br&gt;5.初始化各变量在OnCreate函数中&lt;br&gt;OldClientSize.cx=100;&lt;br&gt;OldClientSize.cy=669;&lt;br&gt;GoodFriendState=UP;&lt;br&gt;StrangerState=UP;&lt;br&gt;BlackListState=UP;&lt;br&gt;6.在COicqView中添加函数GetPosition()来获得各个按钮的当前位置&lt;br&gt;void COicqView::GetPosition()&lt;br&gt;{&lt;br&gt;this-&amp;gt;myButton1.GetWindowRect(&amp;amp;Button1_Rect);//获得窗口坐标&lt;br&gt;ScreenToClient(&amp;amp;Button1_Rect);               //转化Client坐标 &lt;br&gt;this-&amp;gt;myButton2.GetWindowRect(&amp;amp;Button2_Rect);&lt;br&gt;ScreenToClient(&amp;amp;Button2_Rect);&lt;br&gt;this-&amp;gt;myButton3.GetWindowRect(&amp;amp;Button3_Rect);&lt;br&gt;ScreenToClient(&amp;amp;Button3_Rect);&lt;br&gt;&lt;br&gt;}&lt;br&gt;7.在OnCreate()中添加GetPosition()
&lt;p&gt;第五：移动
&lt;p&gt;这里只介绍GoodFriend函数的算法，Stranger函数和BlackList函数类似，详见代码下载。
&lt;table cellspacing=0 cellpadding=0 width="100%" bgcolor="#e0e0e0" border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt; COicqView::GoodFriend()&lt;br&gt;{&lt;br&gt;    &lt;font color="#0000ff"&gt;int&lt;/font&gt; i;&lt;br&gt;    &lt;font color="#0000ff"&gt;switch&lt;/font&gt;(StrangerState)&lt;br&gt;    {&lt;br&gt;    &lt;font color="#0000ff"&gt;case&lt;/font&gt; UP:&lt;br&gt;        &lt;font color="#0000ff"&gt;switch&lt;/font&gt;(BlackListState)&lt;br&gt;        {        &lt;br&gt;        &lt;font color="#0000ff"&gt;case&lt;/font&gt; UP:&lt;br&gt;            &lt;font color="#0000ff"&gt;for&lt;/font&gt;(i=Button3_Rect.top;i&amp;lt;=OldClientSize.cy-Button3_Rect.Height();i++)&lt;br&gt;            {&lt;br&gt;                myButton3.MoveWindow(Button3_Rect.left,i,Button3_Rect.Width(),Button3_Rect.Height(),1);&lt;br&gt;                ValidateRect(CRect(Button3_Rect.left,i-1,Button3_Rect.right,i));&lt;br&gt;                myButton2.MoveWindow(Button2_Rect.left,i-Button2_Rect.Height(),&lt;br&gt;                    Button2_Rect.Width(),Button2_Rect.Height(),1);&lt;br&gt;                ValidateRect(CRect(Button3_Rect.left,i-Button2_Rect.Height()-1,Button3_Rect.right,i));&lt;br&gt;             }&lt;br&gt;            &lt;font color="#0000ff"&gt;this&lt;/font&gt;-&amp;gt;GetPosition();&lt;br&gt;            StrangerState=DOWN;&lt;br&gt;            BlackListState=DOWN;&lt;br&gt;            &lt;font color="#0000ff"&gt;break&lt;/font&gt;;&lt;br&gt;            &lt;font color="#0000ff"&gt;case&lt;/font&gt; DOWN:&lt;br&gt;            &lt;font color="#0000ff"&gt;for&lt;/font&gt;(i=Button2_Rect.top;i&amp;lt;=Button3_Rect.top-Button2_Rect.Height();i++)&lt;br&gt;            {&lt;br&gt;                myButton2.MoveWindow(Button2_Rect.left,i,Button2_Rect.Width(),Button2_Rect.Height());&lt;br&gt;                ValidateRect(CRect(Button2_Rect.left,i-1,Button2_Rect.right,i));&lt;br&gt;            }&lt;br&gt;            &lt;font color="#0000ff"&gt;this&lt;/font&gt;-&amp;gt;GetPosition();&lt;br&gt;            StrangerState=DOWN;&lt;br&gt;            &lt;font color="#0000ff"&gt;break&lt;/font&gt;;&lt;br&gt;        }&lt;br&gt;        &lt;font color="#0000ff"&gt;case&lt;/font&gt; DOWN:&lt;br&gt;            &lt;font color="#0000ff"&gt;break&lt;/font&gt;;&lt;br&gt;    }&lt;br&gt;&lt;br&gt;}&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;两个关键函数&lt;br&gt;BOOL MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE );&lt;br&gt;BOOL ValidateRect( LPCRECT lpRect );&lt;br&gt;只要在准备移动部分都看懂了，这是一段不难懂的代码。关键是在MoveWindow后，要用ValidateRect使移动后的空白区域变为有效区。
&lt;p&gt;第六：OnSize函数
&lt;p&gt;运行后不难发现当改变窗口大小时按钮却大小不变，解决方法，添加OnSize消息函数用ClassWizard,在OnSize中加如下代码即时更新按钮大小。
&lt;p&gt;
&lt;table cellspacing=0 cellpadding=15 width="95%" align=center bgcolor="#f7f3f7" border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;void COicqView::OnSize(UINT nType, int cx, int cy) &lt;br&gt;{&lt;br&gt;    CView::OnSize(nType, cx, cy);&lt;br&gt;    if(cx!=OldClientSize.cx)&lt;br&gt;    { &lt;br&gt;        myButton1.MoveWindow(Button1_Rect.left,Button1_Rect.top,cx,Button1_Rect.Height());&lt;br&gt;        myButton2.MoveWindow(Button2_Rect.left,Button2_Rect.top,cx,Button2_Rect.Height());&lt;br&gt;        myButton3.MoveWindow(Button3_Rect.left,Button3_Rect.top,cx,Button3_Rect.Height());&lt;br&gt;    }&lt;br&gt;    this-&amp;gt;GetPosition();&lt;br&gt;    if(cy!=OldClientSize.cy)&lt;br&gt;    {&lt;br&gt;        if(DOWN==BlackListState)&lt;br&gt;        {&lt;br&gt;            myButton3.MoveWindow(Button3_Rect.left,cy-Button3_Rect.Height(),Button3_Rect.Width(),Button3_Rect.Height());&lt;br&gt;        }&lt;br&gt;        if(DOWN==StrangerState)&lt;br&gt;        {&lt;br&gt;            myButton2.MoveWindow(Button2_Rect.left,cy-Button3_Rect.Height()-    Button2_Rect.Height(),Button2_Rect.Width(),Button2_Rect.Height());&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;    OldClientSize.cx=cx;&lt;br&gt;    OldClientSize.cy=cy;&lt;br&gt;    this-&amp;gt;GetPosition();&lt;br&gt;}&lt;br&gt;　&lt;font color="#00309c"&gt;&lt;/font&gt;&lt;/tbody&gt;&lt;/table&gt;现在万事OK了，不难吧！&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=449534861986366027&amp;page=RSS%3a+VC%e5%88%b6%e4%bd%9c%e6%8b%89%e5%b8%98%e6%8c%89%e9%92%ae&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=wdllstudio.spaces.live.com&amp;amp;GT1=wdllstudio"&gt;</description><comments>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!165.entry#comment</comments><guid isPermaLink="true">http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!165.entry</guid><pubDate>Mon, 02 Jan 2006 05:03:28 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://wdllstudio.spaces.live.com/blog/cns!63D119342DA024B!165/comments/feed.rss</wfw:commentRss><wfw:comment>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!165.entry#comment</wfw:comment><dcterms:modified>2006-01-02T05:03:46Z</dcterms:modified></item><item><title>VC常见问题百问</title><link>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!164.entry</link><description>&lt;div&gt;
&lt;p&gt;（1） &lt;b&gt;如何通过代码获得应用程序主窗口的 指针?&lt;/b&gt;&lt;br&gt;主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。&lt;br&gt;AfxGetMainWnd() -&amp;gt;ShowWindow(SW_SHOWMAXMIZED)&lt;br&gt;//使程序最大化.
&lt;p&gt;&lt;br&gt;（2） &lt;b&gt;确定应用程序的路径&lt;/b&gt;&lt;br&gt;Use GetModuleFileName 获得应用程序的路径，然后去掉可执行文件名。&lt;br&gt;Example:&lt;br&gt;TCHAR&lt;br&gt;exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧，好象是&lt;br&gt;128&lt;br&gt;GetModuleFileName(NULL,exeFullPath,MAX_PATH)&lt;br&gt;&lt;br&gt;（3） &lt;b&gt;如何在程序中获得其他程序的 图标?&lt;/b&gt;&lt;br&gt;两种方法:&lt;br&gt;(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,&lt;br&gt;(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.&lt;br&gt;Example(1):&lt;br&gt;在程序窗口左上角显示 NotePad图标.&lt;br&gt;void CSampleView:&lt;br&gt;OnDraw(CDC * pDC)&lt;br&gt;{&lt;br&gt;if( :: SHGetFileInfo(_T(&amp;quot;c:\\pwin95\\notepad.exe&amp;quot;),0,&lt;br&gt;&amp;amp;stFileInfo,sizeof(stFileInfo),SHGFI_ICON))&lt;br&gt;{&lt;br&gt;pDC -&amp;gt;DrawIcon(10,10,stFileInfo.hIcon)&lt;br&gt;}&lt;br&gt;}&lt;br&gt;Example(2):同样功能,Use ExtractIcon Function&lt;br&gt;void CSampleView:: OnDraw(CDC *pDC)&lt;br&gt;{&lt;br&gt;HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T&lt;br&gt;(&amp;quot;NotePad.exe&amp;quot;),0)&lt;br&gt;if (hIcon &amp;amp;&amp;amp;hIcon!=(HICON)-1)&lt;br&gt;pDC-&amp;gt;DrawIcon(10,10,hIcon)&lt;br&gt;}&lt;br&gt;    说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔，应该用访问注册表的方法获得其路径，要作成一个比较考究的程序，考虑应该全面点.
&lt;p&gt;
&lt;p&gt;&lt;br&gt;（4） &lt;b&gt;获得各种目录信息&lt;/b&gt;&lt;br&gt;Windows目录: Use &amp;quot;GetWindowsDirectory&amp;quot;&lt;br&gt;Windows下的system目录: Use &amp;quot;GetSystemDirectory&amp;quot;&lt;br&gt;temp目录: Use &amp;quot;GetTempPath&amp;quot;&lt;br&gt;当前目录: Use &amp;quot;GetCurrentDirectory&amp;quot;&lt;br&gt;&lt;br&gt;请注意前两个函数的第一个参数为目录变量名，后一个为缓冲区后两个相反.&lt;br&gt;
&lt;p&gt;&lt;br&gt;（5） &lt;b&gt;如何自定义消息&lt;/b&gt;&lt;br&gt;1) 手工定义消息，可以这么写&lt;br&gt;#define WM_MY_MESSAGE(WM_USER+100),&lt;br&gt;MS 推荐的至少是 WM_USER+100&lt;br&gt;&lt;br&gt;(2)写消息处理函数,用&lt;br&gt;WPARAM,LPARAM返回LRESULT.&lt;br&gt;LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)&lt;br&gt;&lt;br&gt;{&lt;br&gt;temp目录: Use &amp;quot;GetTempPath&amp;quot;&lt;br&gt;//加入你的处理函数 irectory&amp;quot;&lt;br&gt;}
&lt;p&gt;（6） &lt;b&gt;如何改变窗口的图标?&lt;/b&gt;&lt;br&gt;向窗口发送 WM_SECTION消息。&lt;br&gt;Example:&lt;br&gt;HICON hIcon=AfxGetApp() -&amp;gt;LoadIcon(IDI_ICON)&lt;br&gt;ASSERT(hIcon)&lt;br&gt;AfxGetMainWnd() -&amp;gt;SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)
&lt;p&gt;&lt;br&gt;（7） &lt;b&gt;如何改变窗口的缺省风格?&lt;/b&gt;&lt;br&gt;重载 CWnd:: PreCreateWindow 并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.&lt;br&gt;Example: Delete &amp;quot;Max&amp;quot; Button and Set Original&lt;br&gt;Window's Position and Size&lt;br&gt;&lt;br&gt;BOOL CMainFrame:: PreCreateWindow&lt;br&gt;(CREATESTRUCT &amp;amp;cs)&lt;br&gt;{&lt;br&gt;cs.style &amp;amp;=~WS_MAXINIZEMOX&lt;br&gt;&lt;br&gt;cs.x=cs.y=0&lt;br&gt;cs.cx=GetSystemMetrics(SM_CXSCREEN/2)&lt;br&gt;cs.cy=GetSystemMetrics(SM_CYSCREEN/2)&lt;br&gt;&lt;br&gt;return CMDIFramewnd ::PreCreateWindow(cs)&lt;br&gt;}（8） &lt;b&gt;如何将窗口居中显示?&lt;/b&gt;&lt;br&gt;Call Function CWnd::&lt;br&gt;Center Windows&lt;br&gt;&lt;br&gt;Example(1):&lt;br&gt;Center Window( ) //Relative to it's parent&lt;br&gt;// Relative&lt;br&gt;to Screen&lt;br&gt;Example(2):&lt;br&gt;Center Window(CWnd:: GetDesktopWindow( ))&lt;br&gt;//Relative to&lt;br&gt;Application's MainWindow&lt;br&gt;AfxGetMainWnd( ) -&amp;gt;&lt;br&gt;Center Window( )&lt;br&gt;
&lt;p&gt;&lt;br&gt;（9） &lt;b&gt;如何让窗口和 MDI窗口一启动就最大化和最小化?&lt;/b&gt;&lt;br&gt;先说窗口。&lt;br&gt;在 InitStance 函数中设定 m_nCmdShow的取值.&lt;br&gt;m_nCmdShow=SW_SHOWMAXMIZED //最大化&lt;br&gt;m_nCmdShow=SW_SHOWMINMIZED //最小化&lt;br&gt;m_nCmdShow=SW_SHOWNORMAL //正常方式&lt;br&gt;&lt;br&gt;MDI窗口:&lt;br&gt;如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数，设置WS_MAXMIZE or WS_MINMIZE&lt;br&gt;&lt;br&gt;如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。（10） &lt;b&gt;如何限制窗口的大小?&lt;/b&gt;&lt;br&gt;也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:&lt;br&gt;
&lt;p&gt;（11） &lt;b&gt;如何使窗口不可见？&lt;/b&gt;&lt;br&gt;很简单,用SW_HIDE 隐藏窗口，可以结合 FindWindow,ShowWindow控制.
&lt;p&gt;（12） &lt;b&gt;如何创建一个字回绕的CEditView&lt;/b&gt;&lt;br&gt;重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构，关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位， 由于CEditView : : PreCreateWindow显示设置cs. style，调用基类函数后要修改cs . style。&lt;br&gt;&lt;br&gt;BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&amp;amp;cs)&lt;br&gt;{&lt;br&gt;//First call basse class function .&lt;br&gt;BOOL bResutl =CEditView : : PreCreateWindow (cs)&lt;br&gt;&lt;br&gt;// Now specify the new window style .&lt;br&gt;cs.style &amp;amp;= ~ (ES_AUTOHSCROLL ｜WS_HSCROLL)&lt;br&gt;return bResult&lt;br&gt;}&lt;br&gt;
&lt;p&gt;（13） &lt;b&gt;如何使程序保持极小状态?&lt;/b&gt;&lt;br&gt;这么办: 在恢复程序窗体大小时，Windows会发送WM_QUERY-OPEN消息，用 ClassWizard设置成员函数&lt;br&gt;OnQueryOpen() ,add following code:&lt;br&gt;&lt;br&gt;Bool CMainFrame:: OnQueryOpen( )&lt;br&gt;{&lt;br&gt;Return false&lt;br&gt;}
&lt;p&gt;（14） &lt;b&gt;移动窗口&lt;/b&gt;&lt;br&gt;调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关（顶层窗口与屏幕有关）。调用CWnd : : MoveWindow时必须要指定窗口的大小。&lt;br&gt;//Move window to positoin 100 , 100 of its parent window .&lt;br&gt;SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE ｜SWP_NOAORDER)
&lt;p&gt;（15） &lt;b&gt;通用控件的显示窗口&lt;/b&gt;&lt;br&gt;MFC提供了几个CView派生的视窗类， 封装了通用控件的功能，但仍然使用工作框文档显示窗口体系结构：CEditView封装了编辑控件，CTreeView保持了树列表控件，CListView封装了列表显示窗口控件，CRichEditView可以处理多种编辑控件。
&lt;p&gt;（16） &lt;b&gt;重置窗口的大小&lt;/b&gt;&lt;br&gt;调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志， 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。&lt;br&gt;// Get the size of the window .&lt;br&gt;Crect reWindow&lt;br&gt;GetWindowRect (reWindow )&lt;br&gt;&lt;br&gt;//Make the window twice as wide and twice as tall .&lt;br&gt;SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,&lt;br&gt;&lt;br&gt;reWindow . Height () * 2,&lt;br&gt;SWP_NOMOVE ｜SWP_NOZORDER )
&lt;p&gt;（17） &lt;b&gt;如何单击除了窗口标题栏以外的区域使窗口移动&lt;/b&gt;&lt;br&gt;当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息，可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序，可以使用ClassWizard处理该信息并调用基类函数， 如果函数返回HTCLIENT 则表明鼠标在客房区域，返回HTCAPTION表明鼠标在Windows的标题栏中。&lt;br&gt;UINT CSampleDialog : : OnNcHitTest (Cpoint point )&lt;br&gt;{&lt;br&gt;UINT nHitTest =Cdialog: : OnNcHitTest (point )&lt;br&gt;return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest&lt;br&gt;}&lt;br&gt;&lt;br&gt;上述技术有两点不利之处，&lt;br&gt;其一是在窗口的客户区域双击时，窗口将极大；&lt;br&gt;其二， 它不适合包含几个视窗的主框窗口。&lt;br&gt;还有一种方法，当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上，使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。&lt;br&gt;void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point&lt;br&gt;)&lt;br&gt;{&lt;br&gt;CView : : OnLButtonDow (nFlags , pont )&lt;br&gt;&lt;br&gt;//Fool frame window into thinking somene clicked&lt;br&gt;on&lt;br&gt;its caption bar .&lt;br&gt;GetParentFrame ( ) —&amp;gt; PostMessage (&lt;br&gt;WM_NCLBUTTONDOWN ,&lt;br&gt;HTCAPTION , MAKELPARAM (poitn .x , point .y) )&lt;br&gt;&lt;br&gt;}&lt;br&gt;该技术也适用于对话框和基于对的应用程序，只是不必调用&lt;br&gt;CWnd: :GetParentFrame 。&lt;br&gt;void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )&lt;br&gt;{&lt;br&gt;Cdialog : : OnLButtonDow (nFlags, goint )&lt;br&gt;//Fool dialog into thinking simeone clicked on its&lt;br&gt;caption bar .&lt;br&gt;PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x&lt;br&gt;, point. y&lt;br&gt;) )&lt;br&gt;}
&lt;p&gt;（18） &lt;b&gt;如何改变视窗的背景颜色&lt;/b&gt;&lt;br&gt;Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景，可以使用ClassWizard重载该消息的缺省处理程序来擦除背景（实际是画），并返回TRUE以防止Windows擦除窗口。&lt;br&gt;//Paint area that needs to be erased.&lt;br&gt;BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)&lt;br&gt;{&lt;br&gt;// Create a pruple brush.&lt;br&gt;CBrush Brush (RGB (128 , 0 , 128) )&lt;br&gt;&lt;br&gt;// Select the brush into the device context .&lt;br&gt;CBrush* pOldBrush = pDC—&amp;gt;SelcetObject (&amp;amp;brush)&lt;br&gt;&lt;br&gt;// Get the area that needs to be erased .&lt;br&gt;CRect reClip&lt;br&gt;pDC—&amp;gt;GetCilpBox (&amp;amp;rcClip)&lt;br&gt;//Paint the area.&lt;br&gt;pDC—&amp;gt; PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )&lt;br&gt;&lt;br&gt;//Unselect brush out of device context .&lt;br&gt;pDC—&amp;gt;SelectObject (pOldBrush )&lt;br&gt;&lt;br&gt;// Return nonzero to half fruther processing .&lt;br&gt;return TRUE&lt;br&gt;}
&lt;p&gt;（19） &lt;b&gt;如何改变窗口标题&lt;/b&gt;&lt;br&gt;调用CWnd : : SetWindowText可以改变任何窗口（包括控件）的标题。&lt;br&gt;//Set title for application's main frame window .&lt;br&gt;AfxGetMainWnd ( ) —&amp;gt; SetWindowText (_T(&amp;quot;Application title&amp;quot;) )&lt;br&gt;&lt;br&gt;//Set title for View's MDI child frame window .&lt;br&gt;GetParentFrame ( ) —&amp;gt; SetWindowText (&amp;quot;_T (&amp;quot;MDI Child Frame new title&amp;quot;)&lt;br&gt;)&lt;br&gt;&lt;br&gt;//Set title for dialog's push button control.&lt;br&gt;GetDigitem (IDC_BUTTON) —&amp;gt; SetWindowText (_T (&amp;quot;Button new title &amp;quot;) )&lt;br&gt;如果需要经常修改窗口的标题（注：控件也是窗口），应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明，在WINUTIL.CPP中实现，在联机帮助中找不到它，它在AFXPRIV.H中半文档化， 在以后发行的MFC中将文档化。&lt;br&gt;AfxSetWindowText的实现如下：&lt;br&gt;voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )&lt;br&gt;{&lt;br&gt;itn nNewLen= Istrlen (Ipaznew)&lt;br&gt;TCHAR szOld [256]&lt;br&gt;//fast check to see if text really changes (reduces&lt;br&gt;flash in the&lt;br&gt;controls )&lt;br&gt;if (nNewLen &amp;gt;_contof (szOld)&lt;br&gt;｜｜ : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen&lt;br&gt;｜｜ Istrcmp (szOld , IpszNew)! = 0&lt;br&gt;{&lt;br&gt;//change it&lt;br&gt;: : SetWindowText(hWndCtrl , IpszNew )&lt;br&gt;}&lt;br&gt;}
&lt;p&gt;（20） &lt;b&gt;如何防止主框窗口在其说明中显示活动的文档名&lt;/b&gt;&lt;br&gt;创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位，如果不希望在说明中自动添加文档名， 必须禁止该风格位， 可以使用ClassWizard重置&lt;br&gt;CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。&lt;br&gt;BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&amp;amp;cs)&lt;br&gt;{&lt;br&gt;//Turn off FWS_ADDTOTITLE in main frame .&lt;br&gt;cs.styel &amp;amp; = ~FWS_ADDTOTITLE 　&lt;br&gt;return CMDIFrameWnd : : PreCreateWindow (cs )&lt;br&gt;}&lt;br&gt;关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口，可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。
&lt;p&gt;（21） &lt;b&gt;如何获取有关窗口正在处理的当前消息的信息&lt;/b&gt;&lt;br&gt;调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如，可以使用ClassWizard将几个菜单项处理程序映射到一个函数中，然后调用GetCurrentMessage来确定所选中的菜单项。&lt;br&gt;viod CMainFrame : : OnCommmonMenuHandler ( )&lt;br&gt;{&lt;br&gt;//Display selected menu item in debug window .&lt;br&gt;TRACE (&amp;quot;Menu item %u was selected . \n&amp;quot; ,
&lt;p&gt;（22） &lt;b&gt;如何在代码中获取工具条和状态条的指针&lt;/b&gt;&lt;br&gt;缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：&lt;br&gt;//Get pointer to status bar .&lt;br&gt;CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR)&lt;br&gt;&lt;br&gt;//Get pointer to toolbar .&lt;br&gt;CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_TOOLBAR)
&lt;p&gt;（23） &lt;b&gt;如何使能和禁止工具条的工具提示&lt;/b&gt;&lt;br&gt;如果设置了CBRS_TOOLTIPS风格位，工具条将显示工具提示，要使能或者禁止工具提示，需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数：&lt;br&gt;void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )&lt;br&gt;{&lt;br&gt;ASSERT_VALID (m_wndToolBar)&lt;br&gt;&lt;br&gt;DWORD dwStyle = m _wndToolBar.GetBarStyle ( )&lt;br&gt;&lt;br&gt;if (bDisplayTips) dwStyle ｜=CBRS_TOOLTIPS&lt;br&gt;&lt;br&gt;else&lt;br&gt;dwStyle &amp;amp; = ~CBRS_TOOLTIPS&lt;br&gt;&lt;br&gt;m_wndToolBar.SetBarStyle (dwStyle )&lt;br&gt;}
&lt;p&gt;（24） &lt;b&gt;如何创建一个不规则形状的窗口&lt;/b&gt;&lt;br&gt;可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域，实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。&lt;br&gt;给对话类增加一个CRgn数据成员，以后要使用该数据成员建立窗口区域。&lt;br&gt;Class CRoundDlg : public CDialog&lt;br&gt;{&lt;br&gt;…&lt;br&gt;private :&lt;br&gt;Crgn m_rgn : // window region&lt;br&gt;…&lt;br&gt;}&lt;br&gt;修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口：&lt;br&gt;BOOL CRoundDlg : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;&lt;br&gt;//Get size of dialog .&lt;br&gt;CRect rcDialog&lt;br&gt;GetClientRect (rcDialog )&lt;br&gt;&lt;br&gt;// Create region and assign to window .&lt;br&gt;m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )&lt;br&gt;SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )&lt;br&gt;&lt;br&gt;return TRUE&lt;br&gt;}&lt;br&gt;&lt;br&gt;通过建立区域和调用SetWindowRgn，已经建立一个不规则形状的窗口，下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。&lt;br&gt;voik CRoundDlg : : OnPaint ( )&lt;br&gt;{&lt;br&gt;CPaintDC de (this) // device context for painting&lt;br&gt;.&lt;br&gt;//draw ellipse with out any border&lt;br&gt;dc. SelecStockObject (NULL_PEN)&lt;br&gt;//get the RGB colour components of the sphere color&lt;br&gt;COLORREF color= RGB( 0 , 0 , 255)&lt;br&gt;BYTE byRed =GetRValue (color)&lt;br&gt;BYTE byGreen = GetGValue (color)&lt;br&gt;BYTE byBlue = GetBValue (color)&lt;br&gt;&lt;br&gt;// get the size of the view window&lt;br&gt;Crect rect&lt;br&gt;GetClientRect (rect)&lt;br&gt;&lt;br&gt;// get minimun number of units&lt;br&gt;int nUnits =min (rect.right , rect.bottom )&lt;br&gt;&lt;br&gt;//calculate he horiaontal and vertical step size&lt;br&gt;float fltStepHorz = (float) rect.right /nUnits&lt;br&gt;float fltStepVert = (float) rect.bottom /nUnits&lt;br&gt;&lt;br&gt;&lt;br&gt;int nEllipse = nUnits/3 // calculate how many to&lt;br&gt;draw&lt;br&gt;int nIndex&lt;br&gt;// current ellipse that is being draw&lt;br&gt;&lt;br&gt;CBrush brush&lt;br&gt;// bursh used for ellipse fill color&lt;br&gt;CBrush *pBrushOld // previous&lt;br&gt;brush that was selected into dc&lt;br&gt;//draw ellipse , gradually moving towards upper-right&lt;br&gt;corner&lt;br&gt;for (nIndex = 0 nIndes &amp;lt; + nEllipse nIndes++)&lt;br&gt;{&lt;br&gt;//creat solid brush&lt;br&gt;brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).&lt;br&gt;( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)&lt;br&gt;/nEllipse ) ) )&lt;br&gt;&lt;br&gt;//select brush into dc&lt;br&gt;pBrushOld= dc .SelectObject (&amp;amp;brhsh)&lt;br&gt;&lt;br&gt;//draw ellipse&lt;br&gt;dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,&lt;br&gt;rect. right -( (int) fltStepHorz * nIndex )+ 1,&lt;br&gt;rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)&lt;br&gt;&lt;br&gt;//delete the brush&lt;br&gt;brush.DelecteObject ( )&lt;br&gt;}&lt;br&gt;}&lt;br&gt;&lt;br&gt;最后，处理WM_NCHITTEST消息，使当击打窗口的任何位置时能移动窗口。&lt;br&gt;UINT CRoundDlg : : OnNchitTest (Cpoint point )&lt;br&gt;{&lt;br&gt;//Let user move window by clickign anywhere on thewindow .&lt;br&gt;UINT nHitTest = CDialog : : OnNcHitTest (point)&lt;br&gt;rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest&lt;br&gt;&lt;br&gt;}
&lt;p&gt;（25） &lt;b&gt;如何获取应用程序的 实例句柄?&lt;/b&gt;&lt;br&gt;应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄.&lt;br&gt;Example: HANDLE hInstance=AfxGetInstanceHandle()
&lt;p&gt;（26） &lt;b&gt;如何编程结束应用程序?&lt;/b&gt;&lt;br&gt;这是个很简单又是编程中经常要遇到的问题.&lt;br&gt;向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.&lt;br&gt;Example: AfxGetMainWindow()-&amp;gt;SendMessage(WM_CLOSE)&lt;br&gt;&lt;br&gt;还可以创建一个自定义的函数 Terminate Window&lt;br&gt;void Terminate Window(LPCSTR pCaption)&lt;br&gt;{&lt;br&gt;CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)&lt;br&gt;&lt;br&gt;if (pWnd)&lt;br&gt;&lt;br&gt;pWnd -&amp;gt;SendMessage(WM_CLOSE)&lt;br&gt;}&lt;br&gt;&lt;br&gt;    说明: FindWindow函数不是提倡的做法，因为它无法处理标题栏自动改变，比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了，可以通过枚举 windows任务列表的办法来实现。在机械出版社&amp;quot;Windows 95 API开发人员指南&amp;quot;一书有比较详细的介绍,这里就不再多说乐。
&lt;p&gt;（27） &lt;b&gt;如何创建和使用无模式对话框&lt;/b&gt;&lt;br&gt;MFC将模式和无模式对话封装在同一个类中，但是使用无模式对话需要几个对话需要几个额处的步骤。首先，使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的：模式对话通过调用CDialog : : EndDialog 来中止，无模式对话则是调用CWnd: : DestroyWindow来中止的，函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。&lt;br&gt;void CSampleDialog : : OnOK ( )&lt;br&gt;{&lt;br&gt;// Retrieve and validate dialog data .&lt;br&gt;if (! UpdateData (TRUE) )&lt;br&gt;{&lt;br&gt;// the UpdateData rountine&lt;br&gt;will set focus to correct item TRACEO (&amp;quot; UpdateData failed during dialog termination .\n&amp;quot;)&lt;br&gt;return&lt;br&gt;}&lt;br&gt;&lt;br&gt;//Call DestroyWindow instead of EndDialog .&lt;br&gt;DestroyWindow ( )&lt;br&gt;}&lt;br&gt;&lt;br&gt;void CSampleDialog : : OnCancel ( )&lt;br&gt;{&lt;br&gt;//Call DestroyWindow instead of EndDialog .&lt;br&gt;DestroyWindow ( )&lt;br&gt;}&lt;br&gt;&lt;br&gt;其次，需要正确删除表示对话的C++对象。对于模式对来说，这很容易，需要创建函数返回后即可删除C++对象；无模式对话不是同步的，创建函数调用后立即返回，因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy，可以重置该函数并执行清除操作，诸如删除this指针。&lt;br&gt;void CSampleDialog : : PostNcDestroy ( )&lt;br&gt;{&lt;br&gt;// Declete the C++ object that represents this dialog.&lt;br&gt;delete this&lt;br&gt;&lt;br&gt;最后，要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放，要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的： 象；无模式对话不是同步的，创建函数调用后立即返回，&lt;br&gt;void CMainFrame : : OnSampleDialog ( )&lt;br&gt;{&lt;br&gt;//Allocate a modeless dialog object .&lt;br&gt;CSampleDilog * pDialog =new CSampleDialog&lt;br&gt;ASSERT_VALID (pDialog) Destroy ( )&lt;br&gt;&lt;br&gt;//Create the modeless dialog . represents this dialog.&lt;br&gt;BOOL bResult = pDialog —&amp;gt; Creste (IDD_IDALOG)&lt;br&gt;ASSERT (bResult )&lt;br&gt;}&lt;br&gt;
&lt;p&gt;
&lt;p&gt;（28） &lt;b&gt;如何防止主框窗口在其说明中显示活动的文档名&lt;/b&gt;&lt;br&gt;创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位，如果不希望在说明中自动添加文档名， 必须禁止该风格位， 可以使用ClassWizard重置&lt;br&gt;CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。&lt;br&gt;BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&amp;amp;cs)&lt;br&gt;{&lt;br&gt;//Turn off FWS_ADDTOTITLE in main frame .&lt;br&gt;cs.styel &amp;amp; = ~FWS_ADDTOTITLE 　&lt;br&gt;return CMDIFrameWnd : : PreCreateWindow (cs )&lt;br&gt;}&lt;br&gt;关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口，可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。
&lt;p&gt;（29） &lt;b&gt;如何在代码中获取工具条和状态条的指针&lt;/b&gt;&lt;br&gt;缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：&lt;br&gt;//Get pointer to status bar .&lt;br&gt;CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR)&lt;br&gt;&lt;br&gt;//Get pointer to toolbar .&lt;br&gt;CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_TOOLBAR)
&lt;p&gt;&lt;br&gt;（30） &lt;b&gt;怎样加载其他的应用程序?&lt;/b&gt;&lt;br&gt;三个SDK函数 winexec, shellexecute,createprocess可以使用。&lt;br&gt;WinExec最简单，两个参数，前一个指定路径，后一个指定显示方式.后一个参数值得说一下，比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序，就是Neterm,calc等等，就不会出现正常的窗体，但是已经被加到任务列表里了。&lt;br&gt;&lt;br&gt;ShellExecute较 WinExex灵活一点，可以指定工作目录,下面的Example就是直接打开 c:\temp\1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口，来显示Readme or Faq,我猜就是这么作的啦.&lt;br&gt;&lt;br&gt;ShellExecute(NULL,NULL,_T(&amp;quot;1.txt&amp;quot;),NULL,_T(&amp;quot;c:\\temp&amp;quot;),SW_SHOWMAXMIZED)&lt;br&gt;&lt;br&gt;CreateProcess最复杂，一共有十个参数，不过大部分都可以用NULL代替，它可以指定进程的安全属性，继承信息，类的优先级等等.来看个很简单的Example:&lt;br&gt;STARTUPINFO stinfo&lt;br&gt;//启动窗口的信息&lt;br&gt;PROCESSINFO procinfo //进程的信息&lt;br&gt;&lt;br&gt;CreateProcess(NULL,_T(&amp;quot;notepad.exe&amp;quot;),NULL,NULL.FALSE,&lt;br&gt;NORMAL_PRIORITY_&lt;br&gt;&lt;br&gt;CLASS,NULL,NULL, &amp;amp;stinfo,&amp;amp;procinfo)&lt;br&gt;
&lt;p&gt;（31） &lt;b&gt;如何在代码中获取工具条和状态条的指针&lt;/b&gt;&lt;br&gt;缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：&lt;br&gt;//Get pointer to status bar .&lt;br&gt;CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR)
&lt;p&gt;（32） &lt;b&gt;如何使能和禁止工具条的工具提示&lt;/b&gt;&lt;br&gt;如果设置了CBRS_TOOLTIPS风格位，工具条将显示工具提示，要使能或者禁止工具提示，需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数：&lt;br&gt;void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )&lt;br&gt;{&lt;br&gt;ASSERT_VALID (m_wndToolBar)&lt;br&gt;&lt;br&gt;DWORD dwStyle = m _wndToolBar.GetBarStyle ( )&lt;br&gt;&lt;br&gt;if (bDisplayTips) dwStyle ｜=CBRS_TOOLTIPS&lt;br&gt;&lt;br&gt;else&lt;br&gt;dwStyle &amp;amp; = ~CBRS_TOOLTIPS&lt;br&gt;&lt;br&gt;m_wndToolBar.SetBarStyle (dwStyle )&lt;br&gt;}&lt;br&gt;&lt;br&gt;//Get pointer to toolbar .&lt;br&gt;CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )&lt;br&gt;—&amp;gt; GetDescendantWindow(AFX_IDW_TOOLBAR)
&lt;p&gt;（33） &lt;b&gt;如何设置工具条标题&lt;/b&gt;&lt;br&gt;工具条是一个窗口，所以可以在调用CWnd : : SetWindowText来设置标题，例子如下：&lt;br&gt;int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )&lt;br&gt;{&lt;br&gt;…&lt;br&gt;// Set the caption of the toolbar .&lt;br&gt;m_wndToolBar.SetWindowText (_T &amp;quot;Standdard&amp;quot;)
&lt;p&gt;（34） &lt;b&gt;如何使窗口始终在最前方?&lt;/b&gt;&lt;br&gt;BringWindowToTop(Handle)&lt;br&gt;SetWindowPos函数，指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格&lt;br&gt;&lt;br&gt;Example:&lt;br&gt;void ToggleTopMost(&lt;br&gt;CWnd *pWnd)&lt;br&gt;{&lt;br&gt;ASSERT_VALID(pWnd)&lt;br&gt;&lt;br&gt;pWnd -&amp;gt;SetWindowPos(pWnd-&amp;gt; GetStyle( ) &amp;amp;WS_EX_TOPMOST)?&lt;br&gt;&lt;br&gt;&amp;amp;wndNoTopMOST: &amp;amp;wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)&lt;br&gt;}
&lt;p&gt;（35） &lt;b&gt;如何在对话框中显示一个位图&lt;/b&gt;&lt;br&gt;这要归功于Win 32先进的静态控件和Microsoft的资源编辑器，在对话框中显示位图是很容易的， 只需将图形控件拖到对话中并选择适当属性即可，用户也可以显示图标、位图以及增强型元文件。
&lt;p&gt;（36） &lt;b&gt;如何改变对话或窗体视窗的背景颜色&lt;/b&gt;&lt;br&gt;调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色，第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。&lt;br&gt;BOOL CSampleApp : : InitInstance ( )&lt;br&gt;{&lt;br&gt;…&lt;br&gt;&lt;br&gt;//use blue dialog with yellow text .&lt;br&gt;SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) )&lt;br&gt;&lt;br&gt;…&lt;br&gt;}&lt;br&gt;&lt;br&gt;需要重画对话（或对话的子控件）时，Windows向对话发送消息WM_CTLCOLOR，通常用户可以让Windows选择绘画背景的刷子，也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。&lt;br&gt;&lt;br&gt;首先，给对话基类增加一人成员变量&lt;br&gt;CBursh :class CMyFormView : public CFormView&lt;br&gt;{&lt;br&gt;…&lt;br&gt;&lt;br&gt;private :&lt;br&gt;CBrush m_ brush // background brush&lt;br&gt;&lt;br&gt;…&lt;br&gt;}&lt;br&gt;&lt;br&gt;其次， 在类的构造函数中将刷子初始化为所需要的背景颜色。&lt;br&gt;CMyFormView : : CMyFormView ( )&lt;br&gt;{&lt;br&gt;// Initialize background brush .&lt;br&gt;m_brush .CreateSolidBrush (RGB ( 0, 0, 255) )&lt;br&gt;}&lt;br&gt;&lt;br&gt;最后，使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意：由于当重画对话控件时也要调用该函数，所以要检测nCtlColor参量。&lt;br&gt;HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor&lt;br&gt;)&lt;br&gt;&lt;br&gt;{&lt;br&gt;// Determine if drawing a dialog box . If we are, return +handle to&lt;br&gt;//our own background brush . Otherwise let windows handle it .&lt;br&gt;if (nCtlColor = = CTLCOLOR _ DLG )&lt;br&gt;return (HBRUSH) m_brush.GetSafeHandle ( )&lt;br&gt;return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor&lt;br&gt;)&lt;br&gt;}
&lt;p&gt;（37） &lt;b&gt;如何获取一个对话控件的指针&lt;/b&gt;&lt;br&gt;有两种方法。其一，调用CWnd: : GetDlgItem，获取一个CWnd*指针调用成员函数。下例调用GetDlgItem，将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数：&lt;br&gt;BOOL CSampleDialog : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;&lt;br&gt;//Get pointer to spin button .&lt;br&gt;CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)&lt;br&gt;ASSERT _ VALID (pSpin)&lt;br&gt;//Set spin button's default position .&lt;br&gt;pSpin —&amp;gt; SetPos (10)&lt;br&gt;&lt;br&gt;return TRUE&lt;br&gt;}&lt;br&gt;&lt;br&gt;其二， 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签，然后选择Add Variable …按钮。如果在对话资源编辑器中，按下Ctrl键并双击控件即可转到Add Member Variable对话。
&lt;p&gt;
&lt;p&gt;（38） &lt;b&gt;如何禁止和使能控件&lt;/b&gt;&lt;br&gt;控件也是窗口，所以可以调用CWnd : : EnableWindow使能和禁止控件。&lt;br&gt;//Disable button controls .&lt;br&gt;m_wndOK.EnableWindow (FALSE )&lt;br&gt;m_wndApply.EnableWindow (FALSE )
&lt;p&gt;
&lt;p&gt;（39） &lt;b&gt;如何改变控件的字体&lt;/b&gt;&lt;br&gt;由于控件是也是窗口，用户可以调用CWnd: : SetFont指定新字体。该函数用一个Cfont指针，要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为8点Arial字体：&lt;br&gt;//Declare font object in class declaration (.H file ).&lt;br&gt;private : Cfont m_font&lt;br&gt;// Set font in class implementation (.Cpp file ). Note m_wndButton is a&lt;br&gt;//member variable added by ClassWizard.DDX routines hook the member&lt;br&gt;//variable to a dialog button contrlo.&lt;br&gt;BOOL CSampleDialog : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;…&lt;br&gt;//Create an 8-point Arial font&lt;br&gt;m_font . CreateFont (MulDiv (8 , -pDC&lt;br&gt;—&amp;gt; GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS ,&lt;br&gt;&lt;br&gt;CLIP_STROKE _PRECIS , DRAFT _QUALITY&lt;br&gt;VARIABLE_PITCH ｜FF_SWISS, _T(&amp;quot;Arial&amp;quot;) )&lt;br&gt;&lt;br&gt;//Set font for push button .&lt;br&gt;m_wndButton . SetFont (&amp;amp;m _font )&lt;br&gt;&lt;br&gt;…&lt;br&gt;}
&lt;p&gt;（40） &lt;b&gt;如何在OLE控件中使用OLE_COLOR数据类型&lt;/b&gt;&lt;br&gt;诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数返回OLE _COLOR数据类型的颜色，而GDI对象诸如笔和刷子使用的是COLORREF数据类型，调用COleControl : : TranslateColor可以很容易地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子：&lt;br&gt;&lt;br&gt;void CSampleControl : : OnDraw (CDC* pdc&lt;br&gt;const Crect&amp;amp; rcBounds , const Crect&amp;amp; rcInvalid&lt;br&gt;)&lt;br&gt;{&lt;br&gt;//Create a brush of the cuttent background color.&lt;br&gt;CBrush brushBack (TranslateColor (GetBackColor () ) )&lt;br&gt;&lt;br&gt;//Paint the background using the current backgroundcolor .&lt;br&gt;pdc—&amp;gt; FilllRect (rcBounds , &amp;amp;brushBack)&lt;br&gt;&lt;br&gt;//other drawign commands&lt;br&gt;&lt;br&gt;…&lt;br&gt;}
&lt;p&gt;
&lt;p&gt;
&lt;p&gt;（41） &lt;b&gt;在不使用通用文件打开对话的情况下如何显示一个文件列表&lt;/b&gt;&lt;br&gt;调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox，Windows 将自动地向列表框或组合框填充可用的驱动器名或者指定目录中的文件，下例将Windows目录中的文件填充在组合框中：&lt;br&gt;BOOL CSampleDig : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;TCHAR szPath [MAX_PATH] = {&amp;quot;c:\\windows&amp;quot;}&lt;br&gt;int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE ｜DDL_READONLY｜DDL_HIDDEN｜ DDL_SYSTEM｜DDL_ARCHIVE)&lt;br&gt;return TRUE&lt;br&gt;}
&lt;p&gt;（42） &lt;b&gt;为什么旋转按钮控件看起来倒转&lt;/b&gt;&lt;br&gt;需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围，旋转按钮控件的缺省上限为0，缺省下限为100，这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100：&lt;br&gt;BOOL CAboutDlg : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;&lt;br&gt;//set the lower and upper limit of the spin button&lt;br&gt;m_wndSpin . SetRange ( 0 ,100 )&lt;br&gt;&lt;br&gt;return TRUE&lt;br&gt;}&lt;br&gt;&lt;br&gt;Visual C++ 4.0 Print对话中的Copise旋转按钮控件也有同样的问题：按下Up按钮时拷贝的数目减少，而按下Down 按钮时拷贝的数目增加。
&lt;p&gt;（43） &lt;b&gt;为什么旋转按钮控件不能自动地更新它下面的编辑控件&lt;/b&gt;&lt;br&gt;如果使用旋转按钮的autu buddy特性， 则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab Order菜单项（或者按下Crtl+D）可以设置对话的标签顺序。
&lt;p&gt;（44） &lt;b&gt;如何用位图显示下压按钮&lt;/b&gt;&lt;br&gt;Windows 95按钮有几处新的创建风格，尤其是BS_BITMAP和BS_ICON，要想具有位图按钮，创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时要指定BS_BITMAP或BS_ICON风格。&lt;br&gt;&lt;br&gt;首先，设置按钮的图标属性。然后，当对话初始化时调用CButton: : SetIcon。注意：下例用图标代替位图，使用位图时要小心，因为不知道背景所有的颜色——并非每个人都使用浅灰色。&lt;br&gt;&lt;br&gt;BOOL CSampleDlg : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;&lt;br&gt;//set the images for the push buttons .&lt;br&gt;BOOL CSampleDlg : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;CDialog : : OnInitDialog ( )&lt;br&gt;&lt;br&gt;//set the images for the push buttons .&lt;br&gt;m_wndButton1.SetIcon (AfxGetApp ( ) —&amp;gt; LoadIcon (IDI _ IPTION1))&lt;br&gt;m_wndButton2.SetIcon (AfxGetApp ( ) —&amp;gt; LoadIcon (IDI _ IPTION2))&lt;br&gt;m_wndButton3.SetIcon (AfxGetApp ( ) —&amp;gt; LoadIcon (IDI _ IPTION3))&lt;br&gt;&lt;br&gt;return TRUE&lt;br&gt;}
&lt;p&gt;
&lt;p&gt;（45） &lt;b&gt;如何一个创建三态下压按钮&lt;/b&gt;&lt;br&gt;可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易，只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。
&lt;p&gt;（46） &lt;b&gt;如何动态创建控件&lt;/b&gt;&lt;br&gt;分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事：忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件：&lt;br&gt;//In class declaration (.H file ).&lt;br&gt;private : CButton* m _pButton&lt;br&gt;&lt;br&gt;//In class implementation (.cpp file ) .&lt;br&gt;m_pButton =new CButton&lt;br&gt;ASSERT_VALID (m_pButton)&lt;br&gt;m_pButton —&amp;gt;Create (_T (&amp;quot;Button Title &amp;quot;) , WS_CHILD ｜WS_VISIBLE ｜BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )
&lt;p&gt;（47） &lt;b&gt;如何限制编辑框中的准许字符&lt;/b&gt;&lt;br&gt;如果用户在编辑控件中只允许接收数字，可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志，该标志限制 编辑控件只按收数字字符。如果用户需要复杂的编辑控件，可以使用Microsoft 的屏蔽编辑控件，它是一个很有用的OLE定制控件。&lt;br&gt;如果希望不使用OLE 定制控件自己处理字符，可以派生一个CEdit类并处理WM_CHAR消息，然后从编辑控件中过滤出特定的字符。首先，使用ClassWizard建立一个 CEdit的派生类，其次，在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem .&lt;br&gt;&lt;br&gt;//In your dialog class declaration (.H file )&lt;br&gt;private : CMyEdit m_wndEdit // Instance of your new edit control .&lt;br&gt;&lt;br&gt;//In you dialog class implementation (.CPP file )&lt;br&gt;BOOL CSampleDialog : : OnInitDialog ( )&lt;br&gt;{&lt;br&gt;…&lt;br&gt;&lt;br&gt;//Subclass the edit lontrod .&lt;br&gt;m_wndEdit .SubclassDlgItem (IDC_EDIT,this)&lt;br&gt;&lt;br&gt;…&lt;br&gt;}&lt;br&gt;&lt;br&gt;使用ClassWizard处理WM_CHAR消息，计算nChar参量并决定所执行的操作，用户可以确定是否修改、传送字符。下例说明了如何显示字母字符，如果字符是字母字符，则调用CWnd OnChar，否则不调用OnChar.&lt;br&gt;//Only display alphabetic dharacters .&lt;br&gt;void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )&lt;br&gt;{&lt;br&gt;//Determine if nChar is an alphabetic character.&lt;br&gt;if (: : IsCharAlpha ( ( TCHAR) nChar ) )&lt;br&gt;CEdit : : OnChar (nChar, nRepCnt , nFlags )&lt;br&gt;}&lt;br&gt;&lt;br&gt;如果要修改字符，则不能仅仅简单地用修改过的nChar调用CEdit: : OnChar，然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值，这样是不行的。要修改一个字符，需要首先修改nChar，然后用修改过的nChar调用CWnd: : DefWindowProc。下例说明了如何将字符转变为大写：&lt;br&gt;//Make all characters uppercase&lt;br&gt;void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )&lt;br&gt;{&lt;br&gt;//Make sure character is uppercase .&lt;br&gt;if (: : IsCharAlpha ( .( TCHAR) nChar)&lt;br&gt;nChar=: : CharUpper(nChar )&lt;br&gt;&lt;br&gt;//Bypass default OnChar processing and directly call&lt;br&gt;//default window proc.&lt;br&gt;DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))&lt;br&gt;}
&lt;p&gt;（48） &lt;b&gt;如何改变控件的颜色&lt;/b&gt;&lt;br&gt;有两种方法。其一，可以在父类中指定控件的颜色，或者利用MFC4.0新的消息反射在控件类中指定颜色。 当控件需要重新着色时，工作框调用父窗口（通常是对话框）的CWnd: : OnCrtlColor,可以在父窗口类中重置该函数并指定控件的新的绘画属性。例如，下述代码将对话中的所有编辑控件文本颜色改为红色：&lt;br&gt;HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)&lt;br&gt;&lt;br&gt;{&lt;br&gt;HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )&lt;br&gt;&lt;br&gt;//Draw red text for all edit controls .&lt;br&gt;if (nCtlColor= = CTLCOLOR_EDIT )&lt;br&gt;pDC —&amp;gt; SetTextColor (RGB (255, 0 , 0 , ) )&lt;br&gt;&lt;br&gt;return hbr&lt;br&gt;}&lt;br&gt;&lt;br&gt;然而，由于每个父窗口必须处理通知消息并指定每个控件的绘画属性，所以，这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口，如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。&lt;br&gt;&lt;br&gt;首先，使用ClassWizard 创建一个CListBox 的派生类并为该类添加下述数据成员。&lt;br&gt;class CMyListBox publilc CListBox&lt;br&gt;{&lt;br&gt;…&lt;br&gt;private&lt;br&gt;COLORREF m_clrFor // foreground color&lt;br&gt;COLORREF m_clrBack //background color&lt;br&gt;Cbrush m_brush //background brush&lt;br&gt;…&lt;br&gt;}&lt;br&gt;其次，在类的构造函数中，初始化数据中。&lt;br&gt;CMyListBox : : CMyListBox ()&lt;br&gt;{&lt;br&gt;//Initialize data members .&lt;br&gt;m_clrFore =RGB (255 , 255 , 0) //yellow text&lt;br&gt;m_clrBack=RGB (0 , 0 , 255) // blue background&lt;br&gt;m_brush . CreateSolidBrush (m _clrBack )&lt;br&gt;}&lt;br&gt;&lt;br&gt;最后，使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的绘画属性。&lt;br&gt;HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )&lt;br&gt;{&lt;br&gt;pDC—&amp;gt;SetTextColor (m_clrFore)&lt;br&gt;pDC—&amp;gt;SetBkColor (m_clrBack)&lt;br&gt;&lt;br&gt;return (HBRUSH) m_brush.GetSafeHandle ()&lt;br&gt;}&lt;br&gt;现在，控件可以自己决定如何绘画，与父窗口无关。
&lt;p&gt;（49） &lt;b&gt;当向列表框中添加多个项时如何防止闪烁&lt;/b&gt;&lt;br&gt;调用CWnd::SetRedraw 清除重画标志可以禁止CListBox（或者窗口）重画。当向列表框添加几个项时，用户可以清除重画标志，然后添加项，最后恢复重画标志。为确保重画列表框的新项，调用SetRedraw (TRUE) 之后调用CWnd::Invalidate。&lt;br&gt;&lt;br&gt;//Disable redrawing.&lt;br&gt;pListBox-&amp;gt;SetRedraw (FALSE)&lt;br&gt;&lt;br&gt;//Fill in the list box gere&lt;br&gt;//Enable drwing and make sure list box is redrawn.&lt;br&gt;pListBox-&amp;gt;SetRedraw (TRUE)&lt;br&gt;pListBox-&amp;gt;Invalidate ()
&lt;p&gt;（50） &lt;b&gt;如何向编辑控件中添加文本&lt;/b&gt;&lt;br&gt;由于没有CEdit:: AppendText函数，用户只好自己做此项工作。调用CEdit:: SetSel移动到编辑控件末尾，然后调用CEdit:: ReplaceSel添加文本。下例是AppendText 的一种实现方法：&lt;br&gt;&lt;br&gt;void CMyEdit:: AppendText (LPCSTR pText)&lt;br&gt;{&lt;br&gt;int nLen=GetWindowTextLength ()&lt;br&gt;SetFocus ()&lt;br&gt;SetSel (nLen, nLen)&lt;br&gt;&lt;br&gt;ReplaceSel (pText)&lt;br&gt;}
&lt;p&gt;（51） &lt;b&gt;如何访问预定义的GDI对象&lt;/b&gt;&lt;br&gt;可以通过调用CDC:: SlectStockObject使用Windows的几个预定义的对象，诸如刷子、笔以及字体。下例使用了Windows预定义的笔和刷子GDI对象在视窗中画一个椭圆。&lt;br&gt;//Draw ellipse using stock black pen and gray brush.&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;//Determine size of view.&lt;br&gt;CRect rcView&lt;br&gt;GetClientRect (rcView)&lt;br&gt;&lt;br&gt;//Use stock black pen and stock gray brush to draw ellipse.&lt;br&gt;pDC-&amp;gt;SelectStockObject (BLACK_PEN)&lt;br&gt;pDC-&amp;gt;SelectStockObject (GRAY_BRUSH)&lt;br&gt;//Draw the ellipse.&lt;br&gt;pDC-&amp;gt;Ellipse (reView)&lt;br&gt;}&lt;br&gt;&lt;br&gt;也可以调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子，下例用背景色在视窗中画一个椭圆：&lt;br&gt;void CsampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;//Determine size of view.&lt;br&gt;CRect rcView&lt;br&gt;GetClientRect (rcView)&lt;br&gt;&lt;br&gt;//Use background color for tooltips brush.&lt;br&gt;CBrush * pOrgBrush=pDC-&amp;gt;SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))&lt;br&gt;&lt;br&gt;//Draw the ellipse.&lt;br&gt;pDC-&amp;gt;Ellipse (rcView)&lt;br&gt;&lt;br&gt;//Restore original brush.&lt;br&gt;pDC-&amp;gt;SelectObject (pOrgBrush)&lt;br&gt;}
&lt;p&gt;（52） &lt;b&gt;如何获取GDI对象的属性信息&lt;/b&gt;&lt;br&gt;可以调用GDIObject:: GetObject。这个函数将指定图表设备的消息写入到缓冲区。下例创建了几个有用的辅助函数。&lt;br&gt;//Determine if font is bold.&lt;br&gt;BOOL IsFontBold (const CFont&amp;amp;font)&lt;br&gt;{&lt;br&gt;LOGFONT stFont&lt;br&gt;font.GetObject (sizeof (LOGFONT), &amp;amp;stFont)&lt;br&gt;return (stFont.lfBold)? TRUE: FALSE&lt;br&gt;}&lt;br&gt;&lt;br&gt;//Return the size of a bitmap.&lt;br&gt;CSize GetBitmapSize (const CBitmap&amp;amp;bitmap)&lt;br&gt;{&lt;br&gt;BITMAP stBitmap&lt;br&gt;bitmap.GetObject (sizeof (BITMAP), &amp;amp;stBitmap)&lt;br&gt;return CSize (stBitmap.bmWidth, stBitmap.bmHeight)&lt;br&gt;}&lt;br&gt;&lt;br&gt;//Create a pen with the same color as a brush.&lt;br&gt;BOOL CreatePenFromBrush (Cpen&amp;amp;pen, cost Cbrush&amp;amp;brush)&lt;br&gt;{&lt;br&gt;LOGBRUSH stBrush&lt;br&gt;brush.Getobject (sizeof (LOGBRUSH), &amp;amp;stBrush)&lt;br&gt;return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)&lt;br&gt;}
&lt;p&gt;（53） &lt;b&gt;如何实现一个橡皮区矩形&lt;/b&gt;&lt;br&gt;CRectTracker是一个很有用的类，可以通过调用CRectTracker::TrackRubberBand 响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。&lt;br&gt;下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。&lt;br&gt;&lt;br&gt;首先，在文件档中声明一个CRectTracker数据成员：&lt;br&gt;class CSampleView : Public CView&lt;br&gt;{&lt;br&gt;…&lt;br&gt;public :&lt;br&gt;CrectTracker m_tracker&lt;br&gt;…&lt;br&gt;}&lt;br&gt;&lt;br&gt;其次，在文档类的构造函数中初始化CRectTracker 对象：&lt;br&gt;CSampleDoc:: CSampleDOC ()&lt;br&gt;{&lt;br&gt;//Initialize tracker position, size and style.&lt;br&gt;m_tracker.m_rect.SetRect (0, 0, 10, 10)&lt;br&gt;m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine&lt;br&gt;}&lt;br&gt;&lt;br&gt;然后，在OnDraw函数中画椭圆和踪迹矩形：&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;CSampleDoc* pDoc=GetDocument ()&lt;br&gt;ASSERT_VALID (pDoc)&lt;br&gt;&lt;br&gt;//Select blue brush into device context.&lt;br&gt;CBrush brush (RGB (0, 0, 255))&lt;br&gt;CBrush* pOldBrush=pDC-&amp;gt;SelectObject (&amp;amp;brush)&lt;br&gt;&lt;br&gt;//draw ellipse in tracking rectangle.&lt;br&gt;Crect rcEllipse&lt;br&gt;pDoc-&amp;gt;m_tracker.GetTrueRect (rcEllipse)&lt;br&gt;pDC-&amp;gt;Ellipse (rcEllipse)&lt;br&gt;&lt;br&gt;//Draw tracking rectangle.&lt;br&gt;pDoc-&amp;gt;m_tracker.Draw (pDC)&lt;br&gt;//Select blue brush out of device context.&lt;br&gt;pDC-&amp;gt;Selectobject (pOldBrush)&lt;br&gt;}&lt;br&gt;&lt;br&gt;最后，使用ClassWizard处理WM_LBUTTONDOWN消息，并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。&lt;br&gt;void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)&lt;br&gt;{&lt;br&gt;//Get pointer to document.&lt;br&gt;CSampleDoc* pDoc=GetDocument ()&lt;br&gt;ASSERT_VALID (pDoc)&lt;br&gt;&lt;br&gt;//If clicked on ellipse, drag or resize it.Otherwise create a&lt;br&gt;//rubber-band rectangle nd create a new ellipse.&lt;br&gt;BOOL bResult=pDoc-&amp;gt;m_tracker.HitTest (point)!= CRectTracker::hitNothing&lt;br&gt;&lt;br&gt;//Tracker rectangle changed so update views.&lt;br&gt;if (bResult)&lt;br&gt;{&lt;br&gt;pDoc-&amp;gt;m_tracker.Track (this,point,TRue)&lt;br&gt;pDoc-&amp;gt;SetModifiedFlag ()&lt;br&gt;pDoc-&amp;gt;UpdateAllViews (NULL)&lt;br&gt;}&lt;br&gt;&lt;br&gt;else&lt;br&gt;pDoc-&amp;gt;m-tracker.TrackRubberBand(this,point,TRUE)&lt;br&gt;CView:: onLButtonDown (nFlags,point)&lt;br&gt;}
&lt;p&gt;（54） &lt;b&gt;如何更新翻转背景颜色的文本&lt;/b&gt;&lt;br&gt;调用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景，或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变，这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT，可以两次更新串，用花色带黑阴影更新文本。黑色串在红色串之后，但由于设置了背景模式仍然可见。&lt;br&gt;&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;//Determint size of view.&lt;br&gt;CRect rcView&lt;br&gt;GetClientRect (rcVieew)&lt;br&gt;&lt;br&gt;//Create sample string to display.&lt;br&gt;CString str (_T (&amp;quot;Awesome Shadow Text．．．&amp;quot;))&lt;br&gt;//Set the background mode to transparent.&lt;br&gt;pDC-&amp;gt;SetBKMode (TRANSPARENT)&lt;br&gt;&lt;br&gt;//Draw black shadow text.&lt;br&gt;rcView.OffsetRect (1, 1)&lt;br&gt;pDc-&amp;gt;SetTextColor (RGB (0, 0, 0))&lt;br&gt;pDC-&amp;gt;DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)&lt;br&gt;&lt;br&gt;//Draw red text.&lt;br&gt;rcView.OffsetRect (-1,-1)&lt;br&gt;pDc-&amp;gt;SetTextColor (RGB (255, 0, 0))&lt;br&gt;pDC-&amp;gt;DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)&lt;br&gt;&lt;br&gt;}
&lt;p&gt;（55） &lt;b&gt;如何创建一个具有特定点大小的字体&lt;/b&gt;&lt;br&gt;可以指定字体逻辑单位的大小，但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度：&lt;br&gt;&lt;br&gt;int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)&lt;br&gt;下例创建了一个8点的Apial字体：&lt;br&gt;…&lt;br&gt;CClientDC dc (AqfxGetMainWnd ())&lt;br&gt;&lt;br&gt;m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T(&amp;quot;Arial&amp;quot;))
&lt;p&gt;（56） &lt;b&gt;如何计算一个串的大小&lt;/b&gt;&lt;br&gt;函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体，则在调用GetTextExtent之前将字体选进设备上下文中是很重要的，否则计算高度和宽度时将依据系统字体，由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小，按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText，该消息使用ON_MESSAE宏指令定义的用户自定义消息。&lt;br&gt;&lt;br&gt;LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)&lt;br&gt;{&lt;br&gt;//Pass message to window procedure.&lt;br&gt;LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() -&amp;gt;message,wParam,lParam)&lt;br&gt;//Get title of push button.&lt;br&gt;CString strTitle&lt;br&gt;GetWindowText (strTitle)&lt;br&gt;&lt;br&gt;//Select current font into device context.&lt;br&gt;CDC* pDC=GetDc ()&lt;br&gt;CFont*pFont=GetFont ()&lt;br&gt;CFont*pOldFont=pDC-&amp;gt;SelectObject (pFont)&lt;br&gt;&lt;br&gt;//Calculate size of title.&lt;br&gt;CSize size=pDC-&amp;gt;GetTextExent (strTitle,strTitle.GetLength())&lt;br&gt;&lt;br&gt;//Adjust the button's size based on its title.&lt;br&gt;//Add a 5-pixel border around the button.&lt;br&gt;SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)&lt;br&gt;//Clean up.&lt;br&gt;pDC-&amp;gt;SelectFont (pOldFont)&lt;br&gt;ReleaseDC (pDC)&lt;br&gt;&lt;br&gt;return bResult&lt;br&gt;}&lt;br&gt;
&lt;p&gt;（57） &lt;b&gt;如何显示旋转文本&lt;/b&gt;&lt;br&gt;只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体）。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角度，角度的单位是十分之一度而不是度，例如，ifEscapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转，一定要设置ifEscapement成员的CLIP_LH_ANGLES位，否则，有些字体可能反向旋转。下例使用了14点Arial字体每间隔15度画一个串。&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;//Determine the size of the window.&lt;br&gt;CRect rcClient&lt;br&gt;GetClientRect (rcClient)&lt;br&gt;&lt;br&gt;//Create sample string.&lt;br&gt;CString str (_T (&amp;quot;Wheeee．．．I am rotating!&amp;quot;))&lt;br&gt;//Draw transparent, red text.&lt;br&gt;pDC-&amp;gt;SetBkMode (TRANSPARENT)&lt;br&gt;pDC-&amp;gt;SetTextColor (RGB (255,0,0))&lt;br&gt;CFont font&lt;br&gt;//font object&lt;br&gt;LOGFONT stFont //font definition&lt;br&gt;//Set font attributes that will not change.&lt;br&gt;memset (&amp;amp;stFont, 0, sizeof (LOGFONT))&lt;br&gt;stFont.ifheight=MulDiv (14, -pDC-&amp;gt;GetDeviceCaps(LOGPIXELSY), 72)&lt;br&gt;stFont.ifWeight=FW_NORMAL&lt;br&gt;stFont.ifClipPrecision=LCIP_LH_ANGLES&lt;br&gt;strcpy (stFont.lfFaceName, &amp;quot;Arial&amp;quot;)&lt;br&gt;&lt;br&gt;//Draw text at 15degree intervals.&lt;br&gt;for (int nAngle=0 nAngle&amp;lt;3600 nAngle+=150)&lt;br&gt;{&lt;br&gt;//Specify new angle.&lt;br&gt;stFont.lfEscapement=nAngle&lt;br&gt;&lt;br&gt;//Create and select font into dc.&lt;br&gt;font.CreateFontIndirect(&amp;amp;stfont)&lt;br&gt;CFont* pOldFont=pDC -&amp;gt;SelectObject(&amp;amp;font)&lt;br&gt;&lt;br&gt;//Draw the text.&lt;br&gt;pDC-&amp;gt;SelectObject(pOldFont)&lt;br&gt;font.DelectObjext()&lt;br&gt;}&lt;br&gt;}
&lt;p&gt;
&lt;p&gt;（58） &lt;b&gt;如何正确显示包含标签字符的串&lt;/b&gt;&lt;br&gt;调用GDI文本绘画函数时需要展开标签字符，这可以通过调用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完成。TabbedTextOut函数允许指定标签位的数组，下例指定每20设备单位展开一个标签：&lt;br&gt;&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;CTestDoc* pDoc=GetDocument ()&lt;br&gt;ASSERT_VALID (pDoC)&lt;br&gt;&lt;br&gt;CString str&lt;br&gt;str.Format (_T (&amp;quot;Cathy\tNorman\tOliver&amp;quot;))&lt;br&gt;int nTabStop=20 //tabs are every 20 pixels&lt;br&gt;pDC-&amp;gt;TabbedtextOut (10, 10, str, 1, &amp;amp;nTabStop, 10)&lt;br&gt;}
&lt;p&gt;（59） &lt;b&gt;如何快速地格式化一个CString对象&lt;/b&gt;&lt;br&gt;调用CString:: Format，该函数和printf函数具有相同的参数，下例说明了如何使用Format函数：&lt;br&gt;&lt;br&gt;//Get size of window.&lt;br&gt;CRect rcWindow&lt;br&gt;GetWindowRect (rcWindow)&lt;br&gt;//Format message string.&lt;br&gt;CString strMessage&lt;br&gt;strMessage.Format (_T (&amp;quot;Window Size (%d, %d)&amp;quot;),&lt;br&gt;&lt;br&gt;rcWindow.Width (), rcWindow.Height ())&lt;br&gt;&lt;br&gt;//Display the message.&lt;br&gt;MessageBox (strmessage)
&lt;p&gt;（60） &lt;b&gt;串太长时如何在其末尾显示一个省略号&lt;/b&gt;&lt;br&gt;调用CDC:: DrawText并指定DT_END_ELLIPSIS标志，这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息，指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。&lt;br&gt;&lt;br&gt;void CSampleView:: OnDraw (CDC* pDC)&lt;br&gt;{&lt;br&gt;CTestDoc* pDoc=GetDocument ()&lt;br&gt;ASSERT_VALID (pDoc)&lt;br&gt;&lt;br&gt;//Add ellpsis to end of string if it does not fit&lt;br&gt;pDC-&amp;gt;Drawtext (CString (&amp;quot;This is a long string&amp;quot;), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)&lt;br&gt;&lt;br&gt;//Add ellpsis to middle of string if it does not fit&lt;br&gt;pDC-&amp;gt;DrawText (AfxgetApp () -&amp;gt;m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)&lt;br&gt;}&lt;br&gt;
&lt;p&gt;（61） &lt;b&gt;为什么即使调用EnableMenuItem菜单项后，菜单项还处于禁止状态&lt;/b&gt;&lt;br&gt;需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE，如果该数据成员为TRUE（缺省值），工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。&lt;br&gt;&lt;br&gt;//Disable MFC from automatically disabling menu items.&lt;br&gt;m_bAuoMenuEnable=FALSE&lt;br&gt;//Now enable the menu item.&lt;br&gt;CMenu* pMenu=GetMenu ()&lt;br&gt;ASSERT_VALID (pMenu)&lt;br&gt;&lt;br&gt;pMenu-&amp;gt;EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)
&lt;p&gt;
&lt;p&gt;（62） &lt;b&gt;如何给系统菜单添加一个菜单项&lt;/b&gt;&lt;br&gt;给系统菜单添加一个菜单项需要进行下述三个步骤：&lt;br&gt;首先，使用Resource Symbols对话（在View菜单中选择Resource Symbols．．．可以显示该对话）定义菜单项ID，该ID应大于0x0F而小于0xF000；&lt;br&gt;其次，调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的&lt;br&gt;int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)&lt;br&gt;{&lt;br&gt;…&lt;br&gt;//Make sure system menu item is in the right range.&lt;br&gt;ASSERT (IDM_MYSYSITEM &amp;amp;0xFFF0)==IDM_MYSYSITEM)&lt;br&gt;ASSERT (IDM-MYSYSITEM&amp;lt;0xF000)&lt;br&gt;&lt;br&gt;//Get pointer to system menu.&lt;br&gt;CMenu* pSysmenu=GetSystemmenu (FALSE)&lt;br&gt;ASSERT_VALID (pSysMenu)&lt;br&gt;//Add a separator and our menu item to system menu.&lt;br&gt;CString StrMenuItem (_T (&amp;quot;New menu item&amp;quot;))&lt;br&gt;pSysMenu-&amp;gt;Appendmenu (MF_SEPARATOR)&lt;br&gt;pSysMenu-&amp;gt;AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)&lt;br&gt;&lt;br&gt;…&lt;br&gt;}&lt;br&gt;&lt;br&gt;现在，选择系统菜单项时用户应进行检测。使用ClassWizard处理WM_SYSCOMMAND消息并检测用户菜单的nID参数：&lt;br&gt;void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)&lt;br&gt;{&lt;br&gt;//Determine if our system menu item was selected.&lt;br&gt;if ( (nID &amp;amp; 0xFFF0)==IDM_MYSYSITEM)&lt;br&gt;{&lt;br&gt;//TODO-process system menu item&lt;br&gt;}&lt;br&gt;&lt;br&gt;else&lt;br&gt;CMDIFrameWnd ::OnSysCommand (nID, lParam)&lt;br&gt;}&lt;br&gt;最后，一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息，这可以通过增加一个包含系统菜单基ID的串表的入口来实现。
&lt;p&gt;（63） &lt;b&gt;如何确定顶层菜单所占据的菜单行数&lt;/b&gt;&lt;br&gt;这可以通过简单的减法和除法来实现。首先，用户需要计算主框窗口的高度和客户区；其次，从主框窗口的高度中减去客户区、框边界以及标题的高度；最后，除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。&lt;br&gt;&lt;br&gt;int CMainFrame:: GetMenuRows ()&lt;br&gt;{&lt;br&gt;CRect rcFrame,rcClient&lt;br&gt;GetWindowRect (rcFrame)&lt;br&gt;GetClientRect (rcClient)&lt;br&gt;return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)&lt;br&gt;}
&lt;p&gt;（64） &lt;b&gt;在用户环境中如何确定系统显示元素的颜色&lt;/b&gt;&lt;br&gt;调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。&lt;br&gt;&lt;br&gt;void CMiniFrameWnd:: OnNcPaint ()&lt;br&gt;{&lt;br&gt;…&lt;br&gt;dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))&lt;br&gt;…
&lt;p&gt;
&lt;p&gt;（65） &lt;b&gt;如何查询和设置系统参数&lt;/b&gt;&lt;br&gt;在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo，调用该函数可以查询和设置系统参数，诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。&lt;br&gt;&lt;br&gt;//Create a font that is used for icon titles.&lt;br&gt;LOGFONT stFont&lt;br&gt;∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &amp;amp;stFont, SPIF_SENDWININICHANGE)&lt;br&gt;m_font.CreateFontIndirect (&amp;amp;stFont)&lt;br&gt;&lt;br&gt;//Change the wallpaper to leaves.bmp.&lt;br&gt;∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (&amp;quot; forest.bmp&amp;quot;), SPIF_UPDATEINIFILE)
&lt;p&gt;
&lt;p&gt;（66） &lt;b&gt;如何确定当前屏幕分辨率&lt;/b&gt;&lt;br&gt;调用SDK函数GetSystemMetrics，该函数可以检索有关windows显示信息，诸如标题大小、边界大小以及滚动条大小等等。&lt;br&gt;&lt;br&gt;//Initialize CSize object with screen size.&lt;br&gt;CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),&lt;br&gt;GetSystemMetrics (SM_CYSCREEN))
&lt;p&gt;
&lt;p&gt;（67） &lt;b&gt;如何使用一个预定义的Windows光标&lt;/b&gt;&lt;br&gt;调用CWinApp:: LoadStandardCursor并传送光标标识符。&lt;br&gt;BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,&lt;br&gt;UINT nHitTest, UINT&lt;br&gt;message)&lt;br&gt;{&lt;br&gt;//Display wait cursor if busy.&lt;br&gt;if (m_bBusy)&lt;br&gt;{&lt;br&gt;SetCursor (AfxGetApp () -&amp;gt;LoadStandardCursor (IDC_WAIT))&lt;br&gt;return TRUE&lt;br&gt;}&lt;br&gt;&lt;br&gt;return CDialog:: OnSetCursor (pWnd. nHitTest,message)&lt;br&gt;}
&lt;p&gt;（68） &lt;b&gt;如何检索原先的Task Manager应用程序使用的任务列表&lt;/b&gt;&lt;br&gt;原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表，窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以检索顶层窗口的列表，调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。&lt;br&gt;&lt;br&gt;void GetTadkList (CListBox&amp;amp;list)&lt;br&gt;{&lt;br&gt;CString strCaption&lt;br&gt;//Caption of window.&lt;br&gt;&lt;br&gt;list.ResetContent ()&lt;br&gt;//Clear list box.&lt;br&gt;&lt;br&gt;//Get first Window in window list.&lt;br&gt;ASSERT_VALID (AfxGetMainWnd ())&lt;br&gt;CWnd* pWnd=AfxGetMainWnd () -&amp;gt;GetWindow (GW_HWNDFIRST)&lt;br&gt;&lt;br&gt;//Walk window list.&lt;br&gt;while (pWnd)&lt;br&gt;{&lt;br&gt;// I window visible, has a caption, and does not have an owner?&lt;br&gt;if (pWnd -&amp;gt;IsWindowVisible()&lt;br&gt;&amp;amp;&amp;amp; pWnd -&amp;gt;GetWindowTextLength ()&lt;br&gt;&amp;amp;&amp;amp;! pWnd -&amp;gt;GetOwner ())&lt;br&gt;{&lt;br&gt;&lt;br&gt;//Add caption o window to list box.&lt;br&gt;&lt;br&gt;pWnd -&amp;gt;GetWindowText (strCaption)&lt;br&gt;&lt;br&gt;list.AddString (strCaption)&lt;br&gt;}&lt;br&gt;//Get next window in window list.&lt;br&gt;pWnd=pWnd -&amp;gt;GetWindow(GW_HWNDNEXT)&lt;br&gt;}&lt;br&gt;}
&lt;p&gt;（69） &lt;b&gt;如何确定Windows和Windows系统目录&lt;/b&gt;&lt;br&gt;有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory，下例说明了如何使用这两个函数：&lt;br&gt;&lt;br&gt;TCHAR szDir [MAX_PATH]&lt;br&gt;//Get the full path of the windows directory.&lt;br&gt;∶ : GetWindowsDirectory (szDir, MAX_PATH)&lt;br&gt;TRACE (&amp;quot;Windows directory %s\n&amp;quot;, szDir)&lt;br&gt;//Get the full path of the windows system directory.&lt;br&gt;∶ : GetSystemDirectory (szDir, MAX_PATH)&lt;br&gt;TRACE (&amp;quot;Windows system directory %s\n&amp;quot;, szDir)
&lt;p&gt;（70） &lt;b&gt;在哪儿创建临文件&lt;/b&gt;&lt;br&gt;调用SDK函数GetTemPath可以确定临时文件的目录，该函数首先为临时路径检测TMP环境变量：如果没有指定TMP，检测TMP环境变量，然后返回到当前目录。下例说明了如何创建一个临时文件。&lt;br&gt;&lt;br&gt;…&lt;br&gt;//get unique temporary file.&lt;br&gt;CString strFile&lt;br&gt;GetUniqueTempName (strFile)&lt;br&gt;TRY&lt;br&gt;{&lt;br&gt;//Create file and write data.Note that file is closed&lt;br&gt;//in the destructor of the CFile object.&lt;br&gt;CFile file (strFile,CFile ::modeCreate | Cfile:: modeWrite)&lt;br&gt;&lt;br&gt;//write data&lt;br&gt;}&lt;br&gt;&lt;br&gt;CATCH (CFileException, e)&lt;br&gt;{&lt;br&gt;//error opening file&lt;br&gt;}&lt;br&gt;END_CATCH&lt;br&gt;…&lt;br&gt;&lt;br&gt;Void GetuniqueTempName (CString&amp;amp; strTempName)&lt;br&gt;{&lt;br&gt;//Get the temporary files directory.&lt;br&gt;TCHAR szTempPath [MAX_PATH]&lt;br&gt;DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)&lt;br&gt;ASSERT (dwResult)&lt;br&gt;&lt;br&gt;//Create a unique temporary file.&lt;br&gt;TCHAR szTempFile [MAX_PATH]&lt;br&gt;UINT nResult=GetTempFileName (szTempPath, _T (&amp;quot;~ex&amp;quot;),0,szTempfile)&lt;br&gt;ASSERT (nResult)&lt;br&gt;&lt;br&gt;strTempName=szTempFile&lt;br&gt;}
&lt;p&gt;（71） &lt;b&gt;我怎样才能建立一个等待光标?&lt;/b&gt;&lt;br&gt;调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标，调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标。要 注 意，二 者 都 要 调 用 app 的 成 员 函 数，如 下 所 示:&lt;br&gt;&lt;br&gt;    AfxGetApp()-&amp;gt;BeginWaitCursor();&lt;br&gt;    // 要做的事&lt;br&gt;    AfxGetApp()-&amp;gt;EndWaitCursor();
&lt;p&gt;（72） &lt;b&gt;我在MDI框架中有个 form 视窗。它有个取消按钮，我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?&lt;/b&gt;&lt;br&gt;调 用 OnCloseDocument 函 数。
&lt;p&gt;（73） &lt;b&gt;如何访问桌面窗口&lt;/b&gt;&lt;br&gt;静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。&lt;br&gt;&lt;br&gt;void CFrameWnd::BeginModalState ()&lt;br&gt;{&lt;br&gt;…&lt;br&gt;//first count all windows that need to be disabled&lt;br&gt;UINT nCount=0&lt;br&gt;HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)&lt;br&gt;while (hWnd!=NULL)&lt;br&gt;{&lt;br&gt;if (:: IsWindowEnabled (hwnd)&lt;br&gt;&amp;amp;&amp;amp; CWnd::FromHandlePermanent (hWnd)!=NULL&lt;br&gt;&amp;amp;&amp;amp; AfxIsDescendant (pParent-&amp;gt;m_hWnd, hWnd)&lt;br&gt;&amp;amp;&amp;amp; :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)&lt;br&gt;{&lt;br&gt;++nCount&lt;br&gt;}&lt;br&gt;hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)&lt;br&gt;}&lt;br&gt;…
&lt;p&gt;（74） &lt;b&gt;什么是COLORREF? 我该怎样用它?&lt;/b&gt;&lt;br&gt;COLORREF 是 一 个 32-bit 整 型 数 值，它 代 表 了 一 种 颜 色。你 可 以 使 用 RGB 函 数 来 初 始 化 COLORREF。例 如：&lt;br&gt;&lt;br&gt;    COLORREF color = RGB(0, 255, 0);&lt;br&gt;RGB 函 数 接 收 三 个 0-255 数 值，一 个 代 表 红 色， 一 个 代 表 绿 色， 一 个 代 表 蓝 色。在 上 面的 例 子 中， 红 色 和 蓝 色 值 都 为 0，所 以 在 该 颜 色 中 没 有 红 色 和 蓝 色。绿 色 为 最 大 值 255。所 以 该 颜 色 为 绿 色。0,0,0 为 黑 色，255,255,255 为 白 色。&lt;br&gt;&lt;br&gt;另 一 种 初 始 化 COLORREF 的 方 法 如 下 所 示：&lt;br&gt;&lt;br&gt;    CColorDialog colorDialog;&lt;br&gt;    COLORREF color;&lt;br&gt;&lt;br&gt;    if( colorDialog.DoModal() == IDOK )&lt;br&gt;    {&lt;br&gt;        color = colorDialog.GetColor();&lt;br&gt;    }&lt;br&gt;这 段 代 码 使 用 了 MFC 中 的 颜 色 对 话 框，它 需 要 文 件。
&lt;p&gt;
&lt;p&gt;（75） &lt;b&gt;AppWizard所产生的STDAFX文件是干什么用的?&lt;/b&gt;&lt;br&gt;它 主 要 是 协 助 产 生 预 编 译 头 文 件 的。通 常 你 是 不 需 要 修 改 它 的。
&lt;p&gt;（76） &lt;b&gt;我在我的程序中是了CDWordArray。我向它添加了约10,000个整数，这使得它变得非常非常慢。为什么会这么糟?&lt;/b&gt;&lt;br&gt;CDWordArray 是 很 好 用 的，只 是 因 为 你 没 有 指 定 数 组 的最大尺寸。因 此，当 你 添 加 新 元 素 时，该 类 会 从 堆 中 重 新 分 配 空 间。不 幸 的 是，该 类 会 在 每 次 插 入 新 元 素 时 都 为 数 组 重 新 分 配 空 间。如 果 你 向 它 添 加 了 很 多 新 元 素，所 有 这 些 分 配 和 复 制 数 组 的 操 作 会 就 会 使 它 变 慢。解 决 该 问 题 的 方 法 是，你 可 以 使 用 SetSize 函 数 的 第 二 个 参 数 来 改 变 这 种 重 新 分 配 的 频 率。例 如，如 果 你 把 该 参 数 设 置 为 500，则 每 次 数 组 空 间 超 出 时 它 才 重 新 分 配 并 添 加 500 个 新 空 间，而 不 是 1 个。这 样 一 来，你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 个 元 素 空 间，这 也 会 大 大 提 高 程 序 的 运 行 速 度。
&lt;p&gt;
&lt;p&gt;（77） &lt;b&gt;我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?&lt;/b&gt;&lt;br&gt;在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。GetParentFrame 会 返 回 一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow。
&lt;p&gt;（78） &lt;b&gt;在我的程序的某些部分，我可以调用 MessageBox 函数来建立一个信息对话框，例如在视类中。但是，在其它部分我却不能，如文档类中。为什么？我怎样才能在我的应用程序类中建立一个信息对话框？&lt;/b&gt;&lt;br&gt;MessageBox 函 数 来 自 CWnd 类，所 以 你 只 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是，MFC 也 提 供 了 AfxMessageBox 函 数，你 可 以 在 任 何 地 方 调 用 它。
&lt;p&gt;
&lt;p&gt;（79） &lt;b&gt;我需要在我的程序中设置全局变量，以使文档中的所有类都能访问。我应该吧它放到哪儿?&lt;/b&gt;&lt;br&gt;把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处。然 后，在 程 序 的 任 何 地 方，你 都 可 以 用 下 面 的 方 法 来 访 问 该 变 量：&lt;br&gt;&lt;br&gt;    CMyApp *app = (CMyApp *)AfxGetApp();&lt;br&gt;    app-&amp;gt;MyGlobalVariable = ...
&lt;p&gt;（80） &lt;b&gt;我听说MFC可以发现内存漏洞，我怎样使用该特性?&lt;/b&gt;&lt;br&gt;如 果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你 的 应 用 程 序，MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有，那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 )，并 启 动 跟 踪。然 后 返 回 应 用 程 序。
&lt;p&gt;（81） &lt;b&gt;我怎样才能在我的应用程序中循环浏览已经打开的文档?&lt;/b&gt;&lt;br&gt;使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。 
&lt;p&gt;
&lt;p&gt;（82）&lt;b&gt;才能在我的应用程序中循环浏览已经打开的视?&lt;/b&gt;&lt;br&gt;使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。
&lt;p&gt;（83）&lt;b&gt;数PreCreateWindow是干什么用的?&lt;/b&gt;&lt;br&gt;PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。
&lt;p&gt;（84）&lt;b&gt;该怎样防止MFC在窗口标题栏上把文档名预置成应用程序名?&lt;/b&gt;&lt;br&gt;在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式：&lt;br&gt;&lt;br&gt;    cs.style &amp;amp;= ~FWS_PREFIXTITLE;
&lt;p&gt;
&lt;p&gt;（85） &lt;b&gt;我应该怎样防止MFC在窗口标题栏上添加文档名?&lt;/b&gt;&lt;br&gt;在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式：&lt;br&gt;&lt;br&gt;    cs.style &amp;amp;= ~FWS_ADDTOTITLE ;
&lt;p&gt;
&lt;p&gt;（86） &lt;b&gt;我应该如何改变视窗口的大小?&lt;/b&gt;&lt;br&gt;因 为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口，所 以 你 必 须 改 变 框 架 窗 口 的 大 小，而 不 是 改 变 视 窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针，然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。
&lt;p&gt;（87） &lt;b&gt;我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?&lt;/b&gt;&lt;br&gt;把“delete this”加 到 PostNcDestroy 中。这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。
&lt;p&gt;
&lt;p&gt;（88） &lt;b&gt;为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?&lt;/b&gt;&lt;br&gt;OnNcDestroy 只 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow )，则 没 有 窗 口 处 来 发 送 WM_NCDESTROY 消 息。PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除，在 OnNcDestroy 后，甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。
&lt;p&gt;
&lt;p&gt;（89） &lt;b&gt;File菜单中的MRU列表是从哪儿来的？列表中的名字放在哪儿了？我怎样才能改变列表中项目的最大值？&lt;/b&gt;&lt;br&gt;在 应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。该 调 用 接 受 一 个 参 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 )。MRU 文 件 名 是 从 INI 文 件 中 调 用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项，它 会 为 调 入 的 MRU 列 表 所 替 换。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 )，则 你 就 改 变 了 所 装 如 文 件 名 的 最 大 值。
&lt;p&gt;（90） &lt;b&gt;我在菜单中添加了新的项。但是，当我选该项时，在状态栏上没有出现任何提示信息。为什么?&lt;/b&gt;&lt;br&gt;打 开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ，你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已 经 建 立 的 工 具 栏 按 钮 ):&lt;br&gt;&lt;br&gt;    Status bar string\nFlying tag
&lt;p&gt;（91） &lt;b&gt;我怎样才能在应用程序的缺省系统菜单中加上一些东西?&lt;/b&gt;&lt;br&gt;系 统 菜 单 与 其 它 菜 单 类 似，你 可 以 添 加 或 删 除 项 目，这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项：&lt;br&gt;&lt;br&gt;    CMenu *sysmenu;&lt;br&gt;    sysmenu = m_pMainWnd-&amp;gt;GetSystemMenu(FALSE);&lt;br&gt;    sysmenu-&amp;gt;AppendMenu(MF_STRING, 1000, &amp;quot;xxx&amp;quot;);&lt;br&gt;参 见 MFC 帮 助 文 件 中 的 CMenu 类。
&lt;p&gt;（92） &lt;b&gt;我建立了一个对话框。但是当我显示该对话框时，第一个编辑框总是不能获得焦点，我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?&lt;/b&gt;&lt;br&gt;打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜单 中 选 择 Tab Order 选 项。按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。
&lt;p&gt;（93） &lt;b&gt;我怎样才能使一个窗口具有“always on top”特性?&lt;/b&gt;&lt;br&gt;在 调 用 OnFileNew 后，在 你 的 InitInstance 函 数 中 加 上 下 面 的 代 码：&lt;br&gt;&lt;br&gt;m_pMainWnd-&amp;gt;SetWindowPos(&amp;amp;CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
&lt;p&gt;(94)   我要为我的form view添加文档模板。我先建立了对话框模板，然后使用ClassWizard建立了基于CFormView的新类，它也是从CDocument继承来的。我还建立了相应的资源并在InitInstance中添加了新的文档模板。但是，当我试图运行该程序时，出现了Assertion信息。为什么?
&lt;p&gt;form 的 对 话 框 模 板 需 要 些 特 殊 设 置 以 便 可 用 于 CFromView。确 保 这 些 设 置 的 最 简 单 方 法 是 使 用 AppWizard 来 建 立 CFormView 应 用 程 序，并 查 看 AppWizard 所 建 立 的 对 话 框 模 板 所 选 择 的Styles Properties。你 会 发 现 该 对 话 框 模 板 具 有 下 列 样 式：没 有 标 题 栏、不 可 见 和“Child”。把 你 的 form view 的 对 话 框 属 性 变 成 这 样 就 可 以 了。&lt;br&gt;&lt;br&gt;(95)   我在一对话框中有一列表框，我需要tabbed列表框中的项目。但是，当我处理含有tab字符(用AddString添加的)的列表项时，tab被显示成小黑块而没有展开。哪儿出错了?
&lt;p&gt;在 对 话 框 模 版 中，打 开 列 表 框 的 属 性。确 保 选 择 了“Use Tabstops” 样 式。然 后，确 保 在 对 话 框 类 中 OnInitDialog 函 数 中 调 用 SetTabStops。&lt;br&gt;&lt;br&gt;(96)  我建立了一个应用程序，并使用了CRecordset类。但是，当我运行该程序时，它试图要访问数据库，并给出“Internal Application Error”对话框。我应该怎样做?
&lt;p&gt;通 常 情 况 下，当 你 的 程 序 中 向 数 据 库 发 送 信 息 的 SQL 语 句 出 现 问 题 时 才 出 现 该 对 话 框。例 如，参 见 下 面 的 例 子：&lt;br&gt;&lt;br&gt;    set.m_strFilter = &amp;quot;(ZipCode = '27111')&amp;quot;;&lt;br&gt;如 果 ZipCode 列 被 定 义 为 字 符 串 时 不 会 出 现 问 题，如 果 定 义 为 long，则 会 出 现“Internal Application Error”对 话 框，这 是 由 于 类 型 不 匹 配 的 缘 故。如 果 你 删 除 27111 的 单 引 号，则 不 会 出 现 问 题。当 你 看 到“Internal Application Error”时，最 好 检 查 一 下 试 图 要 发 送 给 数 据 库 的 SQL 语 句。&lt;br&gt;&lt;br&gt;(97)   我用ClassWizard建立了一个类。但是，我把名字取错了，我想把它从项目中删除，应该如何做?
&lt;p&gt;在 ClassWizard 对 话 框 关 闭 后，用 文 件 管 理 器 删 除 新 类 的 H 和 CPP 文 件。然 后 打 开 ClassWizard，它 会 提 示 丢 失 了 两 个 文 件，并 询 问 你 该 如 何 做。你 可 以 选 择 从 项 目 中 删 除 这 两 个 问 的 按 钮。&lt;br&gt;
&lt;p&gt;(98)     当我打开应用程序中的窗口时，我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小，但是当我调用GetClientRect时，所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?
&lt;p&gt;参 见 CWnd::CalcWindowRect。&lt;br&gt;&lt;br&gt;(99)   我在文档类中设置了一个整型变量。但是，当我试图把该变量写入Serialize函数中的archive文件中时，出现了类型错误。而文档中的其它变量没有问题。为什么?
&lt;p&gt;archive 类 只 重 载 某 些 类 型 的 &amp;gt;&amp;gt; 和 &amp;lt;&amp;lt; 操 作 符。“int”类 型 没 有 在 其 中，也 许 是 因 为 int 变 量 在 Windows 3.1 与 Windows NT/95 有 所 不 同 的 缘 故 吧。“long”类 型 得 到 了 支 持，所 以 你 可 以 把 int 类 型 改 成 long 型。参 见 MFC 帮 助 文 件 中 CArchive 类。&lt;br&gt;
&lt;p&gt;&lt;br&gt;(100)  如何控制菜单的大小?&lt;br&gt;我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).
&lt;p&gt;方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.&lt;br&gt;方法二:查询系统::GetSystemMetric(SM_CXMENUSIZE).
&lt;p&gt;     /* 你可以通过如下代码来获得文本的大小:&lt;br&gt;        (A)获得被使用的字体 */
&lt;p&gt;       NONCLIENTMETRICS ncm;&lt;br&gt;     HFONT hFontMenu;&lt;br&gt;     SIZE size;&lt;br&gt;     size.cy = size.cy = 0;
&lt;p&gt;     memset(&amp;amp;ncm, 0, sizeof(NONCLIENTMETRICS));&lt;br&gt;     ncm.cbSize = sizeof(NONCLIENTMETRICS);&lt;br&gt;     if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &amp;amp;ncm, 0))&lt;br&gt;     {&lt;br&gt;          hFontMenu = CreateFontIndirect(&amp;amp;ncm.lfMenuFont);&lt;br&gt;          /*&lt;br&gt;          (B) 获得菜单项的文本: */&lt;br&gt;          char szText[_MAX_PATH];
&lt;p&gt;          pMenu-&amp;gt;GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);&lt;br&gt;          /*&lt;br&gt;          然后,获得菜单项文本的高度: */&lt;br&gt;          HFONT hFontOld;&lt;br&gt;          HDC hDC;
&lt;p&gt;          hDC = ::GetDC(NULL);&lt;br&gt;          hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);&lt;br&gt;          GetTextExtentPoint32(hDC, szText, lstrlen(szText), &amp;amp;size);&lt;br&gt;          SelectObject(hDC, hFontOld);&lt;br&gt;          ::ReleaseDC(NULL, hDC);&lt;br&gt;     }&lt;br&gt;     /*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4
&lt;p&gt;比较合适。*/
&lt;p&gt;&lt;br&gt;(101)  改变LVIS_SELECTED的状态颜色?&lt;br&gt;我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.
&lt;p&gt;方法一:查找函数CustomDraw,它是IE4提供的公共控制,允许有你自己的代码.&lt;br&gt;方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.
&lt;p&gt;(102)   如何只存储文档的某一部分?&lt;br&gt;我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.
&lt;p&gt;(103)   保存工具条菜单有bug吗?&lt;br&gt;
&lt;p&gt;使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个PToolBar-&amp;gt;Create(this,...,ID_MYTOOLBAR);&lt;br&gt;你的工具条需要包括id,而不是象默认的工具条那样.
&lt;p&gt;(104)   Tip of the day的bug
&lt;p&gt;我创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开mdi应用程序同时打开foo.bsf文档.但当我给mdi应用程序加上a tip of the day组件之后,从资源管理器中双击foo.bsf后,就会给我一个警告:ASSERT(::IsWindow(m_hWnd)),然后mdi应用程序就死那了.&lt;br&gt;&lt;br&gt;当从dde启动应用程序(例如:双击相关文档)时,&amp;quot;Tip of the Day&amp;quot;是有bug的.你可以看看函数&amp;quot;ShowTipAtStartup&amp;quot;,它在&amp;quot;InitInstance&amp;quot;中调用,可以看到tip of the day作为一个模式对话框显示,在处理其它消息时它一直进行消息循环你可心修改ShowTipAtStartup使其从dde启动时不出现tip of the day.&lt;br&gt;void CTipOfApp::ShowTipAtStartup(void)&lt;br&gt;        {&lt;br&gt;                // CG: This function added by 'Tip of the Day' component.&lt;br&gt;&lt;br&gt;                CCommandLineInfo cmdInfo;&lt;br&gt;                ParseCommandLine(cmdInfo);&lt;br&gt;&lt;br&gt;                if (&lt;br&gt;                        cmdInfo.m_bShowSplash &amp;amp;&amp;amp;&lt;br&gt;                        cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE&lt;br&gt;                        )&lt;br&gt;                {&lt;br&gt;                        CTipDlg dlg;&lt;br&gt;                        if (dlg.m_bStartup)&lt;br&gt;                                dlg.DoModal();&lt;br&gt;                }&lt;br&gt;        }&lt;br&gt;如果还有其它bug,你可以设定cmdInfo.m_nShellCommand的过滤.&lt;br&gt;&lt;br&gt;(105)   如何可以让我的程序可以显示在其它的窗口上面?&lt;br&gt;&lt;br&gt;让用户选择&amp;quot;总是在最上面&amp;quot;最好是在系统菜单里加入一个选项.可以通过修改WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个参数传给OnSysCommand().要定义标识(id),将如下代码加入到CMainFrame.CPP中:&lt;br&gt;&lt;br&gt;    #define WM_ALWAYSONTOP WM_USER + 1&lt;br&gt;将&amp;quot;总在最上面&amp;quot;的菜单项加入到系统菜单中,将如下代码加入到函数CMainFrame::OnCreate()中:&lt;br&gt;&lt;br&gt;      CMenu* pSysMenu = GetSystemMenu(FALSE);&lt;br&gt;      pSysMenu-&amp;gt;AppendMenu(MF_SEPARATOR);&lt;br&gt;      pSysMenu-&amp;gt;AppendMenu(MF_STRING, WM_ALWAYSONTOP,&lt;br&gt;                     &amp;quot;&amp;amp;Always On Top&amp;quot;);&lt;br&gt;使用ClassWizard,加入对WM_SYSCOMMAND消息的处理,你应该改变消息过滤器,使用系统可以处理这个消息.&lt;br&gt;void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)&lt;br&gt;{&lt;br&gt;    switch ( nID )&lt;br&gt;    {&lt;br&gt;    case WM_ALWAYSONTOP:&lt;br&gt;&lt;br&gt;        if ( GetExStyle() &amp;amp; WS_EX_TOPMOST )&lt;br&gt;        {&lt;br&gt;            SetWindowPos(&amp;amp;wndNoTopMost, 0, 0, 0, 0,&lt;br&gt;                SWP_NOSIZE | SWP_NOMOVE);&lt;br&gt;            GetSystemMenu(FALSE)-&amp;gt;CheckMenuItem(WM_ALWAYSONTOP,&lt;br&gt;                MF_UNCHECKED);&lt;br&gt;        }&lt;br&gt;        else&lt;br&gt;        {&lt;br&gt;            SetWindowPos(&amp;amp;wndTopMost, 0, 0, 0, 0,&lt;br&gt;                SWP_NOSIZE | SWP_NOMOVE);&lt;br&gt;            GetSystemMenu(FALSE)-&amp;gt;CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        break;&lt;br&gt;&lt;br&gt;    default:&lt;br&gt;        CFrameWnd::OnSysCommand(nID, lParam);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;br&gt;(106)    如何控制窗口框架的最大最小尺寸?
&lt;p&gt;要控制一个框架的的最大最小尺寸,你需要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.&lt;br&gt;&lt;br&gt;// 最大最小尺寸的象素点 - 示例&lt;br&gt;#define MINX 200&lt;br&gt;#define MINY 300&lt;br&gt;#define MAXX 300&lt;br&gt;#define MAXY 400&lt;br&gt;&lt;br&gt;void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)&lt;br&gt;{&lt;br&gt;    CRect rectWindow;&lt;br&gt;    GetWindowRect(&amp;amp;rectWindow);&lt;br&gt;&lt;br&gt;    CRect rectClient;&lt;br&gt;    GetClientRect(&amp;amp;rectClient);&lt;br&gt;&lt;br&gt;      // get offset of toolbars, scrollbars, etc.&lt;br&gt;    int nWidthOffset = rectWindow.Width() - rectClient.Width();&lt;br&gt;    int nHeightOffset = rectWindow.Height() - rectClient.Height();&lt;br&gt;&lt;br&gt;    lpMMI-&amp;gt;ptMinTrackSize.x = MINX + nWidthOffset;&lt;br&gt;    lpMMI-&amp;gt;ptMinTrackSize.y = MINY + nHeightOffset;&lt;br&gt;    lpMMI-&amp;gt;ptMaxTrackSize.x = MAXX + nWidthOffset;&lt;br&gt;    lpMMI-&amp;gt;ptMaxTrackSize.y = MAXY + nHeightOffset;&lt;br&gt;}&lt;br&gt;第二步,在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果.&lt;br&gt;&lt;br&gt;BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT&amp;amp; cs)&lt;br&gt;{&lt;br&gt;    cs.style &amp;amp;= ~WS_MAXIMIZEBOX;&lt;br&gt;    return CFrameWnd::PreCreateWindow(cs);&lt;br&gt;}&lt;br&gt;&lt;br&gt;(107)    如何改变窗口框架的颜色?
&lt;p&gt;MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,&lt;br&gt;#include &amp;quot;MDIClient.h&amp;quot;&lt;br&gt;class CMainFrame : public CMDIFrameWnd&lt;br&gt;{&lt;br&gt;...&lt;br&gt;protected:&lt;br&gt;CMDIClient m_wndMDIClient;&lt;br&gt;}&lt;br&gt;在CMainFrame中重载CMDIFrameWnd::OnCreateClient&lt;br&gt;BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)&lt;br&gt;{&lt;br&gt;    if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )&lt;br&gt;    {&lt;br&gt;        m_wndMDIClient.SubclassWindow(m_hWndMDIClient);&lt;br&gt;        return TRUE;&lt;br&gt;    }&lt;br&gt;    else&lt;br&gt;        return FALSE;&lt;br&gt;}&lt;br&gt;然后就可以加入对消息WM_ERASEBKGND的处理了.&lt;br&gt;&lt;br&gt;(108)    如何将应用程序窗口置于屏幕正中?
&lt;p&gt;要将你的应用程序窗口放置在屏幕正中央,只须在MainFrame的OnCreate函数中加入:&lt;br&gt;CenterWindow( GetDesktopWindow() );&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=449534861986366027&amp;page=RSS%3a+VC%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e7%99%be%e9%97%ae&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=wdllstudio.spaces.live.com&amp;amp;GT1=wdllstudio"&gt;</description><comments>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!164.entry#comment</comments><guid isPermaLink="true">http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!164.entry</guid><pubDate>Mon, 02 Jan 2006 04:54:17 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://wdllstudio.spaces.live.com/blog/cns!63D119342DA024B!164/comments/feed.rss</wfw:commentRss><wfw:comment>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!164.entry#comment</wfw:comment><dcterms:modified>2006-01-02T04:54:17Z</dcterms:modified></item><item><title>MFC窗口位置管理详细分析</title><link>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!163.entry</link><description>&lt;div&gt;   在一般用MFC编写的程序的窗口客户区中，可能有好几个子窗口(具有WM_CHILD风格的窗口)。上边是工具栏，中间是视图窗口，下边是状态栏。三个窗口在框架的客户区里和平共处，互不重叠。主框架窗口的尺寸改变了，别的子窗口都能及时调整自己的尺寸以便保持相互位置关系不变，例如状态条窗口总能保持在主框架客户区底部，并且其宽度总能和主框架客户区宽度一致。工具栏窗口总能停靠在主框架的某一边不变，其宽度或高度总能和主框架客户区的宽度或高度一致，视图窗口总能填满主框架客户区的剩余空间。 &lt;br&gt;&lt;br&gt;   假如我们自己从CWnd类派生一个窗口类并生成一个窗口，在它的客户区里要生成若干个子窗口，我们想使这些子窗口排列得规规矩矩，互不重叠，当父窗口的尺寸变了时各个子窗口能适时调整自己的尺寸和位置，使各个子窗口之间的位置大小比例关系不变。当移动其中一个或几个子窗口时，别的子窗口能及时为这个移动了的子窗口让位。当然我们可以利用api函数里管理窗口的函数来编写自己的管理子窗口的方法。可是如果在父窗口的客户区里有了工具栏，状态条等等子窗口时，你自己加进来的子窗口还能和这些mfc提供的子窗口融洽相处吗？你如何保证你的子窗口不会覆盖了能够四处停靠的工具栏？当工具栏和状态条消失后你的子窗口如何才能知道，以便及时调整自己的大小从而覆盖工具栏和状态条腾出的空间？基于文档视图构架的窗口的客户区内还有个视图，你自己硬加上的子窗口能不和视图窗口争地盘吗？ &lt;br&gt;&lt;br&gt;   所以必须了解mfc的窗口管理它的客户区的方法。其实，mfc的窗口管理它的客户区的方法是非常简单的：父窗口调用一个函数，子窗口响应一个消息，就这么多。 &lt;br&gt;&lt;br&gt;   CWnd::RepositionBars函数和WM_SIZEPARENT消息 &lt;br&gt;&lt;br&gt;   先简述一下mfc的窗口为子窗口分配客户区空间的过程：这一过程是父窗口与子窗口共同协调完成的。父窗口先提供它的客户区内的一块区域，叫做起始可用区域。然后调用一个函数，在这个函数里，父窗口把这片区域通过一个消息提交给它的第一个子窗口，该子窗口决定自己要占用多大一块，然后在可用区域里把它将占据的部分划出去，这样可用区域就被切去了一块。父窗口再把这块剩下的可用区域通过同样的消息提交给第二个子窗口，第二个子窗口再根据自己的需要切掉一块。如此这般，每个子窗口都切去自己所需的一块。最后剩下的可用区域就给最后的子窗口使用。可以看出，除了最后一个子窗口外，其它子窗口都得在消息响应函数里有自己的算法来决定自己将在可用区域里占据多大一块，最后一个子窗口由于别无选择，所以不需要这样的算法。&lt;br&gt;&lt;br&gt;举例说来，在一个典型单文档程序中，父窗口就是从CFrameWnd派生的主框架窗口，最后一个子窗口就是视图窗口，如果用了CSplitterWnd生成分隔条的话，最后一个子窗口就是拥有分隔条的那个窗口。其它子窗口就是工具栏窗口和状态条窗口，以及可能有的别的控件窗口。 &lt;br&gt;&lt;br&gt;在典型多文档界面程序中，父窗口就是主框架窗口，最后一个子窗口就是覆盖在主窗口客户区，背景为黑灰色，拥有包含文档的子框架窗口的那个窗口，这是个预定义了窗口类的窗口，它的窗口类名是“MDIClient”。如果用了CSplitterWnd生成分隔条的话，最后一个子窗口就是拥有分隔条的那个窗口。其它窗口就是工具栏窗口，状态条窗口以及可能有的别的控件窗口。 &lt;br&gt;&lt;br&gt;这个函数和消息是：函数CWnd::RepositionBars()以及消息WM_SIZEPARENT。这个消息是mfc自定义的，不是windows自有的。 &lt;br&gt;&lt;br&gt;先简单说明一下这个函数和消息。 &lt;br&gt;&lt;br&gt;1。函数CWnd::RepositionBars() &lt;br&gt;&lt;br&gt;这个函数不是虚函数，所以就无法在派生类里通过覆盖来编制自己的版本了，只能搞懂它的功能，以便能灵活使用。 &lt;br&gt;&lt;br&gt;简单而言，这个函数的功能是将可用的客户区区域信息放到消息WM_SIZEPARENT的消息参数里，然后枚举本窗口的所有子窗口，给每个子窗口 (除掉一个特定的子窗口，相当于上文提到的最后一个子窗口)都发送这个消息，每个响应这个消息的子窗口都会把可用客户区切去一块。最后把那个特定的子窗口的尺寸和位置调整到刚好放在最后剩下的可用区域里。 &lt;br&gt;&lt;br&gt;2。消息WM_SIZEPARENT &lt;br&gt;&lt;br&gt;每个欲参与分配客户区的子窗口都要响应这个消息，除非这个子窗口是那个特定的子窗口。 &lt;br&gt;&lt;br&gt;响应这个消息的子窗口至少要做两件事：1，将可用的父窗口客户区切去自己所占据的一块。2，根据消息参数的指示，将自己的大小和位置调整到刚好容纳到自己所占据的区域里或不做调整。 &lt;br&gt;&lt;br&gt;下面详细介绍一下函数CWnd::RepositionBars()和消息WM_SIZEPARENT。 &lt;br&gt;&lt;br&gt;1。函数CWnd::RepositionBars() void RepositionBars( UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver, UINT nFlag = CWnd::reposDefault, LPRECT lpRectParam = NULL, LPCRECT lpRectClient = NULL, BOOL bStretch = TRUE ); &lt;br&gt;&lt;br&gt;参数比较多，但还是比较好懂的。 &lt;br&gt;&lt;br&gt;（1）nIDFirst和nIDLast &lt;br&gt;&lt;br&gt;参与分配父窗口客户区的子窗口的id范围。 &lt;br&gt;&lt;br&gt;每个WM_CHILD风格的窗口都有个id，这是在窗口创建过程中指定的。函数CWnd::Create()的第六个参数就是这个id。api函数CreateWindow和 CreateWindowEx里的那个HMENU类型的参数，当窗口的风格里有WM_CHILD时，它不是指的菜单句柄，而是该窗口的id。 &lt;br&gt;&lt;br&gt;nIDFirst和nIDLast参数指明了：如果一个子窗口的id值大于等于nIDFirst并且小于等于nIDLast，在这个函数中才会给这个子窗口发送 WM_SIZEPARENT消息，这个子窗口才能参与父窗口客户区的分配。 &lt;br&gt;&lt;br&gt;（2）nIDLeftOver &lt;br&gt;&lt;br&gt;前面说过，有一个特定的子窗口，它不响应WM_SIZEPARENT消息。只有当其它的子窗口都分配完了，它才来捡取父窗口客户区里剩下的那块。 nIDLeftOver正是这个子窗口的id。它也必须大于等于nIDFirst并且小于等于nIDLast。 &lt;br&gt;&lt;br&gt;（3）lpRectClient &lt;br&gt;&lt;br&gt;这是一个指向RECT结构数据的指针。这个RECT结构里存放的正是父窗口客户区的初始可用区域。随着在该函数里依次给各个子窗口发送 WM_SIZEPARENT消息，每个响应这个消息的子窗口都会切去自己所占据的部分。最后剩下的部分，就是id为nIDLeftOver的子窗口将要占据的区域了。这个参数可以为NULL，这时初始的可用区域就是整个父窗口客户区。 &lt;br&gt;&lt;br&gt;（4）nFlag和lpRectParam &lt;br&gt;&lt;br&gt;这两个参数放在一起讲比较好。nFlag是该函数的功能标志，它可以有三个值：reposDefault，reposQuery 和reposExtra。 &lt;br&gt;&lt;br&gt;当nFlag等于reposDefault时，RepositionBars函数的功能是这样的：依次给id介于nIDFirst和nIDLast之间并且不等于nIDLeftOver的子窗口发送WM_SIZEPARENT消息，每个响应这个消息的子窗口从lpRectClient所指的结构里切去自己所占据的部分，并且将自己的大小和位置调整到自己所占据的区域的大小，最后RepositionBars函数还将id为nIDLeftOver的子窗口的大小和位置调整到被其他子窗口切剩的可用区域内，使这个子窗口正好完全覆盖最后的可用区域。这种情况下lpRectParam不用，可以为NULL。 &lt;br&gt;&lt;br&gt;当nFlag等于reposQuery 时，RepositionBars函数的功能是这样的：依次给id介于nIDFirst和nIDLast之间并且不等于nIDLeftOver的子窗口发送WM_SIZEPARENT消息，每个响应这个消息的子窗口从lpRectClient所指的结构里切去自己所占据的部分，但是他们并不调整自己的大小和位置，最后RepositionBars函数并不调整将id为nIDLeftOver的子窗口的大小和位置，而是根据bStretch的值来做动作：如果bStretch为TRUE，那么 RepositionBars函数把最后剩下的可用区域拷贝到lpRectParam指向的RECT结构里；如果bStretch为FALSE，那么RepositionBars函数把所有其他子窗口占用掉的可用区域的高和宽(要所有的子窗口都紧排在一起，形成一个大的矩形，这个值才有意义)拷贝到lpRectParam指向的RECT结构的bottom 和right成员里，其top和left成员被置零。使用这个nFlag值来调用RepositionBars的目的不是要重排子窗口，而是要看看，假如重排子窗口的话，这些子窗口将占去多大一块，最后剩下的可用区域在什么位置等等信息。 &lt;br&gt;&lt;br&gt;当nFlag等于reposExtra时，该函数的功能和nFlag等于reposDefault时差不多，有点小小的区别。此时需要用到lpRectParam。前面说过，当 nFlag等于reposDefault时，RepositionBars函数将在最后把id为nIDLeftOver的子窗口的大小和位置调整到被其他子窗口切剩的可用区域内，使这个子窗口正好完全覆盖最后的可用区域。而当nFlag等于reposExtra时，RepositionBars在调整id为nIDLeftOver的子窗口的大小和位置前，还要用 lpRectParam来对最后剩下的可用区域做修正。假设lpRect指向的是最后的可用区域，那么这个修正是这样进行的： &lt;br&gt;&lt;br&gt;&lt;br&gt;lpRect-&amp;gt;top+=lpRectParam-&amp;gt;top; &lt;br&gt;lprect-&amp;gt;left+=lpRectParam-&amp;gt;left; &lt;br&gt;lpRect-&amp;gt;right-=lpRectParam-&amp;gt;right; &lt;br&gt;lpRect-&amp;gt;bottom-=lpRectParam-&amp;gt;bottom; &lt;br&gt;&lt;br&gt;通过这样的修正，可以使最后剩下的可用区域不被id为nIDLeftOver的子窗口占满，而是空出一些地方来留作他用。 &lt;br&gt;（5）bStretch &lt;br&gt;&lt;br&gt;这个参数上面已经提到一点它的作用。它主要是提供给各个响应WM_SIZEPARENT消息的子窗口用的，子窗口例如工具栏，状态条等在决定自己将从父窗口客户区的可用空间里划走多少时，这个参数也是个判断的依据。详细可以参阅工具栏和状态条响应WM_SIZEPARENT的函数OnSizeParent()。 &lt;br&gt;&lt;br&gt;2。消息WM_SIZEPARENT &lt;br&gt;&lt;br&gt;这是个mfc自定义的消息。在msdn里的TN024这篇技术文章里有关于这个消息的说明。 &lt;br&gt;&lt;br&gt;该消息的两个参数中wParam不用，lParam是指向一个AFX_SIZEPARENTPARAMS结构变量的指针，这个结构变量是在RepositionBars函数里定义的： &lt;br&gt;&lt;br&gt;AFX_SIZEPARENTPARAMS layout; &lt;br&gt;&lt;br&gt;AFX_SIZEPARENTPARAMS结构定义如下： &lt;br&gt;&lt;br&gt;struct AFX_SIZEPARENTPARAMS &lt;br&gt;{ &lt;br&gt;HDWP hDWP; &lt;br&gt;RECT rect; &lt;br&gt;SIZE sizeTotal; &lt;br&gt;BOOL bStretch; &lt;br&gt;}; &lt;br&gt;这个结构变量的成员是在RepositionBars函数里填写的：它的bStretch成员就是RepositionBars的参数bStretch，它的sizeTotal成员的两个成员cx和cy都被设置为零，它的rect成员就是从RepositionBars的参数lpRectClient里拷贝过来的，就是父窗口客户区的初始可用区域嘛。每个响应这个消息的子窗口都必须修改rect成员的值，以便切去自己所占据的部分。 &lt;br&gt;成员hDWP是什么？这得知道三个api函数：BebinDeferWindowPos()，DeferWindowPos()和EndDeferWindowPos()。这三个api函数是用来成批设置窗口的位置和尺寸的。BebinDeferWindowPos()先通知windows分配一个将用来存贮窗口的位置和尺寸信息的结构，它不是返回这个结构的指针，而是返回代表这个结构的句柄，句柄的类型是HDWP。然后每个需要重新设置位置和尺寸的窗口都要调用DeferWindowPos()函数(该函数需要那个HDWP 类型的句柄为参数)，以便往那个结构里填写各自的窗口位置和大小信息。最后，在某个合适的时候调用EndDeferWindowPos()，windows就会根据那个结构里的信息把有关的窗口的位置和大小一次性设置好。比起针对每个窗口分别用SetWindowPos()等函数逐个设置来说，这种方法速度快。 &lt;br&gt;&lt;br&gt;好了，在RepositionBars函数里正是调用了BebinDeferWindowPos()，获得一个HDWP类型的句柄，这个句柄就被填写到了上面那个结构变量 layout的成员hDWP里。然后RepositionBars函数给每个符合条件的子窗口发送WM_SIZEPARENT消息。在每个响应WM_SIZEPARENT消息的子窗口里，要调用DeferWindowPos()来设置位置和尺寸信息。当所有的子窗口都响应完毕WM_SIZEPARENT消息后，RepositionBars函数再调用 EndDeferWindowPos()函数，这一来，除了那个id为nIDLeftOver的子窗口外，所有的子窗口都一次性排好了位置了。 &lt;br&gt;&lt;br&gt;至于该结构的sizeTotal成员的意义，它累计每个子窗口所占据掉的可用区域的长宽尺寸和。每个子窗口在响应WM_SIZEPARENT消息时一般都要把自己所占据的区域的高和宽分别累加到sizeTotal结构的cy和cx成员里。这有什么意义呢？当每个子窗口所占据的区域都是挨在一起的时候，这个 sizeTotal结构就有意义了，主框架窗口可以使nFlag等于reposQuery，使bStretch等于FALSE来调用RepositionBars函数，RepositionBars函数会把 sizeTotal结构的两个成员值拷贝到lpRectParam参数里返回给主框架类(前面也提到过)，这样主框架类就知道它的客户区内的子窗口占去了客户区内多大的一块空间。如果你的主框架窗口没有利用这个信息，那么响应WM_SIZEPARENT消息的子窗口就可以不理睬sizeTotal成员。 &lt;br&gt;&lt;br&gt;ID的分配 &lt;br&gt;&lt;br&gt;可以看到，每个子窗口都有个id，同一个父窗口的子窗口的id不能重复。mfc的一些现成的控件子窗口都有预定义的id： &lt;br&gt;&lt;br&gt;id名 id值 意义 &lt;br&gt;&lt;br&gt;AFX_IDW_TOOLBAR 0xE800 // 主窗口的工具栏的id &lt;br&gt;AFX_IDW_STATUS_BAR 0xE801 // 状态栏的id &lt;br&gt;AFX_IDW_PREVIEW_BAR 0xE802 // PrintPreview Dialog Bar &lt;br&gt;AFX_IDW_RESIZE_BAR 0xE803 // OLE in-place resize bar &lt;br&gt;AFX_IDW_REBAR 0xE804 // COMCTL32 &amp;quot;rebar&amp;quot; Bar &lt;br&gt;AFX_IDW_DIALOGBAR 0xE805 // CDialogBar &lt;br&gt;&lt;br&gt;还有象单文档程序的视图窗口，多文档程序的那个MDIClient窗口，分隔条窗口，他们的id值介于下面两个id值之间： &lt;br&gt;AFX_IDW_PANE_FIRST 0xE900 // &lt;br&gt;AFX_IDW_PANE_LAST 0xE9FF &lt;br&gt;&lt;br&gt;你要给你自己的子窗口分配id的话，别和上面的重复了。一般如果用IDE的菜单view/resource symbols项来加入自己的id的话，是不会重复的。有关id，还可以看看msdn里的TN020文章，那是专讲id的。 &lt;br&gt;&lt;br&gt;实例分析 &lt;br&gt;&lt;br&gt;1。CFrameWnd类是如何调用RepositionBars函数的 &lt;br&gt;&lt;br&gt;前面介绍了RepositionBars的各个参数和意义，现在看看CFrameWnd类是如何调用这个函数的，从中可以学习RepositionBars函数的使用方法。 &lt;br&gt;&lt;br&gt;CFrameWnd类及其派生类生成的窗口的客户区内可以有工具栏，状态条和视图窗口等子窗口。当父窗口的尺寸发生变化时，这些子窗口的各自的位置和大小比例关系保持不变，这就需要父窗口一旦在它自己的尺寸发生变化时就调用RepositionBars函数。CFrameWnd类是集中在函数 RecalcLayout里调用RepositionBars函数的。该类保证了在窗口尺寸发生变化时函数RecalcLayout都被调用，从而RepositionBars函数也能被及时调用，确保了各个子窗口都能及时调整自己的位置和大小。 &lt;br&gt;&lt;br&gt;RecalcLayout是个虚函数。该函数的功能就是在主框架的客户区内提供一个初始的可用区域，并把这个区域放在一个CRect类型的变量里。该函数大致是这样的： &lt;br&gt;&lt;br&gt;void CFrameWnd::RecalcLayout(BOOL bNotify) &lt;br&gt;{ &lt;br&gt;if (m_bInRecalcLayout) &lt;br&gt;return;//这大概是在防止该函数重入 &lt;br&gt;m_bInRecalcLayout = TRUE; &lt;br&gt;.... &lt;br&gt;.... &lt;br&gt;.... &lt;br&gt;.... &lt;br&gt;if (GetStyle() &amp;amp; FWS_SNAPTOBARS) &lt;br&gt;{ &lt;br&gt;CRect rect(0, 0, 32767, 32767); &lt;br&gt;RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &lt;br&gt;&amp;amp;rect, &amp;amp;rect, FALSE); &lt;br&gt;RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &lt;br&gt;&amp;amp;m_rectBorder, &amp;amp;rect, TRUE); &lt;br&gt;CalcWindowRect(&amp;amp;rect); &lt;br&gt;SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), &lt;br&gt;SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER); &lt;br&gt;} &lt;br&gt;else &lt;br&gt;RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &amp;amp;m_rectBorder); &lt;br&gt;m_bInRecalcLayout = FALSE; &lt;br&gt;} 可以看出，mfc认为这个函数是不能重入的。在编制自己的RecalcLayout()函数时也得用同样的方法来防止重入。 &lt;br&gt;后面的if语句检查框架窗口是否具有风格FWS_SNAPTOBARS，这个风格用在什么时候呢？我是这样认为的：通常都是在主框架窗口的尺寸改变 &lt;br&gt;时，子窗口在响应WM_SIZEPARENT消息时调整自己的尺寸以便跟上框架窗口的尺寸变化。有这样的情况：父窗口的客户区内的子窗口的数目是动态变 &lt;br&gt;化的，而且这些子窗口互相不能重叠，他们的尺寸由于某种原因不好改变。那么当子窗口的数目发生增减时，如不调整父窗口自己的尺寸，就会导 &lt;br&gt;致客户区留下空白或新增加的子窗口没有多余空间安排。FWS_SNAPTOBARS风格就是用在这种情况下，使父窗口能调整自己的大小以便容纳子窗口。 &lt;br&gt;看这个分支里的语句，似乎是这样的。 &lt;br&gt;一般都不会有FWS_SNAPTOBARS风格的，所以一般是执行else分支。在这个分支里简单地调用RepositionBars去重排所有的子窗口，它的参数 &lt;br&gt;lpRectClient 使用默认的NULL值，意思就是初始可用区域是父窗口的整个客户区。 &lt;br&gt;可以在自己的派生类里编写自己的RecalcLayout函数，以便用自己的方法调用RepositionBars函数。要注意的是在CFrameWnd类的窗口刚被创建 &lt;br&gt;时RecalcLayout函数也被调用，此时可能某些用户自己加的子窗口还未被创建出来，所以在这个函数内如果要引用某个用户自己加的子窗口的句柄 &lt;br&gt;的话必须先用::IsWindow()函数判断一下该窗口句柄是否可用。否则的话就会出现非法操作了。 &lt;br&gt;&lt;br&gt;&lt;br&gt;实战演练 &lt;br&gt;由于精力有限，只提供一个实战例子：将视图，工具栏和状态栏赶到右边 &lt;br&gt;我们要生成这样的界面：视图窗口，工具栏和状态条统统在右边，左边是个自己加的窗口。 &lt;br&gt;第一步：启动AppWizard生成一个单文档程序，全部使用默认设置。 &lt;br&gt;第二步：在CMainFrame类里增加一个成员 CWnd m_mywnd。 &lt;br&gt;第三步：在CMainFrame::OnCreate()函数里增加这几行： &lt;br&gt;m_mywnd.CreateEx &lt;br&gt;( &lt;br&gt;WS_EX_CLIENTEDGE, &lt;br&gt;AfxRegisterWndClass &lt;br&gt;( &lt;br&gt;CS_HREDRAW|CS_VREDRAW, &lt;br&gt;::LoadCursor(NULL,IDC_ARROW), &lt;br&gt;::CreateSolidBrush(RGB(190,190,190)) &lt;br&gt;), &lt;br&gt;&amp;quot;&amp;quot;, &lt;br&gt;WS_VISIBLE|WS_CHILD, &lt;br&gt;CRect(0,0,0,0), &lt;br&gt;this, &lt;br&gt;IDC_MYPANE //用IDE的菜单view/resource symbols项加入的id。 &lt;br&gt;); &lt;br&gt;&lt;br&gt;第四步：启动ClassView，在CMainFrame里加上虚函数RecalcLayout()，函数体这样写： &lt;br&gt;void CMainFrame::RecalcLayout(BOOL bNotify) &lt;br&gt;{ &lt;br&gt;if (m_bInRecalcLayout) &lt;br&gt;return; &lt;br&gt;m_bInRecalcLayout = TRUE; &lt;br&gt;&lt;br&gt;//rect1是新加的窗口将占据的区域 &lt;br&gt;//rect2就是提供给工具栏，状态条和视图窗口的初始可用区域。 &lt;br&gt;CRect rect1,rect2; &lt;br&gt;GetClientRect(&amp;amp;rect1); &lt;br&gt;rect1.right=rect1.right/3; &lt;br&gt;GetClientRect(&amp;amp;rect2); &lt;br&gt;rect2.left=rect2.right/3; &lt;br&gt;&lt;br&gt;if(::IsWindow(m_mywnd.m_hWnd)) //这句是不能少的 &lt;br&gt;m_mywnd.MoveWindow(&amp;amp;rect1); &lt;br&gt;RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, CRect(0,0,0,0),&amp;amp;rect2); &lt;br&gt;m_bInRecalcLayout = FALSE; &lt;br&gt;} &lt;br&gt;&lt;br&gt;第五步：用IDE的菜单view/resource symbols项加入一个id：IDC_MYPANE。 &lt;br&gt;第六步：编译并运行程序。 &lt;br&gt;&lt;br&gt;好了，在主框架窗口的左边多了一个灰色的窗口，它占主窗口客户区的三分之一。工具栏，状态条和视图都被赶到右边三分之二的地方去了。 &lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=449534861986366027&amp;page=RSS%3a+MFC%e7%aa%97%e5%8f%a3%e4%bd%8d%e7%bd%ae%e7%ae%a1%e7%90%86%e8%af%a6%e7%bb%86%e5%88%86%e6%9e%90&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=wdllstudio.spaces.live.com&amp;amp;GT1=wdllstudio"&gt;</description><comments>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!163.entry#comment</comments><guid isPermaLink="true">http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!163.entry</guid><pubDate>Mon, 02 Jan 2006 04:44:51 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://wdllstudio.spaces.live.com/blog/cns!63D119342DA024B!163/comments/feed.rss</wfw:commentRss><wfw:comment>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!163.entry#comment</wfw:comment><dcterms:modified>2006-01-02T04:44:51Z</dcterms:modified></item><item><title>UTF-8的编码方式</title><link>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!127.entry</link><description>&lt;div&gt;&lt;strong&gt;UTF编码&lt;/strong&gt; 
&lt;p&gt;
&lt;p&gt;&lt;font size=2&gt;UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下：&lt;/font&gt;
&lt;table width="75%" border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;font size=2&gt;UCS-2编码(16进制)&lt;/font&gt;
&lt;td&gt;&lt;font size=2&gt;UTF-8 字节流(二进制)&lt;/font&gt;
&lt;tr&gt;
&lt;td&gt;&lt;font size=2&gt;0000 - 007F&lt;/font&gt;
&lt;td&gt;&lt;font size=2&gt;0xxxxxxx&lt;/font&gt;
&lt;tr&gt;
&lt;td&gt;&lt;font size=2&gt;0080 - 07FF&lt;/font&gt;
&lt;td&gt;&lt;font size=2&gt;110xxxxx 10xxxxxx&lt;/font&gt;
&lt;tr&gt;
&lt;td&gt;&lt;font size=2&gt;0800 - FFFF&lt;/font&gt;
&lt;td&gt;&lt;font size=2&gt;1110xxxx 10xxxxxx 10xxxxxx&lt;/font&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;font size=2&gt;例如“汉”字的Unicode编码是6C49。6C49在0800-FFFF之间，所以肯定要用3字节模板了：&lt;font color="#0000ff"&gt;1110&lt;/font&gt;xxxx &lt;font color="#0000ff"&gt;10&lt;/font&gt;xxxxxx &lt;font color="#0000ff"&gt;10&lt;/font&gt;xxxxxx。将6C49写成二进制是：0110 110001 001001， 用这个比特流依次代替模板中的x，得到：&lt;font color="#0000ff"&gt;1110&lt;/font&gt;0110 &lt;font color="#0000ff"&gt;10&lt;/font&gt;110001 &lt;font color="#0000ff"&gt;10&lt;/font&gt;001001，即E6 B1 89。&lt;/font&gt;
&lt;p&gt;&lt;font size=2&gt;UTF-16以16位为单元对UCS进行编码。对于小于0x10000的UCS码，UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码，定义了一个算法。不过由于实际使用的UCS2，或者UCS4的BMP必然小于0x10000，所以就目前而言，可以认为UTF-16和UCS-2基本相同。&lt;/font&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=449534861986366027&amp;page=RSS%3a+UTF-8%e7%9a%84%e7%bc%96%e7%a0%81%e6%96%b9%e5%bc%8f&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=wdllstudio.spaces.live.com&amp;amp;GT1=wdllstudio"&gt;</description><comments>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!127.entry#comment</comments><guid isPermaLink="true">http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!127.entry</guid><pubDate>Wed, 21 Dec 2005 09:59:44 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://wdllstudio.spaces.live.com/blog/cns!63D119342DA024B!127/comments/feed.rss</wfw:commentRss><wfw:comment>http://wdllstudio.spaces.live.com/Blog/cns!63D119342DA024B!127.entry#comment</wfw:comment><dcterms:modified>2005-12-23T22:00:10Z</dcterms:modified></item></channel></rss>