﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-挪威的森林-随笔分类-Visual C++</title><link>http://www.blogjava.net/kenneth/category/3118.html</link><description>不需要完美的可怕，太快乐如何招架！！！</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 08:19:40 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 08:19:40 GMT</pubDate><ttl>60</ttl><item><title>windows编程通用的Win32类型和常见的结构</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11833.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11833.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11833.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11833.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11833.html</trackback:ping><description><![CDATA[CALLBACK 在应用程序的回调例程中取代FAR PASCAL<BR>HANDLE 一个32位的无符号整数，用作句柄<BR>HDC 设备描述句柄<BR>HWND 一个32位的无符号整数用作窗口句柄<BR>LONG 一个32位的带符号整数<BR>LPARAM 用于声明lParam的类型<BR>LPCSTR 与LPSTR类似，但用于只读字符串指针<BR>LPSTR 一个32位的指针<BR>LPVIOD 一个普通指针类型等价于（viod *）<BR>LRESULT 子窗口过程的返回值<BR>NULL 一个整型的0值，常常用于激活函数的缺省动作和参数<BR>UINT 一种无符号的整数类型，其大小取决于主机环境；在NT下是32位<BR>WCHAR 一种16位的UNICODE字符，用于表示世界上所有语言的符号。<BR>WINAPI 在API的定义中取代FAR PASCAL<BR>WPARAM 关于wParam的声明<BR><BR><B>Win32应用程序中常见的结构</B><BR><BR>结构 描述<BR>-----------------------------------------------<BR>MSG 定义了输入消息域<BR>PAINTSTRUCT 定义了在窗口内绘图时使用的绘图结构<BR>RECT 定义一个矩形<BR>WNDCLASS 定义一个窗口类<img src ="http://www.blogjava.net/kenneth/aggbug/11833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 13:52 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC实用小知识总结</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11832.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 05:25:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11832.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11832.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11832.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11832.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （1） 如何通过代码获得应用程序主窗口的指针?<BR>　　&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　AfxGetMainWnd() -&gt;ShowWindow(SW_SHOWMAXMIZED)<BR>　　//使程序最大化.</P></TD></TR></TBODY></TABLE>
<P>　　（2） 确定应用程序的路径<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Use GetModuleFileName 获得应用程序的路径，然后去掉可执行文件名。<BR>　　Example:<BR>　　TCHAR<BR>　　exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧，好象是<BR>　　128<BR>　　GetModuleFileName(NULL,exeFullPath,MAX_PATH)</P></TD></TR></TBODY></TABLE></P>
<P>　　（3） 如何在程序中获得其他程序的图标?<BR>　　两种方法:<BR>　　(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,<BR>　　(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.<BR>　　Example(1):<BR>　　在程序窗口左上角显示 NotePad图标.<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　void CSampleView:<BR>　　OnDraw(CDC * pDC)<BR>　　{<BR>　　if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,<BR>　　&amp;stFileInfo,sizeof(stFileInfo),SHGFI_ICON))<BR>　　{<BR>　　pDC -&gt;DrawIcon(10,10,stFileInfo.hIcon)<BR>　　}<BR>　　}<BR>　　Example(2):同样功能,Use ExtractIcon Function<BR>　　void CSampleView:: OnDraw(CDC *pDC)<BR>　　{<BR>　　HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T<BR>　　("NotePad.exe"),0)<BR>　　if (hIcon &amp;&amp;hIcon!=(HICON)-1)<BR>　　pDC-&gt;DrawIcon(10,10,hIcon)<BR>　　}</P></TD></TR></TBODY></TABLE><BR>　　说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔，应该用访问注册表的方法获得其路径，要作成一个比较考究的程序，考虑应该全面点.</P>
<P>　　（4）获得各种目录信息<BR>　　Windows目录: Use "GetWindowsDirectory"<BR>　　Windows下的system目录: Use "GetSystemDirectory"<BR>　　temp目录: Use "GetTempPath"<BR>　　当前目录: Use "GetCurrentDirectory"</P>
<P>　　请注意前两个函数的第一个参数为目录变量名，后一个为缓冲区后两个相反.</P>
<P>　　（5）如何自定义消息<BR>　　(1) 手工定义消息，可以这么写<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　#define WM_MY_MESSAGE(WM_USER+100),</P></TD></TR></TBODY></TABLE><BR>　　MS 推荐的至少是 WM_USER+100</P>
<P>　　(2)写消息处理函数,用<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　WPARAM,LPARAM返回LRESULT.<BR>　　LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)</P>
<P>　　{<BR>　　temp目录: Use "GetTempPath"<BR>　　//加入你的处理函数 irectory"<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（6） 如何改变窗口的图标?<BR>　　向窗口发送 WM_SECTION消息。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Example:<BR>　　HICON hIcon=AfxGetApp() -&gt;LoadIcon(IDI_ICON)<BR>　　ASSERT(hIcon)<BR>　　AfxGetMainWnd() -&gt;SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)</P></TD></TR></TBODY></TABLE></P>
<P>　　（7） 如何改变窗口的缺省风格?<BR>　　重载 CWnd:: PreCreateWindow 并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.<BR></P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Example: Delete "Max" Button and Set Original<BR>　　Window's Position and Size</P>
<P>　　BOOL CMainFrame:: PreCreateWindow<BR>　　(CREATESTRUCT &amp;cs)<BR>　　{<BR>　　cs.style &amp;=~WS_MAXINIZEMOX</P>
<P>　　cs.x=cs.y=0<BR>　　cs.cx=GetSystemMetrics(SM_CXSCREEN/2)<BR>　　cs.cy=GetSystemMetrics(SM_CYSCREEN/2)</P>
<P>　　return CMDIFramewnd ::PreCreateWindow(cs)<BR>　　}</P></TD></TR></TBODY></TABLE></P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （8） 如何将窗口居中显示?<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Call Function CWnd::<BR>　　Center Windows</P>
<P>　　Example(1):<BR>　　Center Window( ) //Relative to it's parent<BR>　　// Relative<BR>　　to Screen<BR>　　Example(2):<BR>　　Center Window(CWnd:: GetDesktopWindow( ))<BR>　　//Relative to<BR>　　Application's MainWindow<BR>　　AfxGetMainWnd( ) -&gt;<BR>　　Center Window( )</P></TD></TR></TBODY></TABLE>
<P>　　（9） 如何让窗口和 MDI窗口一启动就最大化和最小化?<BR>　　先说窗口。<BR>　　在 InitStance 函数中设定 m_nCmdShow的取值.<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　m_nCmdShow=SW_SHOWMAXMIZED //最大化<BR>　　m_nCmdShow=SW_SHOWMINMIZED //最小化<BR>　　m_nCmdShow=SW_SHOWNORMAL //正常方式</P></TD></TR></TBODY></TABLE></P>
<P>　　MDI窗口:<BR>　　如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数，设置WS_MAXMIZE or WS_MINMIZE</P>
<P>　　如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。</P>
<P>　　（10） 如何限制窗口的大小?<BR>　　也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:</P>
<P>　　（11） 如何使窗口不可见？<BR>　　很简单,用SW_HIDE 隐藏窗口，可以结合 FindWindow,ShowWindow控制.</P>
<P>　　（12） 如何创建一个字回绕的CEditView<BR>　　重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构，关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位， 由于CEditView : : PreCreateWindow显示设置cs. style，调用基类函数后要修改cs . style。</P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&amp;cs)<BR>　　{<BR>　　//First call basse class function .<BR>　　BOOL bResutl =CEditView : : PreCreateWindow (cs)</P>
<P>　　// Now specify the new window style .<BR>　　cs.style &amp;= ~ (ES_AUTOHSCROLL ｜WS_HSCROLL)<BR>　　return bResult<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（13） 如何使程序保持极小状态?<BR>　　这么办: 在恢复程序窗体大小时，Windows会发送WM_QUERY-OPEN消息，用 ClassWizard设置成员函数<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　OnQueryOpen() ,add following code:</P>
<P>　　Bool CMainFrame:: OnQueryOpen( )<BR>　　{<BR>　　Return false<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（14） 移动窗口<BR>　　调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关（顶层窗口与屏幕有关）。调用CWnd : : MoveWindow时必须要指定窗口的大小。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　//Move window to positoin 100 , 100 of its parent window .<BR>　　SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE ｜SWP_NOAORDER)</P></TD></TR></TBODY></TABLE></P>
<P>　　（15） 通用控件的显示窗口<BR>　　MFC提供了几个CView派生的视窗类， 封装了通用控件的功能，但仍然使用工作框文档显示窗口体系结构：CEditView封装了编辑控件，CTreeView保持了树列表控件，CListView封装了列表显示窗口控件，CRichEditView可以处理多种编辑控件。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （16） 重置窗口的大小<BR>　　调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志， 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　// Get the size of the window .<BR>　　Crect reWindow<BR>　　GetWindowRect (reWindow )</P>
<P>　　//Make the window twice as wide and twice as tall .<BR>　　SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,</P>
<P>　　reWindow . Height () * 2,<BR>　　SWP_NOMOVE ｜SWP_NOZORDER )</P></TD></TR></TBODY></TABLE></P>
<P>　　（17） 如何单击除了窗口标题栏以外的区域使窗口移动<BR>　　当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息，可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序，可以使用ClassWizard处理该信息并调用基类函数， 如果函数返回HTCLIENT 则表明鼠标在客房区域，返回HTCAPTION表明鼠标在Windows的标题栏中。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　UINT CSampleDialog : : OnNcHitTest (Cpoint point )<BR>　　{<BR>　　UINT nHitTest =Cdialog: : OnNcHitTest (point )<BR>　　return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　上述技术有两点不利之处，<BR>　　其一是在窗口的客户区域双击时，窗口将极大；<BR>　　其二， 它不适合包含几个视窗的主框窗口。<BR>　　还有一种方法，当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上，使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point<BR>　　)<BR>　　{<BR>　　CView : : OnLButtonDow (nFlags , pont )</P>
<P>　　//Fool frame window into thinking somene clicked<BR>　　on<BR>　　its caption bar .<BR>　　GetParentFrame ( ) —&gt; PostMessage (<BR>　　WM_NCLBUTTONDOWN ,<BR>　　HTCAPTION , MAKELPARAM (poitn .x , point .y) )</P>
<P>　　}</P></TD></TR></TBODY></TABLE><BR>　　该技术也适用于对话框和基于对的应用程序，只是不必调用<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　CWnd: :GetParentFrame 。<BR>　　void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )<BR>　　{<BR>　　Cdialog : : OnLButtonDow (nFlags, goint )<BR>　　//Fool dialog into thinking simeone clicked on its<BR>　　caption bar .<BR>　　PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x<BR>　　, point. y<BR>　　) )<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（18） 如何改变视窗的背景颜色<BR>　　Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景，可以使用ClassWizard重载该消息的缺省处理程序来擦除背景（实际是画），并返回TRUE以防止Windows擦除窗口。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　//Paint area that needs to be erased.<BR>　　BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)<BR>　　{<BR>　　// Create a pruple brush.<BR>　　CBrush Brush (RGB (128 , 0 , 128) )</P>
<P>　　// Select the brush into the device context .<BR>　　CBrush* pOldBrush = pDC—&gt;SelcetObject (&amp;brush)</P>
<P>　　// Get the area that needs to be erased .<BR>　　CRect reClip<BR>　　pDC—&gt;GetCilpBox (&amp;rcClip)<BR>　　//Paint the area.<BR>　　pDC—&gt; PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )</P>
<P>　　//Unselect brush out of device context .<BR>　　pDC—&gt;SelectObject (pOldBrush )</P>
<P>　　// Return nonzero to half fruther processing .<BR>　　return TRUE<BR>　　}</P></TD></TR></TBODY></TABLE></P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （19） 如何改变窗口标题<BR>　　调用CWnd : : SetWindowText可以改变任何窗口（包括控件）的标题。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　//Set title for application's main frame window .<BR>　　AfxGetMainWnd ( ) —&gt; SetWindowText (_T("Application title") )</P>
<P>　　//Set title for View's MDI child frame window .<BR>　　GetParentFrame ( ) —&gt; SetWindowText ("_T ("MDI Child Frame new title")<BR>　　)</P>
<P>　　//Set title for dialog's push button control.<BR>　　GetDigitem (IDC_BUTTON) —&gt; SetWindowText (_T ("Button new title ") )</P></TD></TR></TBODY></TABLE><BR>　　如果需要经常修改窗口的标题（注：控件也是窗口），应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明，在WINUTIL.CPP中实现，在联机帮助中找不到它，它在AFXPRIV.H中半文档化， 在以后发行的MFC中将文档化。<BR>　　AfxSetWindowText的实现如下：<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )<BR>　　{<BR>　　itn nNewLen= Istrlen (Ipaznew)<BR>　　TCHAR szOld [256]<BR>　　//fast check to see if text really changes (reduces<BR>　　flash in the<BR>　　controls )<BR>　　if (nNewLen &gt;_contof (szOld)<BR>　　｜｜ : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen<BR>　　｜｜ Istrcmp (szOld , IpszNew)! = 0<BR>　　{<BR>　　//change it<BR>　　: : SetWindowText(hWndCtrl , IpszNew )<BR>　　}<BR>　　}</P></TD></TR></TBODY></TABLE>
<P></P>
<P>　　（20） 如何防止主框窗口在其说明中显示活动的文档名<BR>　　创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位，如果不希望在说明中自动添加文档名， 必须禁止该风格位， 可以使用ClassWizard重置<BR>　　CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&amp;cs)<BR>　　{<BR>　　//Turn off FWS_ADDTOTITLE in main frame .<BR>　　cs.styel &amp; = ~FWS_ADDTOTITLE 　<BR>　　return CMDIFrameWnd : : PreCreateWindow (cs )<BR>　　}</P></TD></TR></TBODY></TABLE><BR>　　关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口，可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。</P>
<P>　　（21） 如何获取有关窗口正在处理的当前消息的信息<BR>　　调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如，可以使用ClassWizard将几个菜单项处理程序映射到一个函数中，然后调用GetCurrentMessage来确定所选中的菜单项。<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　viod CMainFrame : : OnCommmonMenuHandler ( )<BR>　　{<BR>　　//Display selected menu item in debug window .<BR>　　TRACE ("Menu item %u was selected . \n" ,</P></TD></TR></TBODY></TABLE></P>
<P>　　（22） 如何在代码中获取工具条和状态条的指针<BR>　　缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　//Get pointer to status bar .<BR>　　CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR)</P>
<P>　　//Get pointer to toolbar .<BR>　　CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_TOOLBAR)</P></TD></TR></TBODY></TABLE></P>
<P>　　（23） 如何使能和禁止工具条的工具提示<BR>　　如果设置了CBRS_TOOLTIPS风格位，工具条将显示工具提示，要使能或者禁止工具提示，需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数：<BR><BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )<BR>　　{<BR>　　ASSERT_VALID (m_wndToolBar)</P>
<P>　　DWORD dwStyle = m _wndToolBar.GetBarStyle ( )</P>
<P>　　if (bDisplayTips) dwStyle ｜=CBRS_TOOLTIPS</P>
<P>　　else<BR>　　dwStyle &amp; = ~CBRS_TOOLTIPS</P>
<P>　　m_wndToolBar.SetBarStyle (dwStyle )<BR>　　}</P></TD></TR></TBODY></TABLE></P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （24） 如何创建一个不规则形状的窗口<BR>　　可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域，实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。<BR>　　给对话类增加一个CRgn数据成员，以后要使用该数据成员建立窗口区域。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Class CRoundDlg : public CDialog<BR>　　{<BR>　　…<BR>　　private :<BR>　　Crgn m_rgn : // window region<BR>　　…<BR>　　}<BR>　　修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口：<BR>　　BOOL CRoundDlg : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( )</P>
<P>　　//Get size of dialog .<BR>　　CRect rcDialog<BR>　　GetClientRect (rcDialog )</P>
<P>　　// Create region and assign to window .<BR>　　m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )<BR>　　SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )</P>
<P>　　return TRUE<BR>　　}</P></TD></TR></TBODY></TABLE>
<P>　　通过建立区域和调用SetWindowRgn，已经建立一个不规则形状的窗口，下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　voik CRoundDlg : : OnPaint ( )<BR>　　{<BR>　　CPaintDC de (this) // device context for painting<BR>　　.<BR>　　//draw ellipse with out any border<BR>　　dc. SelecStockObject (NULL_PEN)<BR>　　//get the RGB colour components of the sphere color<BR>　　COLORREF color= RGB( 0 , 0 , 255)<BR>　　BYTE byRed =GetRValue (color)<BR>　　BYTE byGreen = GetGValue (color)<BR>　　BYTE byBlue = GetBValue (color)</P>
<P>　　// get the size of the view window<BR>　　Crect rect<BR>　　GetClientRect (rect)</P>
<P>　　// get minimun number of units<BR>　　int nUnits =min (rect.right , rect.bottom )</P>
<P>　　//calculate he horiaontal and vertical step size<BR>　　float fltStepHorz = (float) rect.right /nUnits<BR>　　float fltStepVert = (float) rect.bottom /nUnits</P>
<P><BR>　　int nEllipse = nUnits/3 // calculate how many to<BR>　　draw<BR>　　int nIndex<BR>　　// current ellipse that is being draw</P>
<P>　　CBrush brush<BR>　　// bursh used for ellipse fill color<BR>　　CBrush *pBrushOld // previous<BR>　　brush that was selected into dc<BR>　　//draw ellipse , gradually moving towards upper-right<BR>　　corner<BR>　　for (nIndex = 0 nIndes &lt; + nEllipse nIndes++)<BR>　　{<BR>　　//creat solid brush<BR>　　brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).<BR>　　( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)<BR>　　/nEllipse ) ) )</P>
<P>　　//select brush into dc<BR>　　pBrushOld= dc .SelectObject (&amp;brhsh)</P>
<P>　　//draw ellipse<BR>　　dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,<BR>　　rect. right -( (int) fltStepHorz * nIndex )+ 1,<BR>　　rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)</P>
<P>　　//delete the brush<BR>　　brush.DelecteObject ( )<BR>　　}<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　最后，处理WM_NCHITTEST消息，使当击打窗口的任何位置时能移动窗口。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　UINT CRoundDlg : : OnNchitTest (Cpoint point )<BR>　　{<BR>　　//Let user move window by clickign anywhere on thewindow .<BR>　　UINT nHitTest = CDialog : : OnNcHitTest (point)<BR>　　rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest</P>
<P>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（25） 如何获取应用程序的 实例句柄?<BR>　　应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄.<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>
<P>　　Example: HANDLE hInstance=AfxGetInstanceHandle()</P></TD></TR></TBODY></TABLE></P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（26） 如何编程结束应用程序?<BR>　　这是个很简单又是编程中经常要遇到的问题.<BR>　　向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.<BR>　　<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><FONT color=#002c99><BR></FONT></TD>
<TD>　　Example: AfxGetMainWindow()-&gt;SendMessage(WM_CLOSE)</TD></TR></TBODY></TABLE>
<P>　　还可以创建一个自定义的函数 Terminate Window<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void Terminate Window(LPCSTR pCaption)<BR>　　{<BR>　　CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption) 
<P>　　if (pWnd)</P>
<P>　　pWnd -&gt;SendMessage(WM_CLOSE)<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　说明: FindWindow函数不是提倡的做法，因为它无法处理标题栏自动改变，比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了，可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。</P>
<P>　　（27） 如何创建和使用无模式对话框<BR>　　MFC将模式和无模式对话封装在同一个类中，但是使用无模式对话需要几个对话需要几个额处的步骤。首先，使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的：模式对话通过调用CDialog : : EndDialog 来中止，无模式对话则是调用CWnd: : DestroyWindow来中止的，函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void CSampleDialog : : OnOK ( )<BR>　　{<BR>　　// Retrieve and validate dialog data .<BR>　　if (! UpdateData (TRUE) )<BR>　　{<BR>　　// the UpdateData rountine<BR>　　will set focus to correct item TRACEO (" UpdateData failed during dialog termination .\n")<BR>　　return<BR>　　} 
<P>　　//Call DestroyWindow instead of EndDialog .<BR>　　DestroyWindow ( )<BR>　　}</P>
<P>　　void CSampleDialog : : OnCancel ( )<BR>　　{<BR>　　//Call DestroyWindow instead of EndDialog .<BR>　　DestroyWindow ( )<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　其次，需要正确删除表示对话的C++对象。对于模式对来说，这很容易，需要创建函数返回后即可删除C++对象；无模式对话不是同步的，创建函数调用后立即返回，因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy，可以重置该函数并执行清除操作，诸如删除this指针。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void CSampleDialog : : PostNcDestroy ( )<BR>　　{<BR>　　// Declete the C++ object that represents this dialog.<BR>　　delete this</TD></TR></TBODY></TABLE></P>
<P>　　最后，要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放，要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的： 象；无模式对话不是同步的，创建函数调用后立即返回，<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void CMainFrame : : OnSampleDialog ( )<BR>　　{<BR>　　//Allocate a modeless dialog object .<BR>　　CSampleDilog * pDialog =new CSampleDialog<BR>　　ASSERT_VALID (pDialog) Destroy ( ) 
<P>　　//Create the modeless dialog . represents this dialog.<BR>　　BOOL bResult = pDialog —&gt; Creste (IDD_IDALOG)<BR>　　ASSERT (bResult )<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（28） 如何防止主框窗口在其说明中显示活动的文档名<BR>　　创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位，如果不希望在说明中自动添加文档名， 必须禁止该风格位， 可以使用ClassWizard重置<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。<BR>　　BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&amp;cs)<BR>　　{<BR>　　//Turn off FWS_ADDTOTITLE in main frame .<BR>　　cs.styel &amp; = ~FWS_ADDTOTITLE 　<BR>　　return CMDIFrameWnd : : PreCreateWindow (cs )<BR>　　}</TD></TR></TBODY></TABLE><BR>　　关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口，可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （29） 如何在代码中获取工具条和状态条的指针<BR>　　缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Get pointer to status bar .<BR>　　CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR) 
<P>　　//Get pointer to toolbar .<BR>　　CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_TOOLBAR)</P></TD></TR></TBODY></TABLE></P>
<P>　　（30） 怎样加载其他的应用程序?<BR>　　三个SDK函数 winexec, shellexecute,createprocess可以使用。<BR>　　WinExec最简单，两个参数，前一个指定路径，后一个指定显示方式.后一个参数值得说一下，比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序，就是Neterm,calc等等，就不会出现正常的窗体，但是已经被加到任务列表里了。</P>
<P>　　ShellExecute较 WinExex灵活一点，可以指定工作目录,下面的Example就是直接打开 c:\temp\1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口，来显示Readme or Faq,我猜就是这么作的啦.</P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:\\temp"),SW_SHOWMAXMIZED)</TD></TR></TBODY></TABLE></P>
<P>　　CreateProcess最复杂，一共有十个参数，不过大部分都可以用NULL代替，它可以指定进程的安全属性，继承信息，类的优先级等等.来看个很简单的Example:<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　STARTUPINFO stinfo<BR>　　//启动窗口的信息<BR>　　PROCESSINFO procinfo //进程的信息 
<P>　　CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,<BR>　　NORMAL_PRIORITY_</P>
<P>　　CLASS,NULL,NULL, &amp;stinfo,&amp;procinfo)</P></TD></TR></TBODY></TABLE></P>
<P>　　（31） 如何在代码中获取工具条和状态条的指针<BR>　　缺省时， 工作框创建状态条和工具条时将它们作为主框窗口的子窗口，状态条有一个AFX_IDW_STATUS_BAR标识符，工具条有一个AFX_IDW_TOOLBAR标识符，下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Get pointer to status bar .<BR>　　CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_STUTUS_BAR)</TD></TR></TBODY></TABLE></P>
<P>　　（32） 如何使能和禁止工具条的工具提示<BR>　　如果设置了CBRS_TOOLTIPS风格位，工具条将显示工具提示，要使能或者禁止工具提示，需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )<BR>　　{<BR>　　ASSERT_VALID (m_wndToolBar) 
<P>　　DWORD dwStyle = m _wndToolBar.GetBarStyle ( )</P>
<P>　　if (bDisplayTips) dwStyle ｜=CBRS_TOOLTIPS</P>
<P>　　else<BR>　　dwStyle &amp; = ~CBRS_TOOLTIPS</P>
<P>　　m_wndToolBar.SetBarStyle (dwStyle )<BR>　　}</P>
<P>　　//Get pointer to toolbar .<BR>　　CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )<BR>　　—&gt; GetDescendantWindow(AFX_IDW_TOOLBAR)</P></TD></TR></TBODY></TABLE></P>
<P>　　（33） 如何设置工具条标题<BR>　　工具条是一个窗口，所以可以在调用CWnd : : SetWindowText来设置标题，例子如下：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )<BR>　　{<BR>　　…<BR>　　// Set the caption of the toolbar .<BR>　　m_wndToolBar.SetWindowText (_T "Standdard")</TD></TR></TBODY></TABLE></P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （34） 如何使窗口始终在最前方?<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BringWindowToTop(Handle)</TD></TR></TBODY></TABLE><BR>　　SetWindowPos函数，指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格 
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　Example:<BR>　　void ToggleTopMost(<BR>　　CWnd *pWnd)<BR>　　{<BR>　　ASSERT_VALID(pWnd) 
<P>　　pWnd -&gt;SetWindowPos(pWnd-&gt; GetStyle( ) &amp;WS_EX_TOPMOST)?</P>
<P>　　&amp;wndNoTopMOST: &amp;wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（35） 如何在对话框中显示一个位图<BR>　　这要归功于Win 32先进的静态控件和Microsoft的资源编辑器，在对话框中显示位图是很容易的， 只需将图形控件拖到对话中并选择适当属性即可，用户也可以显示图标、位图以及增强型元文件。</P>
<P>　　（36） 如何改变对话或窗体视窗的背景颜色<BR>　　调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色，第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BOOL CSampleApp : : InitInstance ( )<BR>　　{<BR>　　… 
<P>　　//use blue dialog with yellow text .<BR>　　SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) )</P>
<P>　　…<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　需要重画对话（或对话的子控件）时，Windows向对话发送消息WM_CTLCOLOR，通常用户可以让Windows选择绘画背景的刷子，也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。</P>
<P>　　首先，给对话基类增加一人成员变量<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　CBursh :class CMyFormView : public CFormView<BR>　　{<BR>　　… 
<P>　　private :<BR>　　CBrush m_ brush // background brush</P>
<P>　　…<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　其次， 在类的构造函数中将刷子初始化为所需要的背景颜色。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　CMyFormView : : CMyFormView ( )<BR>　　{<BR>　　// Initialize background brush .<BR>　　m_brush .CreateSolidBrush (RGB ( 0, 0, 255) )<BR>　　}</TD></TR></TBODY></TABLE></P>
<P>　　最后，使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意：由于当重画对话控件时也要调用该函数，所以要检测nCtlColor参量。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor<BR>　　) 
<P>　　{<BR>　　// Determine if drawing a dialog box . If we are, return +handle to<BR>　　//our own background brush . Otherwise let windows handle it .<BR>　　if (nCtlColor = = CTLCOLOR _ DLG )<BR>　　return (HBRUSH) m_brush.GetSafeHandle ( )<BR>　　return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor<BR>　　)<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（37） 如何获取一个对话控件的指针<BR>　　有两种方法。其一，调用CWnd: : GetDlgItem，获取一个CWnd*指针调用成员函数。下例调用GetDlgItem，将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BOOL CSampleDialog : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( ) 
<P>　　//Get pointer to spin button .<BR>　　CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)<BR>　　ASSERT _ VALID (pSpin)<BR>　　//Set spin button's default position .<BR>　　pSpin —&gt; SetPos (10)</P>
<P>　　return TRUE<BR>　　}</P></TD></TR></TBODY></TABLE></P>其二， 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签，然后选择Add Variable …按钮。如果在对话资源编辑器中，按下Ctrl键并双击控件即可转到Add Member Variable对话。 
<P>　　（38） 如何禁止和使能控件<BR>　　控件也是窗口，所以可以调用CWnd : : EnableWindow使能和禁止控件。<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Disable button controls .<BR>　　m_wndOK.EnableWindow (FALSE )<BR>　　m_wndApply.EnableWindow (FALSE )</TD></TR></TBODY></TABLE></P>
<P>　　（39） 如何改变控件的字体<BR>　　由于控件是也是窗口，用户可以调用CWnd: : SetFont指定新字体。该函数用一个Cfont指针，要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为8点Arial字体：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Declare font object in class declaration (.H file ).<BR>　　private : Cfont m_font<BR>　　// Set font in class implementation (.Cpp file ). Note m_wndButton is a<BR>　　//member variable added by ClassWizard.DDX routines hook the member<BR>　　//variable to a dialog button contrlo.<BR>　　BOOL CSampleDialog : : OnInitDialog ( )<BR>　　{<BR>　　…<BR>　　//Create an 8-point Arial font<BR>　　m_font . CreateFont (MulDiv (8 , -pDC<BR>　　—&gt; GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS , 
<P>　　CLIP_STROKE _PRECIS , DRAFT _QUALITY<BR>　　VARIABLE_PITCH ｜FF_SWISS, _T("Arial") )</P>
<P>　　//Set font for push button .<BR>　　m_wndButton . SetFont (&amp;m _font )</P>
<P>　　…<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（40） 如何在OLE控件中使用OLE_COLOR数据类型<BR>　　诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数返回OLE _COLOR数据类型的颜色，而GDI对象诸如笔和刷子使用的是COLORREF数据类型，调用COleControl : : TranslateColor可以很容易地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子：</P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　void CSampleControl : : OnDraw (CDC* pdc<BR>　　const Crect&amp; rcBounds , const Crect&amp; rcInvalid<BR>　　)<BR>　　{<BR>　　//Create a brush of the cuttent background color.<BR>　　CBrush brushBack (TranslateColor (GetBackColor () ) ) 
<P>　　//Paint the background using the current backgroundcolor .<BR>　　pdc—&gt; FilllRect (rcBounds , &amp;brushBack)</P>
<P>　　//other drawign commands</P>
<P>　　…<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　（41） 在不使用通用文件打开对话的情况下如何显示一个文件列表<BR>　　调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox，Windows 将自动地向列表框或组合框填充可用的驱动器名或者指定目录中的文件，下例将Windows目录中的文件填充在组合框中：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BOOL CSampleDig : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( )<BR>　　TCHAR szPath [MAX_PATH] = {"c:\\windows"}<BR>　　int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE ｜DDL_READONLY｜DDL_HIDDEN｜ DDL_SYSTEM｜DDL_ARCHIVE)<BR>　　return TRUE<BR>　　}</TD></TR></TBODY></TABLE></P>
<P>　　（42） 为什么旋转按钮控件看起来倒转<BR>　　需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围，旋转按钮控件的缺省上限为0，缺省下限为100，这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BOOL CAboutDlg : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( ) 
<P>　　//set the lower and upper limit of the spin button<BR>　　m_wndSpin . SetRange ( 0 ,100 )</P>
<P>　　return TRUE<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　Visual C++ 4.0 Print对话中的Copise旋转按钮控件也有同样的问题：按下Up按钮时拷贝的数目减少，而按下Down 按钮时拷贝的数目增加。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （43） 为什么旋转按钮控件不能自动地更新它下面的编辑控件<BR>　　如果使用旋转按钮的autu buddy特性， 则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab Order菜单项（或者按下Crtl+D）可以设置对话的标签顺序。</P>
<P>　　（44） 如何用位图显示下压按钮<BR>　　Windows 95按钮有几处新的创建风格，尤其是BS_BITMAP和BS_ICON，要想具有位图按钮，创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时要指定BS_BITMAP或BS_ICON风格。</P>
<P>　　首先，设置按钮的图标属性。然后，当对话初始化时调用CButton: : SetIcon。注意：下例用图标代替位图，使用位图时要小心，因为不知道背景所有的颜色——并非每个人都使用浅灰色。</P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　BOOL CSampleDlg : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( ) 
<P>　　//set the images for the push buttons .<BR>　　BOOL CSampleDlg : : OnInitDialog ( )<BR>　　{<BR>　　CDialog : : OnInitDialog ( )</P>
<P>　　//set the images for the push buttons .<BR>　　m_wndButton1.SetIcon (AfxGetApp ( ) —&gt; LoadIcon (IDI _ IPTION1))<BR>　　m_wndButton2.SetIcon (AfxGetApp ( ) —&gt; LoadIcon (IDI _ IPTION2))<BR>　　m_wndButton3.SetIcon (AfxGetApp ( ) —&gt; LoadIcon (IDI _ IPTION3))</P>
<P>　　return TRUE<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P><BR>　　（45） 如何一个创建三态下压按钮<BR>　　可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易，只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。</P>
<P>　　（46） 如何动态创建控件<BR>　　分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事：忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//In class declaration (.H file ).<BR>　　private : CButton* m _pButton 
<P>　　//In class implementation (.cpp file ) .<BR>　　m_pButton =new CButton<BR>　　ASSERT_VALID (m_pButton)<BR>　　m_pButton —&gt;Create (_T ("Button Title ") , WS_CHILD ｜WS_VISIBLE ｜BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )</P></TD></TR></TBODY></TABLE></P>
<P>　　（47） 如何限制编辑框中的准许字符<BR>　　如果用户在编辑控件中只允许接收数字，可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志，该标志限制 编辑控件只按收数字字符。如果用户需要复杂的编辑控件，可以使用Microsoft 的屏蔽编辑控件，它是一个很有用的OLE定制控件。<BR>如果希望不使用OLE 定制控件自己处理字符，可以派生一个CEdit类并处理WM_CHAR消息，然后从编辑控件中过滤出特定的字符。首先，使用ClassWizard建立一个 CEdit的派生类，其次，在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem . </P>
<P></P>
<P>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//In your dialog class declaration (.H file )<BR>　　private : CMyEdit m_wndEdit // Instance of your new edit control . 
<P>　　//In you dialog class implementation (.CPP file )<BR>　　BOOL CSampleDialog : : OnInitDialog ( )<BR>　　{<BR>　　…</P>
<P>　　//Subclass the edit lontrod .<BR>　　m_wndEdit .SubclassDlgItem (IDC_EDIT,this)</P>
<P>　　…<BR>　　}</P></TD></TR></TBODY></TABLE></P>
<P>　　使用ClassWizard处理WM_CHAR消息，计算nChar参量并决定所执行的操作，用户可以确定是否修改、传送字符。下例说明了如何显示字母字符，如果字符是字母字符，则调用CWnd OnChar，否则不调用OnChar.<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Only display alphabetic dharacters .<BR>　　void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )<BR>　　{<BR>　　//Determine if nChar is an alphabetic character.<BR>　　if (: : IsCharAlpha ( ( TCHAR) nChar ) )<BR>　　CEdit : : OnChar (nChar, nRepCnt , nFlags )<BR>　　}</TD></TR></TBODY></TABLE></P>
<P>　　如果要修改字符，则不能仅仅简单地用修改过的nChar调用CEdit: : OnChar，然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值，这样是不行的。要修改一个字符，需要首先修改nChar，然后用修改过的nChar调用CWnd: : DefWindowProc。下例说明了如何将字符转变为大写：<BR>
<TABLE borderColor=#55aaff cellSpacing=0 cellPadding=0 rules=none width=500 align=center bgColor=#ddedfb border=1>
<TBODY>
<TR>
<TD width=10><BR></TD>
<TD>　　//Make all characters uppercase<BR>　　void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )<BR>　　{<BR>　　//Make sure character is uppercase .<BR>　　if (: : IsCharAlpha ( .( TCHAR) nChar)<BR>　　nChar=: : CharUpper(nChar ) 
<P>　　//Bypass default OnChar processing and directly call<BR>　　//default window proc.<BR>　　DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))<BR>　　}</P></TD></TR></TBODY></TABLE></P><img src ="http://www.blogjava.net/kenneth/aggbug/11832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 13:25 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC中的常用的20个方法</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11831.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 05:21:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11831.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11831.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11831.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11831.html</trackback:ping><description><![CDATA[<H4 clear=all>一、打开CD-ROM</H4>
<P class=code>mciSendString("Set cdAudio door open wait",NULL,0,NULL);</P>
<H4>二、关闭CD_ROM</H4>
<P class=code>mciSendString("Set cdAudio door closed wait",NULL,0,NULL);</P>
<H4>三、关闭计算机</H4>
<P class=code>OSVERSIONINFO OsVersionInfo; //包含操作系统版本信息的数据结构<BR>OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);<BR>GetVersionEx(&amp;OsVersionInfo); //获取操作系统版本信息<BR>if(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)<BR>{<BR>&nbsp;&nbsp;&nbsp; //Windows98,饔肊xitWindowsEx()函数重新启动计算机<BR>&nbsp;&nbsp;&nbsp; DWORD dwReserved;<BR>&nbsp;&nbsp;&nbsp; ExitWindowsEx(EWX_REBOOT,dwReserved); //可以改变第一个参数，实现注销用户、<BR>&nbsp;&nbsp;&nbsp; //关机、关闭电源等操作<BR>&nbsp;&nbsp;&nbsp; // 退出前的一些处理程序<BR>}</P>
<H4>四、重启计算机</H4>
<P class=code>typedef int (CALLBACK *SHUTDOWNDLG)(int); //显示关机对话框函数的指针<BR>HINSTANCE hInst = LoadLibrary("shell32.dll"); //装入shell32.dll<BR>SHUTDOWNDLG ShutDownDialog; //指向shell32.dll库中显示关机对话框函数的指针<BR>if(hInst != NULL)<BR>{<BR>&nbsp;&nbsp;&nbsp; //获得函数的地址并调用之<BR>&nbsp;&nbsp;&nbsp; ShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; (*ShutDownDialog)(0);<BR>}</P>
<H4>五、枚举所有字体</H4>
<P class=code>LOGFONT lf;<BR>lf.lfCharSet = DEFAULT_CHARSET; // Initialize the LOGFONT structure<BR>strcpy(lf.lfFaceName,"");<BR>CClientDC dc (this);<BR>// Enumerate the font families<BR>::EnumFontFamiliesEx((HDC) dc,&amp;lf, (FONTENUMPROC) EnumFontFamProc,(LPARAM) this,0);<BR>//枚举函数<BR>int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPNEWTEXTMETRIC lpntm,DWORD nFontType,long lparam)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>{<BR>&nbsp;&nbsp;&nbsp; // Create a pointer to the dialog window<BR>&nbsp;&nbsp;&nbsp; CDay7Dlg* pWnd = (CDay7Dlg*) lparam;<BR>&nbsp;&nbsp;&nbsp; // add the font name to the list box<BR>&nbsp;&nbsp;&nbsp; pWnd -&gt;m_ctlFontList.AddString(lpelf -&gt;elfLogFont.lfFaceName);<BR>&nbsp;&nbsp;&nbsp; // Return 1 to continue font enumeration<BR>&nbsp;&nbsp;&nbsp; return 1;<BR>}<BR>//其中m_ctlFontList是一个列表控件变量</P>
<H4>六、一次只运行一个程序实例，如果已运行则退出</H4>
<P class=code>if( FindWindow(NULL,"程序标题")) exit(0);</P>
<H4>七、得到当前鼠标所在位置</H4>
<P class=code>CPoint pt;<BR>GetCursorPos(&amp;pt); //得到位置</P>
<H4>八、上下文菜单事件触发事件</H4>
<P class=code>OnContextMenu事件</P>
<H4>九、显示和隐藏程序菜单</H4>
<P class=code>CWnd *pWnd=AfxGetMainWnd();<BR>if(b_m) //隐藏菜单<BR>{<BR>&nbsp;&nbsp;&nbsp; pWnd-&gt;SetMenu(NULL);<BR>&nbsp;&nbsp;&nbsp; pWnd-&gt;DrawMenuBar();<BR>&nbsp;&nbsp;&nbsp; b_m=false;<BR>}<BR>else<BR>{<BR>&nbsp;&nbsp;&nbsp; CMenu menu;<BR>&nbsp;&nbsp;&nbsp; menu.LoadMenu(IDR_MAINFRAME); ////显示菜单 也可改变菜单项<BR>&nbsp;&nbsp;&nbsp; pWnd-&gt;SetMenu(&amp;menu);<BR>&nbsp;&nbsp;&nbsp; pWnd-&gt;DrawMenuBar();<BR>&nbsp;&nbsp;&nbsp; b_m=true;<BR>&nbsp;&nbsp;&nbsp; menu.Detach();<BR>}</P>
<H4>十、获取可执行文件的图标</H4>
<P class=code>HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);<BR>if (hIcon &amp;&amp;hIcon!=(HICON)-1)<BR>{<BR>&nbsp;&nbsp;&nbsp; pDC-&gt;DrawIcon(10,10,hIcon);<BR>&nbsp;&nbsp;&nbsp; <BR>}<BR>DestroyIcon(hIcon);</P>
<H4>十一、窗口自动靠边程序演示</H4>
<P class=code>BOOL AdjustPos(CRect* lpRect)<BR>{//自动靠边<BR>&nbsp;&nbsp;&nbsp; int iSX=GetSystemMetrics(SM_CXFULLSCREEN);<BR>&nbsp;&nbsp;&nbsp; int iSY=GetSystemMetrics(SM_CYFULLSCREEN);<BR>&nbsp;&nbsp;&nbsp; RECT rWorkArea;<BR>&nbsp;&nbsp;&nbsp; BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &amp;rWorkAre<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a, 0);<BR>&nbsp;&nbsp;&nbsp; CRect rcWA;<BR>&nbsp;&nbsp;&nbsp; if(!bResult)<BR>&nbsp;&nbsp;&nbsp; {//如果调用不成功就利用GetSystemMetrics获取屏幕面积<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rcWA=CRect(0,0,iSX,iSY);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rcWA=rWorkArea;<BR>&nbsp;&nbsp;&nbsp; int iX=lpRect-&gt;left;<BR>&nbsp;&nbsp;&nbsp; int iY=lpRect-&gt;top;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; if(iX &lt; rcWA.left + DETASTEP &amp;&amp; iX!=rcWA.left)<BR>&nbsp;&nbsp;&nbsp; {//调整左<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //pWnd-&gt;SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpRect-&gt;OffsetRect(rcWA.left-iX,0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AdjustPos(lpRect);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; if(iY &lt; rcWA.top + DETASTEP &amp;&amp; iY!=rcWA.top)<BR>&nbsp;&nbsp;&nbsp; {//调整上<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //pWnd-&gt;SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpRect-&gt;OffsetRect(0,rcWA.top-iY);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AdjustPos(lpRect);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; if(iX + lpRect-&gt;Width() &gt; rcWA.right - DETASTEP &amp;&amp; iX !=rcWA.right-lpRect-&gt;Width())<BR>&nbsp;&nbsp;&nbsp; {//调整右<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //pWnd-&gt;SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpRect-&gt;OffsetRect(rcWA.right-lpRect-&gt;right,0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AdjustPos(lpRect);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; if(iY + lpRect-&gt;Height() &gt; rcWA.bottom - DETASTEP &amp;&amp; iY !=rcWA.bottom-lpRect<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt;Height())<BR>&nbsp;&nbsp;&nbsp; {//调整下<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //pWnd-&gt;SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpRect-&gt;OffsetRect(0,rcWA.bottom-lpRect-&gt;bottom);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return FALSE;<BR>}<BR>//然后在ONMOVEING事件中使用所下过程调用<BR>CRect r=*pRect;<BR>AdjustPos(&amp;r);<BR>*pRect=(RECT)r;</P>
<H4>十二、给系统菜单添加一个菜单项</H4>
<P>　　给系统菜单添加一个菜单项需要进行下述三个步骤：</P>
<P>　　首先，使用Resource Symbols对话（在View菜单中选择Resource Symbols．．．可以显示该对话）定义菜单项ID，该ID应大于0x0F而小于0xF000；<BR>　　其次，调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的</P>
<P class=code>int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)<BR>{<BR>&nbsp;&nbsp;&nbsp; //…<BR>&nbsp;&nbsp;&nbsp; //Make sure system menu item is in the right range.<BR>&nbsp;&nbsp;&nbsp; ASSERT(IDM_MYSYSITEM&lt;0xF000);<BR>&nbsp;&nbsp;&nbsp; //Get pointer to system menu.<BR>&nbsp;&nbsp;&nbsp; CMenu* pSysMenu=GetSystemMenu(FALSE);<BR>&nbsp;&nbsp;&nbsp; ASSERT_VALID(pSysMenu);<BR>&nbsp;&nbsp;&nbsp; //Add a separator and our menu item to system menu.<BR>&nbsp;&nbsp;&nbsp; CString StrMenuItem(_T ("New menu item"));<BR>&nbsp;&nbsp;&nbsp; pSysMenu-&gt;AppendMenu(MF_SEPARATOR);<BR>&nbsp;&nbsp;&nbsp; pSysMenu-&gt;AppendMenu(MF_STRING, IDM_MYSYSITEM, StrMenuItem);<BR>&nbsp;&nbsp;&nbsp; //…<BR>}<BR></P>
<H4>十三、运行其它程序</H4>
<P>　　1、运行EMAIL或网址</P>
<P class=code>char szMailAddress[80];<BR>strcpy(szMailAddress,"mailto:netvc@21cn.com");<BR>ShellExecute(NULL, "open", szMailAddress, NULL, NULL, SW_SHOWNORMAL);</P>
<P>　　2、运行可执行程序</P>
<P class=code>WinExec("notepad.exe",SW_SHOW); //运行计事本</P>
<H4>十四、动态增加或删除菜单</H4>
<P>1、 增加菜单<BR>添加</P>
<P class=code>CMenu *mainmenu;<BR>mainmenu=AfxGetMainWnd()-&gt;GetMenu(); //得到主菜单<BR>(mainmenu-&gt;GetSubMenu (0))-&gt;AppendMenu (MF_SEPARATOR);//添加分隔符<BR>(mainmenu-&gt;GetSubMenu (0))-&gt;AppendMenu(MF_STRING,ID_APP_ABOUT,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _T("Always on &amp;Top")); //添加新的菜单项<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawMenuBar(); //重画菜单</P>
<P>2、 删除菜单</P>
<P>删除</P>
<P class=code>CMenu *mainmenu;<BR>mainmenu=AfxGetMainWnd()-&gt;GetMenu(); //得到主菜单<BR><BR>CString str ;<BR>for(int i=(mainmenu-&gt;GetSubMenu (0))-&gt;GetMenuItemCount()-1;i&gt;=0;i--) //取得菜单的项数。<BR>{<BR>&nbsp;&nbsp;&nbsp; (mainmenu-&gt;GetSubMenu (0))-&gt;GetMenuString(i,str,MF_BYPOSITION);<BR>&nbsp;&nbsp;&nbsp; //将指定菜单项的标签拷贝到指定的缓冲区。MF_BYPOSITION的解释见上。<BR>&nbsp;&nbsp;&nbsp; if(str=="Always on &amp;Top") //如果是刚才我们增加的菜单项，则删除。<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (mainmenu-&gt;GetSubMenu (0))-&gt;DeleteMenu(i,MF_BYPOSITION);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P>
<H4>十五、改变应用程序的图标静态更改：</H4>
<P>　　修改图标资源IDR_MAINFRAME。它有两个图标，一个是16*16的，另一个是32*32的，注意要一起修改。</P>
<P>　　动态更改： 向主窗口发送WM_SETICON消息.代码如下：</P>
<P class=code>HICON hIcon=AfxGetApp()-&gt;LoadIcon(IDI_ICON);<BR>ASSERT(hIcon);<BR>AfxGetMainWnd()-&gt;SendMessage(WM_SETICON,TRUE,(LPARAM)hIcon);</P>
<H4>十六、另一种改变窗口标题的方法</H4>
<P>　　使用语句 CWnd* m_pCWnd = AfxGetMainWnd( )，然后，再以如下形式调用SetWindowText()函数：</P>
<P class=code>SetWindowText( *m_pCWnd,(LPCTSTR)m_WindowText);// m_WindowText可以是一个CString类的变量。</P>
<H4>十七、剪切板上通过增强元文件拷贝图像数据</H4>
<P>　　下面代码拷贝通过元文件拷贝图像数据到任何应用程序，</P>
<P>//其可以放置在CView派生类的函数中。</P>
<P class=code>CMetaFileDC * m_pMetaDC = new CMetaFileDC();<BR>m_pMetaDC-&gt;CreateEnhanced(GetDC(),NULL,NULL,"whatever");<BR>//draw meta file<BR>//do what ever you want to do: bitmaps, lines, text...<BR>//close meta file dc and prepare for clipboard;<BR>HENHMETAFILE hMF = m_pMetaDC-&gt;CloseEnhanced();<BR>//copy to clipboard<BR>OpenClipboard();<BR>EmptyClipboard();<BR>::SetClipboardData(CF_ENHMETAFILE,hMF); <BR>CloseClipboard();<BR><BR>//DeleteMetaFile(hMF);<BR>delete m_pMetaDC;<BR></P>
<H4>十八、剪切板上文本数据的传送把文本放置到剪接板上：</H4>
<P class=code>CString source;<BR>//put your text in source<BR>if(OpenClipboard())<BR>{<BR>&nbsp;&nbsp;&nbsp; HGLOBAL clipbuffer;<BR>&nbsp;&nbsp;&nbsp; char * buffer;<BR>&nbsp;&nbsp;&nbsp; EmptyClipboard();<BR>&nbsp;&nbsp;&nbsp; clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);<BR>&nbsp;&nbsp;&nbsp; buffer = (char*)GlobalLock(clipbuffer);<BR>&nbsp;&nbsp;&nbsp; strcpy(buffer, LPCSTR(source));<BR>&nbsp;&nbsp;&nbsp; GlobalUnlock(clipbuffer);<BR>&nbsp;&nbsp;&nbsp; SetClipboardData(CF_TEXT,clipbuffer);<BR>&nbsp;&nbsp;&nbsp; CloseClipboard();<BR>}<BR><BR>//从剪接板上获取文本：<BR><BR>char * buffer;<BR>if(OpenClipboard())<BR>{<BR>&nbsp;&nbsp;&nbsp; buffer = (char*)GetClipboardData(CF_TEXT);<BR>&nbsp;&nbsp;&nbsp; //do something with buffer here<BR>&nbsp;&nbsp;&nbsp; //before it goes out of scope<BR>}<BR>CloseClipboard();</P>
<H4>十九、将捕捉屏幕图像到剪切版中</H4>
<P class=code>void CShowBmpInDlgDlg::OnCutScreen()<BR>{<BR>&nbsp;&nbsp;&nbsp; ShowWindow(SW_HIDE);<BR>&nbsp;&nbsp;&nbsp; RECT r_bmp={0,0,::GetSystemMetrics(SM_CXSCREEN),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ::GetSystemMetrics(SM_CYSCREEN)}; <BR>&nbsp;&nbsp;&nbsp; HBITMAP hBitmap;<BR>&nbsp;&nbsp;&nbsp; hBitmap=CopyScreenToBitmap(&amp;r_bmp);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //hWnd为程序窗口句柄<BR>&nbsp;&nbsp;&nbsp; if (OpenClipboard())<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EmptyClipboard();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetClipboardData(CF_BITMAP, hBitmap);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseClipboard();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; ShowWindow(SW_SHOW);<BR>}<BR>HBITMAP CShowBmpInDlgDlg::CopyScreenToBitmap(LPRECT lpRect)<BR>{<BR>&nbsp;&nbsp;&nbsp; //lpRect 代表选定区域<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hScrDC, hMemDC;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 屏幕和内存设备描述表<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HBITMAP hBitmap, hOldBitmap;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 位图句柄<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nX, nY, nX2, nY2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 选定区域坐标<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nWidth, nHeight;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 位图宽度和高度<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int xScrn, yScrn;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 屏幕分辨率<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 确保选定区域不为空矩形<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IsRectEmpty(lpRect))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //为屏幕创建设备描述表<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //为屏幕设备描述表创建兼容的内存设备描述表<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hMemDC = CreateCompatibleDC(hScrDC);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 获得选定区域坐标<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nX = lpRect-&gt;left;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nY = lpRect-&gt;top;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nX2 = lpRect-&gt;right;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nY2 = lpRect-&gt;bottom;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 获得屏幕分辨率<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xScrn = GetDeviceCaps(hScrDC, HORZRES);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yScrn = GetDeviceCaps(hScrDC, VERTRES);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //确保选定区域是可见的<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nX&lt;0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nX = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nY&lt;0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nY = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nX2&gt;xScrn)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nX2 = xScrn;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nY2&gt;yScrn)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nY2 = yScrn;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nWidth = nX2 - nX;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nHeight = nY2 - nY;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个与屏幕设备描述表兼容的位图<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hBitmap = CreateCompatibleBitmap<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (hScrDC, nWidth, nHeight);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 把新位图选到内存设备描述表中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 把屏幕设备描述表拷贝到内存设备描述表中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //得到屏幕位图的句柄<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //清除<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hScrDC);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hMemDC);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 返回位图句柄<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hBitmap;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P>
<H4>二十、如何将位图缩放显示在Static控件中</H4>
<P class=code>//在Staic控件内显示位图<BR>void CShowBmpInDlgDlg::ShowBmpInStaic()<BR>{<BR>&nbsp;&nbsp;&nbsp; CBitmap hbmp;<BR>&nbsp;&nbsp;&nbsp; HBITMAP hbitmap;<BR>&nbsp;&nbsp;&nbsp; //将pStatic指向要显示的地方<BR>&nbsp;&nbsp;&nbsp; CStatic *pStaic;<BR>&nbsp;&nbsp;&nbsp; pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);<BR>&nbsp;&nbsp;&nbsp; //装载资源 MM.bmp是我的一个文件名，用你的替换<BR>&nbsp;&nbsp;&nbsp; hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"MM.bmp",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; hbmp.Attach(hbitmap);<BR>&nbsp;&nbsp;&nbsp; //获取图片格式<BR>&nbsp;&nbsp;&nbsp; BITMAP bm;<BR>&nbsp;&nbsp;&nbsp; hbmp.GetBitmap(&amp;bm);<BR>&nbsp;&nbsp;&nbsp; CDC dcMem;<BR>&nbsp;&nbsp;&nbsp; dcMem.CreateCompatibleDC(GetDC());<BR>&nbsp;&nbsp;&nbsp; CBitmap *poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);<BR>&nbsp;&nbsp;&nbsp; CRect lRect;<BR>&nbsp;&nbsp;&nbsp; pStaic-&gt;GetClientRect(&amp;lRect);<BR>&nbsp;&nbsp;&nbsp; //显示位图<BR>&nbsp;&nbsp;&nbsp; pStaic-&gt;GetDC()-&gt;StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Height(),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);<BR>&nbsp;&nbsp;&nbsp; dcMem.SelectObject(&amp;poldBitmap);<BR>}</P><img src ="http://www.blogjava.net/kenneth/aggbug/11831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 13:21 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用通用对话框</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11815.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11815.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11815.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11815.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11815.html</trackback:ping><description><![CDATA[<SPAN class=large><FONT color=#000000>&nbsp;
<P>在Windows系统中提供了一些通用对话框如：文件选择对话框<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/57_g1.gif" target=_blank><FONT color=#002c99>如图</FONT></A>，颜色选择对话框<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/57_g2.gif" target=_blank><FONT color=#002c99>如图</FONT></A>，字体选择对话框<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/57_g3.gif" target=_blank><FONT color=#002c99>如图</FONT></A>。在MFC中使用CFileDialog，CColorDialog，CFontDialog来表示。一般来讲你不需要派生新的类，因为基类已经提供了常用的功能。而且在创建并等待对话框结束后你可以通过成员函数得到用户在对话框中的选择。 </P>
<P><B>CFileDialog文件选择对话框的使用</B>：首先构造一个对象并提供相应的参数，构造函数原型如下：<BR>CFileDialog::CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );参数意义如下： 
<UL>
<LI>bOpenFileDialog 为TRUE则显示打开对话框，为FALSE则显示保存对话文件对话框。 
<LI>lpszDefExt 指定默认的文件扩展名。 
<LI>lpszFileName 指定默认的文件名。 
<LI>dwFlags 指明一些特定风格。 
<LI>lpszFilter 是最重要的一个参数，它指明可供选择的文件类型和相应的扩展名。参数格式如： <BR>"Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||";文件类型说明和扩展名间用 | 分隔，同种类型文件的扩展名间可以用 ; 分割，每种文件类型间用 | 分隔，末尾用 || 指明。 
<LI>pParentWnd 为父窗口指针。 </LI></UL>创建文件对话框可以使用DoModal()，在返回后可以利用下面的函数得到用户选择： 
<UL>
<LI>CString CFileDialog::GetPathName( ) 得到完整的文件名，包括目录名和扩展名如：c:\test\test1.txt 
<LI>CString CFileDialog::GetFileName( ) 得到完整的文件名，包括扩展名如：test1.txt 
<LI>CString CFileDialog::GetExtName( ) 得到完整的文件扩展名，如：txt 
<LI>CString CFileDialog::GetFileTitle ( ) 得到完整的文件名，不包括目录名和扩展名如：test1 
<LI>POSITION CFileDialog::GetStartPosition( ) 对于选择了多个文件的情况得到第一个文件位置。 
<LI>CString CFileDialog::GetNextPathName( POSITION&amp; pos ) 对于选择了多个文件的情况得到下一个文件位置，并同时返回当前文件名。但必须已经调用过POSITION CFileDialog::GetStartPosition( )来得到最初的POSITION变量。 </LI></UL>
<P></P>
<P><B>CColorDialog颜色选择对话框的使用</B>：首先通过CColorDialog::CColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd* pParentWnd = NULL )构造一个对象，其中clrInit为初始颜色。通过调用DoModal()创建对话框，在返回后调用COLORREF CColorDialog::GetColor( )得到用户选择的颜色值。 </P>
<P><B>CFontDialog字体选择对话框的使用</B>：首先构造一个对象并提供相应的参数，构造函数原型如下： <BR>CFontDialog::CFontDialog( LPLOGFONT lplfInitial = NULL, DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, CDC* pdcPrinter = NULL, CWnd* pParentWnd = NULL );构造一个对象，其中参数lplfInitial指向一个LOGFONG结构（该结构介绍请见<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_22.html" target=_blank><FONT color=#002c99>2.2 在窗口中输出文字</FONT></A>），如果该参数设置为NULL表示不设置初始字体。pdcPrinter指向一个代表打印机设备环境的DC对象，若设置该参数则选择的字体就为打印机所用。pParentWnd用于指定父窗口。通过调用DoModal()创建对话框，在返回后通过调用以下函数来得到用户选择： 
<UL>
<LI>void CFontDialog::GetCurrentFont( LPLOGFONT lplf );用来获得所选字体的属性。该函数有一个参数，该参数是指向LOGFONT结构的指针，函数将所选字体的各种属性写入这个LOGFONT结构中。 
<LI>CString CFontDialog::GetFaceName( ) 得到所选字体名字。 
<LI>int CFontDialog::GetSize( ) 得到所选字体的尺寸（以10个象素为单位）。 
<LI>COLORREF CFontDialog::GetColor( ) 得到所选字体的颜色。 
<LI>BOOL CFontDialog::IsStrikeOut( )<BR>BOOL CFontDialog::IsUnderline( )<BR>BOOL CFontDialog::IsBold( )<BR>BOOL CFontDialog::IsItalic( )<BR>得到所选字体的其他属性，是否有删除线，是否有下划线，是否为粗体，是否为斜体。 </LI></UL></FONT></SPAN><img src ="http://www.blogjava.net/kenneth/aggbug/11815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 10:45 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在对话框中进行数据交换和数据检查</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11813.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11813.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11813.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11813.html</trackback:ping><description><![CDATA[<SPAN class=large><FONT color=#000000>&nbsp;
<P>MFC提供两种方法在对话框中进行数据交换和数据检查（Dialog data exchange/Dialog data validation），数据交换和数据检查的思想是将某一变量和对话框中的一个子窗口进行关联，然后通过调用BOOL UpdateData( BOOL bSaveAndValidate = TRUE )来指示MFC将变量中数据放入子窗口还是将子窗口中数据取到变量中并进行合法性检查。</P>
<P>在进行数据交换时一个子窗口可以和两种类型的变量相关联，一种是控件（Control）对象，比如说按钮子窗口可以和一个CButton对象相关联，这种情况下你可以通过该对象直接控制子窗口，而不需要象上节中讲的一样使用GetDlgItem(IDC_CONTROL_ID)来得到窗口指针；一种是内容对象，比如说输入框可以和一个CString对象关联，也可以和一个UINT类型变量关联，这种情况下你可以直接设置/获取窗口中的输入内容。</P>
<P>而数据检查是在一个子窗口和一个内容对象相关联时在存取内容时对内容进行合法性检查，比如说当一个输入框和一个CString对象关联时，你可以设置检查CString的对象的最长/最小长度，当输入框和一个UINT变量相关联时你可以设置检查UINT变量的最大/最小值。在BOOL UpdateData( BOOL bSaveAndValidate = TRUE )被调用后，合法性检查会自动进行，如果无法通过检查MFC会弹出消息框进行提示，并返回FALSE。</P>
<P>设置DDX/DDV在VC中非常简单，ClassWizard可以替你完成所有的工作，你只需要打开ClassWizard并选中Member Variables页，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/55_g1.gif" target=_blank><FONT color=#002c99>如图</FONT></A>，你可以看到所有可以进行关联的子窗口ID列表，双击一个ID会弹出一个添加变量的对话框，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/55_g2.gif" target=_blank><FONT color=#002c99>如图</FONT></A>，填写相关的信息后按下确定按钮就可以了。然后选中你刚才添加的变量在底部的输入框中输入检查条件，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/55_g3.gif" target=_blank><FONT color=#002c99>如图</FONT></A>。</P>
<P>下面我们看一个例子，对话框上的子窗口<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/55_g4.gif" target=_blank><FONT color=#002c99>如图</FONT></A>设置，各子窗口的ID和关联的变量如下表： 
<TABLE cellSpacing=0 cellPadding=3 width="100%" align=center border=1>
<TBODY>
<TR>
<TD><FONT color=#000000>ID</FONT></TD>
<TD><FONT color=#000000>关联的变量</FONT></TD>
<TD><FONT color=#000000>作用</FONT></TD></TR>
<TR>
<TD><FONT color=#000000>IDC_CHECK_TEST</FONT></TD>
<TD><FONT color=#000000>BOOL m_fCheck</FONT></TD>
<TD><FONT color=#000000>检查框是否被选中</FONT></TD></TR>
<TR>
<TD><FONT color=#000000>IDC_RADOI_TEST_1</FONT></TD>
<TD><FONT color=#000000>int m_iSel</FONT></TD>
<TD><FONT color=#000000>当前选择的圆形按钮的索引</FONT></TD></TR>
<TR>
<TD><FONT color=#000000>IDC_COMBO_TEST</FONT></TD>
<TD><FONT color=#000000>CString m_szCombo</FONT></TD>
<TD><FONT color=#000000>组合框中选中的文本或是输入的文本</FONT></TD></TR>
<TR>
<TD><FONT color=#000000>IDC_EDIT_TEST</FONT></TD>
<TD><FONT color=#000000>CString m_szEdit</FONT></TD>
<TD><FONT color=#000000>输入框中输入的文本，最大长度为5</FONT></TD></TR>
<TR>
<TD><FONT color=#000000>IDC_LIST_TEST</FONT></TD>
<TD><FONT color=#000000>CListBox m_lbTest</FONT></TD>
<TD><FONT color=#000000>列表框对象</FONT></TD></TR></TBODY></TABLE>这时候ClassWizard会自动生成变量定义和相关代码，在对话框的构造函数中可以对变量的初始值进行设置，此外在BOOL CDialog::OnInitDialog()中会调用UpdateData(FALSE)，即会将变量中的数据放入窗口中 。相关代码如下： <PRE>//头文件中的变量定义，ClassWizard自动产生
// Dialog Data
	//{{AFX_DATA(CMy55_s1Dlg)
	enum { IDD = IDD_MY55_S1_DIALOG };
	CListBox	m_lbTest;
	int		m_iSel;
	CString	m_szEdit;
	CString	m_szCombo;
	BOOL	m_fCheck;
	//}}AFX_DATA
//构造函数中赋初值
CMy55_s1Dlg::CMy55_s1Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMy55_s1Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMy55_s1Dlg)
	m_iSel = -1;
	m_szEdit = _T("");
	m_szCombo = _T("");
	m_fCheck = FALSE;
	//}}AFX_DATA_INIT
.....
}
//ClassWizard产生的关联和检查代码
void CMy55_s1Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMy55_s1Dlg)
	DDX_Control(pDX, IDC_LIST_TEST, m_lbTest);
	DDX_Radio(pDX, IDC_RADIO_TEST_1, m_iSel);
	DDX_Text(pDX, IDC_EDIT_TEST, m_szEdit);
	DDV_MaxChars(pDX, m_szEdit, 5);
	DDX_CBString(pDX, IDC_COMBO_TEST, m_szCombo);
	DDX_Check(pDX, IDC_CHECK_TEST, m_fCheck);
	//}}AFX_DATA_MAP
}
//在OnInitDialog中利用已经关联过的变量m_lbTest
BOOL CMy55_s1Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();
...	
	// TODO: Add extra initialization here
	//设置列表框中数据
	m_lbTest.AddString("String 1");
	m_lbTest.AddString("String 2");
	m_lbTest.AddString("String 3");
	m_lbTest.AddString("String 4");
	return TRUE;  // return TRUE  unless you set the focus to a control
}
//对两个按钮消息处理
//通过UpdateData(TRUE)得到窗口中数据
void CMy55_s1Dlg::OnGet() 
{
	if(UpdateData(TRUE))
	{
		//数据合法性检查通过，可以使用变量中存放的数据
		CString szOut;
		szOut.Format("radio =%d \ncheck is %d\nedit input is
 %s\ncomboBox input is %s\n",
	m_iSel,m_fCheck,m_szEdit,m_szCombo);
		AfxMessageBox(szOut);
	}
	//else 未通过检查
}
//通过UpdateData(FALSE)将数据放入窗口
void CMy55_s1Dlg::OnPut() 
{
	m_szEdit="onPut test";
	m_szCombo="onPut test";
	UpdateData(FALSE);
}	
</PRE>
<P></P>
<P>在上面的例子中我们看到利用DDX/DDV和UpdateData(BOOL)调用我们可以很方便的存取数据，而且也可以同时进行合法性检查。<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/55_s1.zip"><FONT color=#002c99>下载例子代码</FONT></A></P></FONT></SPAN><img src ="http://www.blogjava.net/kenneth/aggbug/11813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 10:42 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于对话框的创建</title><link>http://www.blogjava.net/kenneth/archive/2005/09/02/11811.html</link><dc:creator>Kenneth Blog</dc:creator><author>Kenneth Blog</author><pubDate>Fri, 02 Sep 2005 02:41:00 GMT</pubDate><guid>http://www.blogjava.net/kenneth/archive/2005/09/02/11811.html</guid><wfw:comment>http://www.blogjava.net/kenneth/comments/11811.html</wfw:comment><comments>http://www.blogjava.net/kenneth/archive/2005/09/02/11811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kenneth/comments/commentRss/11811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kenneth/services/trackbacks/11811.html</trackback:ping><description><![CDATA[<P><STRONG><FONT size=4>1 使用资源编辑器编辑对话框<!-- #EndEditable --><BR><!-- #BeginEditable "%D7%F7%D5%DF%BC%B0%CA%B1%BC%E4" --><!-- #EndEditable --><!-- #BeginEditable "%D5%FD%CE%C4" --></FONT></STRONG><SPAN class=large><FONT color=#000000></P>
<P>在Windows开发中弹出对话框是一种常用的输入/输出手段，同时编辑好的对话框可以保存在资源文件中。Visual C++提供了对话框编辑工具，利用编辑工具可以方便的添加各种控件到对话框中，而且利用ClassWizard可以方便的生成新的对话框类和映射消息。</P>
<P>首先资源列表中按下右键，可以在弹出菜单中选择“插入对话框”，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g1.gif" target=_blank><FONT color=#002c99>如图1</FONT></A>。然后再打开该对话框进行编辑，你会在屏幕上看到一个控件板，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g2.gif" target=_blank><FONT color=#002c99>如图2</FONT></A>。你可以将所需要添加的控件拖到对话框上，或是先选中后再在对话框上用鼠标画出所占的区域。</P>
<P>接下来我们在对话框上产生一个输入框，和一个用于显示图标的图片框。之后我们使用鼠标右键单击产生的控件并选择其属性，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g3.gif" target=_blank><FONT color=#002c99>如图3</FONT></A>。我们可以在属性对话框中编辑控件的属性同时也需要指定控件ID，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g4.gif" target=_blank><FONT color=#002c99>如图4</FONT></A>，如果在选择对话框本身的属性那么你可以选择对话框的一些属性，包括字体，外观，是否有系统菜单等等。最后我们编辑图片控件的属性，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g5.gif" target=_blank><FONT color=#002c99>如图5</FONT></A>，我们设置控件的属性为显示图标并指明一个图标ID。</P>
<P>接下来我们添加一些其他的控件，最后的效果<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g6.gif" target=_blank><FONT color=#002c99>如图6</FONT></A>。按下Ctrl-T可以测试该对话框。此外在对话框中还有一个有用的特性，就是可以利用Tab键让输入焦点在各个控件间移动，要达到这一点首先需要为控件设置在Tab键按下时可以接受焦点移动的属性Tab Stop，如果某一个控件不打算利用这一特性，你需要清除这一属性。然后从菜单“Layout”选择Tab Order来确定焦点移动顺序，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_g7.gif" target=_blank><FONT color=#002c99>如图7</FONT></A>。使用鼠标依此点击控件就可以重新规定焦点移动次序。最后按下Ctrl-T进行测试。</P>
<P>最后我们需要为对话框产生新的类，ClassWizard可以替我们完成大部分的工作，我们只需要填写几个参数就可以了。在编辑好的对话框上双击，然后系统回询问是否添加新的对话框，选择是并在接下来的对话框中输入类名就可以了。ClassWizard会为你产生所需要的头文件和CPP文件。然后在需要使用的地方包含相应的头文件，对于有模式对话框使用DoModal()产生，对于无模式对话框使用Create()产生。相关代码如下； <PRE>void CMy51_s1View::OnCreateDlg() 
{//产生无模式对话框
	CTestDlg *dlg=new CTestDlg;
	dlg-&gt;Create(IDD_TEST_DLG);
	dlg-&gt;ShowWindow(SW_SHOW);
}

void CMy51_s1View::OnDoModal() 
{//产生有模式对话框
	CTestDlg dlg;
	int iRet=dlg.DoModal();
	TRACE("dlg return %d\n",iRet);
}
</PRE>
<P><A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/51_s1.zip"><FONT color=#002c99>下载例子</FONT></A>。如果你在调试这个程序时你会发现程序在退出后会有内存泄漏，这是因为我没有释放无模式对话框所使用的内存，这一问题会在以后的章节<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_53.html" target=_blank><FONT color=#002c99>5.3 创建无模式对话框</FONT></A>中专门讲述。 </P>
<P></P>
<P><B>关于在使用对话框时Enter键和Escape键的处理：</B>在使用对话框是你会发现当你按下Enter键或Escape键都会退出对话框，这是因为Enter键会引起CDialog::OnOK()的调用，而Escape键会引起CDialog::OnCancel()的调用。而这两个调用都会引起对话框的退出。在MFC中这两个成员函数都是虚拟函数，所以我们需要进行重载，如果我们不希望退出对话框那么我们可以在函数中什么都不做，如果需要进行检查则可以添加检查代码，然后调用父类的OnOK()或OnCancel()。相关代码如下； <PRE>void CTestDlg::OnOK()
{
	AfxMessageBox("你选择确定");
	CDialog::OnOK();
}

void CTestDlg::OnCancel()
{
	AfxMessageBox("你选择取消");
	CDialog::OnCancel();
}</PRE>
<P></FONT></SPAN><STRONG><FONT size=4>2 创建有模式对话框<!-- #EndEditable --><BR><!-- #BeginEditable "%D7%F7%D5%DF%BC%B0%CA%B1%BC%E4" --><!-- #EndEditable --><!-- #BeginEditable "%D5%FD%CE%C4" --></FONT></STRONG></P><SPAN class=large><FONT color=#000000>
<P>使用有模式对话框时在对话框弹出后调用函数不会立即返回，而是等到对话框销毁后才会返回（请注意在对话框弹出后其他窗口的消息依然会被传递）。所以在使用对话框时其他窗口都不能接收用户输入。创建有模式对话框的方法是调用CDialog::DoModal()。下面的代码演示了这种用法： <PRE>CYourView::OnOpenDlg()
{
	CYourDlg dlg;
	int iRet=dlg.DoModal();
}
</PRE>CDialog::DoModal()的返回值为IDOK，IDCANCEL。表明操作者在对话框上选择“确认”或是“取消”。由于在对话框销毁前DoModal不会返回，所以可以使用局部变量来引用对象。在退出函数体后对象同时也会被销毁。而对于无模式对话框则不能这样使用，下节<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_53.html" target=_blank><FONT color=#002c99>3 创建无模式对话框</FONT></A>中会详细讲解。 
<P></P>
<P>你需要根据DoModal()的返回值来决定你下一步的动作，而得到返回值也是使用有模式对话框的一个很大原因。</P>
<P>使用有模式对话框需要注意一些问题，比如说不要在一些反复出现的事件处理过程中生成有模式对话框，比如说在定时器中产生有模式对话框，因为在上一个对话框还未退出时，定时器消息又会引起下一个对话框的弹出。</P>
<P>同样的在你的对话框类中为了向调用者返回不同的值可以调用CDialog::OnOK()或是CDialog::OnCancel()以返回IDOK或IDCANCEL，如果你希望返回其他的值，你需要调用 <BR>CDialog::EndDialog( int nResult );其中nResult会作为DoModal()调用的返回值。</P>
<P>下面的代码演示了如何使用自己的函数来退出对话框：<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/52_s1.zip"><FONT color=#002c99>下载例子</FONT></A> <PRE>void CMy52_s1View::OnLButtonDown(UINT nFlags, CPoint point) 
{//创建对话框并得到返回值
	CView::OnLButtonDown(nFlags, point);
	CTestDlg dlg;
	int iRet=dlg.DoModal();
	CString szOut;
	szOut.Format("return value %d",iRet);
	AfxMessageBox(szOut);
}
//重载OnOK,OnCancel
void CTestDlg::OnOK()
{//什么也不做
}
void CTestDlg::OnCancel()
{//什么也不做
}
//在对话框中对三个按钮消息进行映射
void CTestDlg::OnExit1() 
{
	CDialog::OnOK();
}
void CTestDlg::OnExit2() 
{
	CDialog::OnCancel();
}
void CTestDlg::OnExit3() 
{
	CDialog::EndDialog(0XFF);
}
</PRE>由于重载了OnOK和OnCancel所以在对话框中按下Enter键或Escape键时都不会退出，只有按下三个按钮中的其中一个才会返回。 
<P></P>
<P>此外在对话框被生成是会自动调用BOOL CDialog::OnInitDialog()，你如果需要在对话框显示前对其中的控件进行初始化，你需要重载这个函数，并在其中填入相关的初始化代码。利用ClassWizard可以方便的产生一些默认代码，首先打开ClassWizard，选择相应的对话框类，在右边的消息列表中选择WM_INITDIALOG并双击，<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/52_g1.gif" target=_blank><FONT color=#002c99>如图</FONT></A>，ClassWizard会自动产生相关代码，代码如下： <PRE>BOOL CTestDlg::OnInitDialog() 
{
	/*先调用父类的同名函数*/
	CDialog::OnInitDialog();
	/*填写你的初始化代码*/	
	return TRUE;  
}
</PRE>有关对对话框中控件进行初始化会在<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/01_54.html" target=_blank><FONT color=#002c99>4 在对话框中进行消息映射</FONT></A>中进行更详细的讲解。 <BR><STRONG><FONT size=4><BR>3 创建无模式对话框<!-- #EndEditable --><BR><!-- #BeginEditable "%D7%F7%D5%DF%BC%B0%CA%B1%BC%E4" --><!-- #EndEditable --><!-- #BeginEditable "%D5%FD%CE%C4" --></FONT></STRONG><SPAN class=large><FONT color=#000000>
<P>无模式对话框与有模式对话框不同的是在创建后其他窗口都可以继续接收用户输入，因此无模式对话框有些类似一个弹出窗口。创建无模式对话框需要调用<BR>BOOL CDialog::Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );之后还需要调用 <BR>BOOL CDialog::ShowWindow( SW_SHOW);进行显示，否则无模式对话框将是不可见的。相关代码如下： <PRE>void CYourView::OnOpenDlg(void)
{
	/*假设IDD_TEST_DLG为已经定义的对话框资源的ID号*/
	CTestDlg *dlg=new CTestDlg;
	dlg-&gt;Create(IDD_TEST_DLG,NULL);
	dlg-&gt;ShowWindows(SW_SHOW);
	/*不要调用 delete dlg;*/
}
</PRE>在上面的代码中我们新生成了一个对话框对象，而且在退出函数时并没有销毁该对象。因为如果此时销毁该对象（对象被销毁时窗口同时被销毁），而此时对话框还在显示就会出现错误。那么这就提出了一个问题：什么时候销毁该对象。我时常使用的方法有两个： 
<UL>
<LI><B>在对话框退出时销毁自己：</B>在对话框中重载OnOK与OnCancel在函数中调用父类的同名函数，然后调用DestroyWindow()强制销毁窗口，在对话框中映射WM_DESTROY消息，在消息处理函数中调用<FONT color=red>delete this</FONT>;强行删除自身对象。相关代码如下： <PRE>void CTestDlg1::OnOK()
{
	CDialog::OnOK();
	DestroyWindow();
}

void CTestDlg1::OnCancel()
{
	CDialog::OnCancel();
	DestroyWindow();
}

void CTestDlg1::OnDestroy() 
{
	CDialog::OnDestroy();
	AfxMessageBox("call delete this");
	delete this;
}
</PRE>这种方法的要点是在窗口被销毁的时候，删除自身对象。所以你可以在任何时候调用DestroyWindow()以达到彻底销毁自身对象的作用。（DestroyWindow()的调用会引起OnDestroy()的调用） 
<LI><B>通过向父亲窗口发送消息，要求其他窗口对其进行销毁：</B>首先需要定义一个消息用于进行通知，然后在对话框中映射WM_DESTROY消息，在消息处理函数中调用消息发送函数通知其他窗口。在接收消息的窗口中利用ON_MESSAGE映射处理消息的函数，并在消息处理函数中删除对话框对象。相关代码如下： <PRE>/*更改对话框的有关文件*/
CTestDlg2::CTestDlg2(CWnd* pParent /*=NULL*/)
	: CDialog(CTestDlg2::IDD, pParent)
{/*m_pParent为一成员变量，用于保存通知窗口的指针，
所以该指针不能是一个临时指针*/
	ASSERT(pParent);
	m_pParent=pParent;
	//{{AFX_DATA_INIT(CTestDlg2)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}
void CTestDlg2::OnOK()
{
	CDialog::OnOK();
	DestroyWindow();
}

void CTestDlg2::OnCancel()
{
	CDialog::OnCancel();
	DestroyWindow();
}

void CTestDlg2::OnDestroy() 
{
	CDialog::OnDestroy();
	/*向其他窗口发送消息，将自身指针作为一个参数发送*/
	m_pParent-&gt;PostMessage(WM_DELETE_DLG,<FONT color=red>(WPARAM)this</FONT>);
}

/*在消息接收窗口中添加消息映射*/
/*在头文件中添加函数定义*/
	<FONT color=red>afx_msg LONG OnDelDlgMsg(WPARAM wP,LPARAM lP);</FONT>
/*添加消息映射代码*/
	<FONT color=red>ON_MESSAGE(WM_DELETE_DLG,OnDelDlgMsg)</FONT>
END_MESSAGE_MAP()
/*实现消息处理函数*/
LONG CMy53_s1View::OnDelDlgMsg(WPARAM wP,LPARAM lP)
{
	delete <FONT color=red>(CTestDlg2*)wP</FONT>;
	return 0;
}
/*创建对话框*/
void CMy53_s1View::OnTest2() 
{
	CTestDlg2 *dlg=new CTestDlg2(this);
	dlg-&gt;Create(IDD_TEST_DLG_2);
	dlg-&gt;ShowWindow(SW_SHOW);
}
</PRE>在这种方法中我们利用消息来进行通知，在Window系统中利用消息进行通知和传递数据的用法是很多的。 </LI></UL>
<P></P>
<P>同样无模式对话框的另一个作用还可以用来在用户在对话框中的输入改变时可以及时的反映到其他窗口。下面的代码演示了在对话框中输入一段文字，然后将其更新到视图的显示区域中，这同样也是利用了消息进行通知和数据传递。 <PRE>/*在对话框中取出数据，并向其他窗口发送消息和数据，将数据指针作为一个参数发送*/
void CTestDlg2::OnCommBtn() 
{
	char szOut[30];
	GetDlgItemText(IDC_OUT,szOut,30);
	<FONT color=red>m_pParent-&gt;SendMessage(WM_DLG_NOTIFY,(WPARAM)szOut);</FONT>
}

/*在消息接收窗口中*/
/*映射消息处理函数*/
	<FONT color=red>ON_MESSAGE(WM_DLG_NOTIFY,OnDlgNotifyMsg)</FONT>

/*在视图中绘制出字符串 m_szOut*/
void CMy53_s1View::OnDraw(CDC* pDC)
{
	CMy53_s1Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	pDC-&gt;TextOut(0,0,"Display String");
	pDC-&gt;TextOut(0,20,m_szOut);
}
/*处理通知消息，保存信息并更新显示*/
LONG CMy53_s1View::OnDlgNotifyMsg(WPARAM wP,LPARAM lP)
{
	<FONT color=red>m_szOut=(char*)wP;</FONT>
	Invalidate();
	return 0;
}

</PRE>此外这种用法利用消息传递数据的方法对有模式对话框和其他的窗口间通信也一样有效。<A href="http://tech.china.com/zh_cn/netschool/programme/c/656/20001207/53_s1.zip"><FONT color=#002c99>下载本节例子</FONT></A> 
<P>&nbsp;</P></FONT></SPAN></FONT></SPAN><img src ="http://www.blogjava.net/kenneth/aggbug/11811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kenneth/" target="_blank">Kenneth Blog</a> 2005-09-02 10:41 <a href="http://www.blogjava.net/kenneth/archive/2005/09/02/11811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>