vc编程指南67篇  

 
  

  
 

    
 
 
 * 贴子主题: vc编程指南67篇   回复贴子             
 
 
 

   
  
  
  
 
 


 

摘自"水木清华"

 1. 如何获取应用程序的实例句柄?
  应用程序的 实例句柄保存在CWinAppIm_hInstance 中,可以这么调用
  AfxGetInstancdHandle获得句柄.
    Example: HANDLE hInstance=AfxGetInstanceHandle();

 2. 如何通过代码获得应用程序主窗口的 指针?
   主窗口的 指针保存在CWinThread::m_pMainWnd中,调用 AfxGetMainWnd实现。
    AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化.

 3.如何在程序中获得其他程序的 图标?
    两种方法:
      (1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,
      (2) SDK函数 SHGetFileInfo获得有关文件的 很多信息,如大小图标,属性,
         类型等.
        Example(1): 在程序窗口左上角显示 NotePad图标.

         void CSampleView: OnDraw(CDC * pDC)
           {
              if( :: SHGetFileInfo(_T("c://pwin95//notepad.exe"),0,
                   &stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
                 {
                   pDC ->DrawIcon(10,10,stFileInfo.hIcon);
                 }    
            }
          Example(2):同样功能,Use ExtractIcon Function

          void CSampleView:: OnDraw(CDC *pDC)
            {
              HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
               ("NotePad.exe"),0);

              if (hIcon &&hIcon!=(HICON)-1)
                 pDC->DrawIcon(10,10,hIcon);
              }
 说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory 函数得到,
    如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个
   比较考究的程序,考虑应该全面点.

 4.如何编程结束应用程序?如何编程控制windows的重新引导?
    这是个很简单又是编程中经常要遇到的问题.
   第一问,向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示
  是否保存修改过的数据.
   Example: AfxGetMainWindow()->SendMessage(WM_CLOSE);

  还可以创建一个自定义的函数 Terminate Window
    void Terminate Window(LPCSTR pCaption)
    {
        CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption);
             if (pWnd)
                pWnd ->SendMessage(WM_CLOSE);
    }

 说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如
 我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时 FindWindow就
 无能为力了,可以通过枚举 windows任务列表的办法来实现。 在 机械出版社
 "Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。

第二问,Use ExitWindowsEx Function函数控制系统是重新引导,还是重启 windows.
 前面已经有人讲过乐,就不再提了。

 5.怎样加栽其他的应用程序?
  我记得这好象是出场频度很高的问题。
  三个SDK函数 winexec, sh/*llexecute,createprocess可以使用。
   WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数
值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加栽一个无最大化按钮的 程序,呵呵
就是Neterm,calc等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。
  Sh/*llExecute较 WinExex灵活一点,可以指定工作目录,下面的 Example就是直接
打开 c:/temp/1.txt,而不用加栽与 txt文件关联的应用程序,很多安装程序完成后
都会打开一个窗口,来显示Readme or Faq,偶猜就是这么作的啦.
  Sh/*llExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED);

  CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以
  指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的 Example:
     STARTUPINFO stinfo;   //启动窗口的信息
     PROCESSINFO procinfo;  //进程的信息

   CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, NORMAL_PRIORITY_
     CLASS,NULL,NULL, &stinfo,&procinfo);

  6. 确定应用程序的 路径
     前些天好象有人问过这个问题.
      Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
        Example:
         TCHAR exeFullPath[MAX_PATH]; // MAX_PATH在API中定义了吧,好象是128
         GetModuleFileName(NULL,exeFullPath,MAX_PATH)

   7. 获得各种目录信息
      Windows目录: Use "GetWindowsDirectory“
      Windows下的system目录: Use "GetSystemDirectory"
      temp目录: Use "GetTempPath "
       当前目录: Use "GetCurrentDirectory"
     请注意前两个函数的第一个参数为 目录变量名,后一个为缓冲区; 后两个相反.

   8. 如何自定义消息
      也有人问过的,其实不难。
        (1) 手工定义消息,可以这么写 #define WM_MY_MESSAGE(WM_USER+100),
          MS 推荐的至少是 WM_USER+100;
        (2)写消息处理函数,用 WPARAM,LPARAM返回LRESULT.
           LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)
            {

              //加入你的处理函数
            }
         (3)  在类的 AFX_MSG处进行声明,也就是常说的"宏映射"

9-16: 对窗口的 控制

9. 如何改变窗口的 图标?
  向窗口发送 WM_SECTION消息。
  Example:
    HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON);
    ASSERT(hIcon);
    AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM) hIcon);

10. 如何改变窗口的 缺省风格?
    重栽 CWnd:: PreCreateWindow 并修改CREATESTRUCT结构来指定窗口风格和其他
   创建信息.
   Example: Delete "Max" Button and Set Original Window's Position and Size
     
    BOOL CMainFrame::  PreCreateWindow (CREATESTRUCT &cs)
    {      
     cs.style &=~WS_MAXINIZEMOX;

     cs.x=cs.y=0;
     cs.cx=GetSystemMetrics(SM_CXSCREEN/2);
     cs.cy=GetSystemMetrics(SM_CYSCREEN/2);

      return CMDIFramewnd ::PreCreateWindow(cs);
   
    }

11.  如何将窗口居中显示?
      Easy, Call Function CWnd:: Center Windows
       
       Example(1):  Center Window( );  //Relative to it's parent
        // Relative to Screen
       Example(2):  Center Window(CWnd:: GetDesktopWindow( ));
        //Relative to Application's MainWindow
       AfxGetMainWnd( ) -> Center Window( );
 
 12. 如何让窗口和 MDI窗口一启动就最大化和最小化?
     先说窗口。
     在 InitStance 函数中设定 m_nCmdShow的 取值.
       m_nCmdShow=SW_SHOWMAXMIZED ;  //最大化
       m_nCmdShow=SW_SHOWMINMIZED ;  //最小化
       m_nCmdShow=SW_SHOWNORMAL   ;   //正常方式

      MDI窗口:
        如果是创建新的应用程序,可以用 MFC AppWizard 的Advanced 按钮并在
         MDI子窗口风格组中检测最大化或最小化; 还可以重载 MDI Window 的
          PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE;
       如果从 CMDIChildWnd 派生,调用 OnInitialUpdate函数中的 CWnd::Show
      Window来指定 MDI Child Window的 风格。

 13. 如何使程序保持极小状态?
     很有意思的 问题
      这么办: 在恢复程序窗体大小时, Windows会发送WM_QUERY-OPEN消息,
      用 ClassWizard设置成员函数 OnQueryOpen() ,add following code:
          Bool CMainFrame:: OnQueryOpen( )
            {
               Return false;
            }

 14. 如何限制窗口的 大小?
    也就是 FixedDialog形式。  Windows 发送 WM_GETMAXMININFO消息来跟踪,
  响应它,在 OnGetMAXMININFO 中写代码:

 15.  如何使窗口不可见?
  很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow 控制.

 16. 如何使窗口始终在最前方?
    两种途径.
     BringWindowToTop(Handle);
     SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的 风格
     
     Example:
       void  ToggleTopMost( CWnd *pWnd)
        {
           ASSERT_VALID(pWnd);
           pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?
            &wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE);
         }


17、如何创建一个字回绕的CEditView

  重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象
的ES_AUTOHSCROLL和WS_HSCROLL风格位, 由于CEditView : : PreCreateWindow显示
设置cs. style,调用基类函数后要修改cs . style。
BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)
{
  //First call basse class function .
  BOOL bResutl =CEditView : : PreCreateWindow (cs) ;

  // Now specify the new window style .
  cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL);
  return bResult ;
}

18、通用控件的显示窗口

  MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工
作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表
控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。

19、移动窗口

  调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口
有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口
的大小。
//Move window to positoin 100 , 100 of its parent window .
SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER);

20、重置窗口的大小

  调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用
CWnd : : MoveWindow 但必须指定窗口的位置。
// Get the size of the window .
Crect reWindow ;
GetWindowRect (reWindow );

//Make the window twice as wide and twice as tall .
SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,
            reWindow . Height () * 2,
   SWP_NOMOVE |SWP_NOZORDER );

21、如何单击除了窗口标题栏以外的区域使窗口移动

 当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理
该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可
以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明
鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。
UINT CSampleDialog : : OnNcHitTest  (Cpoint point )
{
  UINT nHitTest =Cdialog: : OnNcHitTest (point );
  return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest ;
}
  上述技术有两点不利之处, 其一是在窗口的客户区域双击时, 窗口将极大;
其二, 它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键
使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN
信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。
void CSampleView : : OnLButtonDown  (UINT nFlags , Cpoint point )
{
  CView : : OnLButtonDow  (nFlags , pont );

  //Fool frame window into thinking somene clicked on
  its caption bar .
  GetParentFrame ( ) —> PostMessage (
       WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARAM (poitn .x , point .y) );
}
  该技术也适用于对话框和基于对的应用程序,只是不必调用CWnd : : GetParentFrame 。
void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )
{
  Cdialog : : OnLButtonDow (nFlags, goint );
  //Fool dialog into thinking simeone clicked on its caption bar .
PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x , point. y ) )      
}

22、如何改变视窗的背景颜色

  Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用
ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以
防止Windows擦除窗口。
//Paint area that needs to be erased.
BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)
{
// Create a pruple brush.
CBrush Brush (RGB (128 , 0 , 128) );

// Select the brush into the device context .
CBrush* pOldBrush = pDC—>SelcetObject (&brush);

// Get the area that needs to be erased .
CRect reClip ;
pDC—>GetCilpBox (&rcClip);

//Paint the area.
pDC—> PatBlt (rcClip.left , rcClip.top ,
      rcClip.Width ( ) , rcClip.Height ( ) , PATCOPY );

//Unselect brush out of device context .
pDC—>SelectObject (pOldBrush );

// Return nonzero to half fruther processing .
return TRUE;
}

23、如何改变窗口标题

  调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。
//Set title for application's main frame window .
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") );

//Set title for View's MDI child frame window .
GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title") );

//Set title for dialog's push button control.
GetDigitem  (IDC_BUTTON) —> SetWindowText  (_T ("Button new title ") );
  如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化
的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在
联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。
AfxSetWindowText的实现如下:
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
{
  itn nNewLen= Istrlen (Ipaznew);
  TCHAR szOld [256];
  //fast check to see if text really changes (reduces flash in the controls )
  if (nNewLen >_contof (szOld) ||
      : : GetWindowText (hWndCrtl , szOld , _countof (szOld) !=nNewLen ||
      Istrcmp (szOld , IpszNew )! = 0
{
  //change it
       : : SetWindowText (hWndCtrl , IpszNew );
  }
}  

24、如何防止主框窗口在其说明中显示活动的文档名

  创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位, 如果不希望在
说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。
BOOL CMainFrame : : PreCreateWindow  (CREATESTRUCT&cs)
{
  //Turn off  FWS_ADDTOTITLE in main frame .
  cs.styel & = ~FWS_ADDTOTITLE ; 
  return CMDIFrameWnd : : PreCreateWindow (cs );
}
  关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调
用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。

25、如何获取有关窗口正在处理的当前消息的信息

  调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用
ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage
来确定所选中的菜单项。
viod CMainFrame : : OnCommmonMenuHandler ( )
{
  //Display selected menu item in debug window .
  TRACE ("Menu item %u was selected . /n" ,
                               GetCruuentMessage ( ) —> wParam );
}

26、如何创建一个不规则形状的窗口
   
 可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一
个指定的区域,实际上使窗口成为指定的不规则形状。
  使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删
除所在的缺省控件、标题以及边界。
  给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。    
Class CRoundDlg : public CDialog
{
  …
private :
  Crgn m_rgn : // window region
  …
} ;
  修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给
窗口:
BOOL CRoundDlg : : OnInitDialog ( )
{
  CDialog : : OnInitDialog ( ) ;

  //Get size of dialog .
  CRect rcDialog ;
  GetClientRect (rcDialog );

  // Create region and assign to window .
  m_rgn . CreateEllipticRgn  (0 , 0 , rcDialog.Width ( ) , rcDialog .Height ( ) );
  SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn , TRUE );

  return TRUE ;
}
  通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例
子程序是修改OnPaint函数使窗口形状看起来象一个球形体。
voik CRoundDlg : : OnPaint ( )
{
  CPaintDC de (this) ; // device context for painting .
  //draw ellipse with out any border
  dc. SelecStockObject (NULL_PEN);

  //get the RGB colour components of the sphere color
  COLORREF color= RGB( 0 , 0 , 255);
  BYTE byRed =GetRvalues (color);
  BYTE byGreen = GetGvalues (color);
  BYTE byBlue = GetBvalues (color);

  // get the size of the view window
  Crect rect ;
  GetClientRect  (rect);
   
  // get minimun number of units
  int nUnits =min (rect.right , rect.bottom );  
   
  //calculate he horiaontal and vertical step size
  float fltStepHorz = (float) rect.right /nUnits ;
  float fltStepVert = (float) rect.bottom /nUnits ;

  int nEllipse = nUnits/3; // calculate how many to draw
  int nIndex ;             // current ellipse that is being draw

  CBrush brush ;       // bursh used for ellipse fill color
  CBrush *pBrushOld;     // previous brush that was selected into dc

  //draw ellipse , gradually moving towards upper-right corner
  for (nIndex = 0 ; nIndes < + nEllipse ; nIndes ++)
{
  //creat solid brush
  brush . CreatSolidBrush   (RGB ( ( (nIndex *byRed ) /nEllipse ).
             ( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue) /nEllipse ) ) );

  //select brush into dc
  pBrushOld= dc .SelectObject (&brhsh);

  //draw ellipse
  dc .Ellipse (  (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
       rect. right -( (int) fltStepHorz * nIndex )+ 1,
       rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1) ;

  //delete the brush
  brush.DelecteObject ( );
  }
  }
 
  最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。
UINT CRoundDlg : : OnNchitTest (Cpoint point )
{
  //Let user move window by clickign anywhere on the window .
  UINT nHitTest = CDialog : : OnNcHitTest (point) ;
  rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest ;
  }
27、如何在代码中获取工具条和状态条的指针

  缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条
有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说
明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些
子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar =
  (CStatusBar *) AfxGetMainWnd ( ) —> GetDescendantWindow
(AFX_IDW_STUTUS_BAR);

//Get pointer to toolbar .
CToolBar * pToolBar =
  (CToolBar * ) AfxGetMainWnd ( ) —> GetDescendantWindow (AFX_IDW_TOOLBAR);
28、如何使能和禁止工具条的工具提示

  如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止
工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle
和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
{
  ASSERT_VALID  (m_wndToolBar);

  DWORD dwStyle = m _wndToolBar.GetBarStyle ( ) ;

  if (bDisplayTips)
       dwStyle |=CBRS_TOOLTIPS ;
  else
       dwStyle & = ~ CBRS_TOOLTIPS ;

  m_wndToolBar.SetBarStyle  (dwStyle );
}
29、如何设置工具条标题

  工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,
例子如下:
int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )
{

       …
  // Set the caption of the toolbar .
  m_wndToolBar.SetWindowText  (_T "Standdard");
30、如何创建和使用无模式对话框

  MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几
个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用
ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:
模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用
CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel
调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。
void CSampleDialog : : OnOK ( )
{
  // Retrieve and validate dialog data .
  if (! UpdateData (TRUE) )
  {
      // the UpdateData rountine will set focus to correct item
      TRACEO (" UpdateData failed during dialog termination ./n") ;
      return ;
  }
   
  //Call DestroyWindow instead of EndDialog .
  DestroyWindow ( ) ;
}

void CSampleDialog : : OnCancel ( )
{
  //Call DestroyWindow instead of EndDialog .
  DestroyWindow ( ) ;
}
  其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创
建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,
因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,
可以重置该函数并执行清除操作,诸如删除this指针。
void CSampleDialog : : PostNcDestroy ( )
{
  // Declete the C++ object that represents this dialog .
  delete this ;
}
  最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,
要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序
是如何创建无模式对话的:
void CMainFrame : : OnSampleDialog  ( )
{
  //Allocate a modeless dialog object .
  CSampleDilog * pDialog =new CSampleDialog ;
  ASSERT_VALID (pDialog) ;

  //Create the modeless dialog .
  BOOL bResult = pDialog —> Creste (IDD_IDALOG) ;
  ASSERT (bResult ) ;
}

31、如何在对话框中显示一个位图

  这要归功于Win 32先进的静态控件和Microsoft的资源编辑器, 在对话框中
显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也
可以显示图标、位图以及增强型元文件。
32、如何改变对话或窗体视窗的背景颜色

  调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第
一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置
为蓝色背景和黄色文本。
BOOL CSampleApp : : InitInstance  ( )
{
      …

  //use blue dialog with yellow text .
  SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

      …
}
  需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,
通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说
明了创建一个红色背景对话的步骤。
  首先,给对话基类增加一人成员变量CBursh :
class CMyformView : public CformView
{
  …

  private :
      CBrush m_ brush ; // background brush

  …
} ;
  其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyformView : : CMyformView ( )
{
  // Initialize background brush .
  m_brush .CreateSolidBrush  (RGB ( 0, 0, 255 ) )
}
  最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的
刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor
参量。
HBRUSH CMyformView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor )  
{
  // Determine if drawing a dialog box . If we are , return +handle to
  //our own background brush . Otherwise let windows handle it .
  if (nCtlColor = = CTLCOLOR _ DLG )
      return (HBRUSH) m_brush .GetSafeHandle ( ) ;

  return CformView : : OnCtlColor (pDC, pWnd , nCtlColor );
}
33、如何获取一个对话控件的指针

  有两种方法。其一,调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成
员函数。下例调用GetDlgItem,将返回值传给一个CSpinButtonCtrl*以便调用
CSpinButtonCtrl : : SetPos 函数:
BOOL CSampleDialog : : OnInitDialog ( )
{
  CDialog : : OnInitDialog ( ) ;

  //Get pointer to spin button .
  CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem (IDC_SPIN) ;
  ASSERT _ VALID (pSpin) ;

  //Set spin button's default position .
  pSpin —> SetPos (10) ;

  return TRUE ;
}
  其二, 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简
单地选择Member Variables标签,然后选择Add Variable …按钮。如果在对话资源
编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。
34、如何禁止和使能控件

  控件也是窗口,所以可以调用CWnd : : EnableWindow使能和禁止控件。
//Disable button controls .
m_wndOK.EnableWindow (FALSE ) ;
m_wndApply.EnableWindow (FALSE ) ;

35、如何改变控件的字体

  由于控件是也是窗口,用户可以调用CWnd: : SetFont指定新字体。该函数用
一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字
体改为8点Arial字体:
//Declare font object in class declaration (.H file ).
private :
  Cfont m_font ;
// Set font in class implementation (.Cpp file ). Note m_wndButton is a
//member variable added by ClassWizard.DDX routines hook the member
//variable to a dialog button contrlo.      
BOOL CSampleDialog : : OnInitDialog ( )
{

  …

  //Create an 8-point Arial font
  m_font . CreateFont  (MulDiv (8 , -pDC—> GetDeviceCaps  (LOGPIXELSY) , 72).
     0 , 0 , 0 , FW_NORMAL , 0 , 0, 0, ANSI_CHARSER, OUT_STROKE_PRECIS ,
     CLIP_STROKE _PRECIS , DRAFT _QUALITY
     VARIABLE_PITCH |FF_SWISS, _T ("Arial") );

  //Set font for push button .
  m_wndButton . SetFont (&m _font );

  …
}

36、如何在OLE控件中使用OLE_COLOR数据类型

  诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数
返回OLE _COLOR数据类型的颜色,而GDI对象诸如笔和刷子使用的是COLORREF数据类
型,调用COleControl : : TranslateColor可以很容易地将OLE_COLOR类型改为
COLORREF类型。下例创建了一个当前背景颜色的刷子:

void CSampleControl : : OnDraw (CDC* pdc
  const Crect& rcBounds , const Crect& rcInvalid )
{
  //Create a brush of the cuttent background color .
  CBrush brushBack (TranslateColor (GetBackColor ( ) ) );

  //Paint the background using the current background color .
  pdc—> FilllRect  (rcBounds , &brushBack) ;

  //other drawign commands

  …

}

37、在不使用通用文件打开对话的情况下如何显示一个文件列表

  调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox, Windows 将自动
地向列表框或组合框填充可用的驱动器名或者指定目录中的文件,下例将Windows目
录中的文件填充在组合框中:
BOOL CSampleDig : : OnInitDialog ( )
{
  CDialog : : OnInitDialog  ( )
  TCHAR szPath [MAX_PATH] = {"c://windows"} ;
  int nReslt = DlgDirListComboBox  (szPath , IDC_COMBO , IDC_CURIDIR,
      DDL_READWRITE |DDL_READONLY|DDL_HIDDEN|
      DDL_SYSTEM|DDL_ARCHIVE ) ;
  return TRUE ;
}

38、为什么旋转按钮控件看起来倒转

  需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件
的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。
下例将旋转按钮控件的范围设置为0到100:
BOOL CAboutDlg : : OnInitDialog ( )
{
  CDialog : : OnInitDialog ( )
   
  //set the lower and upper limit of the spin button
  m_wndSpin . SetRange ( 0 ,100 ) ;
 
  return TRUE ;
}
  Visual C++ 4.0 Print对话中的Copise旋转按钮控件也有同样的问题:按下Up
按钮时拷贝的数目减少,而按下Down 按钮时拷贝的数目增加。

39为什么旋转按钮控件不能自动地更新它下面的编辑控件

  如果使用旋转按钮的autu buddy特性, 则必须保证在对话的标记顺序中
buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab Order菜单项(或者按
下Crtl+D)可以设置对话的标签顺序。

40、如何用位图显示下压按钮

  Windows 95按钮有几处新的创建风格,尤其是BS_BITMAP和BS_ICON,要想具
有位图按钮,创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时
要指定BS_BITMAP或BS_ICON风格。
  首先,设置按钮的图标属性。
  然后,当对话初始化时调用CButton: : SetIcon。注意:下例用图标代替位
图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰
色。

BOOL CSampleDlg : : OnInitDialog ( )        
{
CDialog : : OnInitDialog ( ) ;

//set the images for the push buttons .
m_wndButton1.SetIcon (AfxGetApp  ( ) —> LoadIcon (IDI _ IPTION1) )
m_wndButton2.SetIcon (AfxGetApp  ( ) —> LoadIcon (IDI _ IPTION2) )
m_wndButton3.SetIcon (AfxGetApp  ( ) —> LoadIcon (IDI _ IPTION3) )

  return TRUE ;
}

41、如何一个创建三态下压按钮

  可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下
压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即
可。不用任何附加程序就可以成为三态下压按钮。

42、如何动态创建控件

  分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件
事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按
钮控件:
//In class declaration (.H file ).
private :
  CButton* m _pButton ;

//In class implementation (.cpp file ) .
m_pButton =new CButton ;
ASSERT_VALID   (m_pButton);

m_pButton —>Create (_T ("Button Title ") , WS_CHILD |WS_VISIBLE |BS_PUSHBUTTON.
  Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )

43、如何限制编辑框中的准许字符

  如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指
定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制 编辑控
件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽
编辑控件,它是一个很有用的OLE定制控件。
  如果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit 类并处理
WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard 建
立一个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在
OnInitdialog 中调用CWnd: : SubclassDlgItem .

//In your dialog class declaration (.H file )
private :
  CMyEdit m_wndEdit ; // Instance of your new edit control .

//In you dialog class implementation (.CPP file )
BOOL CSampleDialog : : OnInitDialog ( )
{
  …

  //Subclass the edit lontrod .
  m_wndEdit .SubclassDlgItem  (IDC_EDIT,this );

  …
}
  使用ClassWizard处理WM_CHAR消息,计算nChar参量并决定所执行的操作,用
户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母
字符,则调用CWnd ; OnChar,否则不调用OnChar.
//Only display alphabetic dharacters .
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
{
  //Determine if nChar is an alphabetic character .
  if (: : IsCharAlpha  ( ( TCHAR) nChar ) )
      CEdit : : OnChar (nChar, nRepCnt , nFlags );
}
  如果要修改字符,则不能仅仅简单地用修改过的nChar调用CEdit : : OnChar,
然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值 ,这
样是不行的。要修改一个字符,需要首先修改nChar,然后用修改过的nChar调用
CWnd: : DefWindowProc。下例说明了如何将字符转变为大写:

//Make all characters uppercase
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
{
  //Make sure character is uppercase .
  if (: : IsCharAlpha  ( .( TCHAR) nChar)
       nChar=: : CharUpper (nChar ) ;

  //Bypass default OnChar processing and directly call
  //default window proc.
  DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt , nFlags )) ;
}

44、如何改变控件的颜色

  有两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反
射在控件类中指定颜色。
  当控件需要重新着色时,工作框调用父窗口(通常是对话框)的
CWnd: : OnCrtlColor,可以在父窗口类中重置该函数并指定控件的新的绘画属
性。例如,下述代码将对话中的所有编辑控件文本颜色改为红色:
HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)
{
  HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor );

  //Draw red text for all edit controls .
  if (nCtlColor= = CTLCOLOR_EDIT )
     pDC —> SetTextColor (RGB (255 , 0 , 0 , ) ) ;

  return hbr ;
}
  然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,
这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。
  消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理
则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。
  首先,使用ClassWizard 创建一个CListBox 的派生类并为该类添加下述数据
成员。
class CMyListBox ; publilc CListBox
{


private;
  COLORREF m_clrFor ;     // foreground color
  COLORREF m_clrBack ;   //background color
  Cbrush m_brush ;         //background brush


} ;
  其次,在类的构造函数中,初始化数据中。
CMyListBox : : CMyListBox ()
{
  //Initialize data members .
  m_clrFore =RGB (255 , 255 , 0) ;   // yellow text
  m_clrBack=RGB (0 , 0 , 255) ;    // blue background
  m_brush . CreateSolidBrush  (m _clrBack );
}
  最后,使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新
的绘画属性。
HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
{
  pDC—>SetTextColor (m_clrFore);
  pDC—>SetBkColor  (m_clrBack);        
   
  return (HBRUSH) m_brush.GetSafeHandle ()
}
  现在,控件可以自己决定如何绘画,与父窗口无关。

45、当向列表框中添加多个项时如何防止闪烁

  调用CWnd::SetRedraw 清除重画标志可以禁止CListBox(或者窗口)重画。
当向列表框添加几个项时,用户可以清除重画标志,然后添加项,最后恢复重画
标志。为确保重画列表框的新项,调用SetRedraw (TRUE) 之后调用CWnd::Invalidate。

//Disable redrawing.
pListBox->SetRedraw (FALSE);

//Fill in the list box gere

//Enable drwing and make sure list box is redrawn.
pListBox->SetRedraw (TRUE);
pListBox->Invalidate ();

46、如何向编辑控件中添加文本

  由于没有CEdit:: AppendText函数,用户只好自己做此项工作。调用
CEdit:: SetSel移动到编辑控件末尾,然后调用CEdit:: ReplaceSel添加文
本。下例是AppendText 的一种实现方法:

void CMyEdit:: AppendText (LPCSTR pText)
{
   int nLen=GetWindowTextLength ();
   SetFocus ();
   SetSel (nLen, nLen);

   ReplaceSel (pText);
}

47、如何访问预定义的GDI对象

  可以通过调用CDC:: SlectStockObject使用Windows的几个预定义的对象,诸
如刷子、笔以及字体。下例使用了Windows预定义的笔和刷子GDI对象在视窗中画一
个椭圆。
//Draw ellipse using stock black pen and gray brush.
void CSampleView:: OnDraw (CDC* pDC)
{
   //Determine size of view.
   CRect rcView;
   GetClientRect (rcView);

   //Use stock black pen and stock gray brush to draw ellipse.
   pDC->SelectStockObject (BLACK_PEN);
   pDC->SelectStockObject (GRAY_BRUSH)
   //Draw the ellipse.
   pDC->Ellipse (reView);
}
  也可以调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子,下例用背景
色在视窗中画一个椭圆:
void CsampleView:: OnDraw (CDC* pDC)
{
   //Determine size of view.
   CRect rcView;
   GetClientRect (rcView);

   //Use background color for tooltips brush.
   CBrush * pOrgBrush=pDC->SelectObject (
        CBrush::FromHandle (::GetSysColorBrush (COLOR_INFOBK)));

   //Draw the ellipse.
   pDC->Ellipse (rcView);

   //Restore original brush.
   pDC->SelectObject (pOrgBrush);
}

48、如何获取GDI对象的属性信息  

  可以调用GDIObject:: GetObject。这个函数将指定图表设备的消息写入到
缓冲区。下例创建了几个有用的辅助函数。
//Determine if font is bold.
BOOL IsFontBold (const CFont&font)
{
   LOGFONT stFont;
   font.GetObject (sizeof (LOGFONT), &stFont);
   return (stFont.lfBold)? TRUE: FALSE;
}

//Return the size of a bitmap.
CSize GetBitmapSize (const CBitmap&bitmap)
{
   BITMAP stBitmap;
   bitmap.GetObject (sizeof (BITMAP), &stBitmap);
   return CSize (stBitmap.bmWidth, stBitmap. bmHeight);
}

//Create a pen with the same color as a brush.
BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
{
   LOGBRUSH stBrush;
   brush.Getobject (sizeof (LOGBRUSH), &stBrush);
   return pen. Createpen (PS_SOLID, 0, stBrush.ibColor);
}

49、如何实现一个橡皮区矩形

  CRectTracker是一个很有用的类,可以通过调用CRectTracker:: TrackRubberBand
响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。下例表明使用CRectTracker移动
和重置视窗中的蓝色椭圆的大小是很容易的事情。
  首先,在文件档中声明一个CRectTracker数据成员:
class CSampleView : Public CView
{

  …

  public :
       CrectTracker m_tracker;

  …
};
  其次,在文档类的构造函数中初始化CRectTracker 对象:
CSampleDoc:: CSampleDOC ()
{
   //Initialize tracker position, size and style.
   m_tracker.m_rect.SetRect (0, 0, 10, 10);
   m_tracker.m_nStyle=CRectTracker:: resizeInside  |
         CRectTracker:: dottedLine;
}
  然后,在OnDraw函数中画椭圆和踪迹矩形:
void CSampleView:: OnDraw (CDC* pDC)
{
   CSampleDoc* pDoc=GetDocument ();
   ASSERT_VALID (pDoc);

   //Select blue brush into device context.
   CBrush brush (RGB (0, 0, 255));
   CBrush* pOldBrush=pDC->SelectObject (&brush);
 
   //draw ellipse in tracking rectangle.
   Crect rcEllipse;
   pDoc->m_tracker.GetTrueRect (rcEllipse);
   pDC->Ellipse (rcEllipse);

   //Draw tracking rectangle.
   pDoc->m_tracker.Draw (pDC);
   //Select blue brush out of device context.
   pDC->Selectobject (pOldBrush);
}
  最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码
根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。

void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
{
   //Get pointer to document.
   CSampleDoc* pDoc=GetDocument ();
   ASSERT_VALID (pDoc);

   //If clicked on ellipse, drag or resize it. Otherwise create a
   //rubber-band rectangle nd create a new ellipse.
   BOOL bResult=pDoc->m_tracker.HitTest (point)!=
       CRectTracker::hitNothing;

   //Tracker rectangle changed so update views.
   if (bResult)
   {
      pDoc->m_tracker.Track (this,point,TRue);
      pDoc->SetModifiedFlag ();
      pDoc->UpdateAllViews (NULL);
   }
   
   else
      pDoc->m-tracker.TrackRubberBand (this,point,TRUE);

   CView:: onLButtonDown (nFlags,point);
}

50、如何更新翻转背景颜色的文本

  调用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用
CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景
模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新
文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。

void CSampleView:: OnDraw (CDC* pDC)
{
   //Determint size of view.
   CRect rcView;
   GetClientRect (rcVieew);

   //Create sample string to display.
   CString str (_T ("Awesome Shadow Text..."));
   //Set the background mode to transparent.
   pDC->SetBKMode (TRANSPARENT);

   //Draw black shadow text.
   rcView.OffsetRect  (1, 1);
   pDc->SetTextColor (RGB (0, 0, 0));
   pDC->DrawText (str, str.GetLength (), rcView,
       DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    //Draw red  text.
   rcView.OffsetRect  (-1,-1);
   pDc->SetTextColor (RGB (255, 0, 0));
   pDC->DrawText (str, str.GetLength (), rcView,
       DT_SINGLELINE | DT_CENTER | DT_VCENTER);

}

51、如何创建一个具有特定点大小的字体

  可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一
些。可以如下将字体的点转换为字体的高度:

int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72);
  下例创建了一个8点的Apial字体:


CClientDC dc (AqfxGetMainWnd ());

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 ("Arial"));

...
52、如何计算一个串的大小

  函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽
度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字
体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此
得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按
钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时
调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。

LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
{
   //Pass message to window procedure.
   LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr (),
       m_hWnd, GetCurrentMessage () ->message,wParam,lParam);
   //Get title of push button.
   CString strTitle;
   GetWindowText (strTitle);

   //Select current font into device context.
   CDC* pDC=GetDc ();
   CFont*pFont=GetFont ();
   CFont*pOldFont=pDC->SelectObject (pFont);

   //Calculate size of title.
   CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength ());

   //Adjust the button's size based on its title.
   //Add a 5-pixel border around the button.
   SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10,
       SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
   //Clean up.
   pDC->SelectFont (pOldFont);
   ReleaseDC (pDC);

   return bResult;
}

53、如何显示旋转文本

  只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也
支持旋转光栅字体)。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角
度,角度的单位是十分之一度而不是度,例如,ifEscapement为450表示字体旋转
45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成
员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial字体
每间隔15度画一个串。

void CSampleView:: OnDraw (CDC* pDC)
{
   //Determine the size of the window.
   CRect rcClient;
   GetClientRect (rcClient);

   //Create sample string.
   CString str (_T ("Wheeee...I am rotating!"));
   //Draw transparent, red text.
   pDC->SetBkMode (TRANSPARENT);
   pDC->SetTextColor (RGB (255,0,0));

   CFont font;           //font object
   LOGFONT stFont;    //font definition
   //Set font attributes that will not change.
   memset (&stFont, 0, sizeof (LOGFONT));
   stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps (LOGPIXELSY), 72);
   stFont.ifWeight=FW_NORMAL;
   stFont.ifClipPrecision=LCIP_LH_ANGLES;
   strcpy (stFont.lfFaceName, "Arial");

   //Draw text at 15degree intervals.
   for (int nAngle=0; nAngle<3600; nAngle+=150)
{
       //Specify new angle.
       stFont.lfEscapement=nAngle;

       //Create and select font into dc.
       font.CreateFontIndirect (&stfont);
       CFont* pOldFont=pDC->SelectObject (&font);

       //Draw the text.
       pDC->SelectObject (pOldFont);
       font.DelectObjext ();
   }
}

54、如何正确显示包含标签字符的串  

  调用GDI文本绘画函数时需要展开标签字符,这可以通过调用
CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完
成。TabbedTextOut函数允许指定标签位的数组,下例指定每20设备单位展
开一个标签:

void CSampleView:: OnDraw (CDC* pDC)
{
   CTestDoc* pDoc=GetDocument ();
   ASSERT_VALID (pDoC);

   CString str;
   str.format (_T ("Cathy/tNorman/tOliver"));
   int nTabStop=20; //tabs are every 20 pixels
   pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10);
}

55、串太长时如何在其末尾显示一个省略号

  调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取
代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定
DT_END_ELLIPSIS标志并省略号取代串中间的字符。

void CSampleView:: OnDraw (CDC* pDC)
{
   CTestDoc* pDoc=GetDocument ();
   ASSERT_VALID (pDoc);

   //Add ellpsis to end of string if it does not fit
   pDC->Drawtext (CString ("This is a long string"),
       CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS);

   //Add ellpsis to middle of string if it does not fit
   pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath,
       CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS);    
}

56、如何快速地格式化一个CString对象

  调用CString:: format,该函数和printf函数具有相同的参数,下例说明了
如何使用format函数:

//Get size of window.
CRect rcWindow;
GetWindowRect (rcWindow);
//format message string.
CString strMessage;
strMessage.format (_T ("Window Size (%d, %d)"),
              rcWindow.Width (), rcWindow.Height ());

//Display the message.
MessageBox (strmessage);

57、为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态

  需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员
为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者
ON_COMMAND的菜单项。

//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE;

//Now enable the menu item.
CMenu* pMenu=GetMenu ();
ASSERT_VALID (pMenu);

pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED);

58、如何给系统菜单添加一个菜单项

  给系统菜单添加一个菜单项需要进行下述三个步骤:
  首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...
可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000;
  其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用
CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的
菜单项:

int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
   …

   //Make sure system menu item is in the right range.
   ASSERT  (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM);
  ASSERT (IDM-MYSYSITEM<0xF000);

   //Get pointer to system menu.
   CMenu* pSysmenu=GetSystemmenu (FALSE);
   ASSERT_VALID (pSysMenu);
   //Add a separator and our menu item to system menu.
   CString StrMenuItem (_T ("New menu item"));
   pSysMenu->Appendmenu (MF_SEPARATOR);
   pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem);

   …
}
  现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理
WM_SYSCOMMAND消息并检测用户菜单的nID参数:

void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
   //Determine if our system menu item was selected.
   if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
   {
        //TODO-process system menu item
   }
 
   else
        CMDIFrameWnd:: OnSysCommand (nID, lParam);
}
  最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示
一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。

59、如何确定顶层菜单所占据的菜单行数

  这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高
度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;
最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代
码实现。

int CMainFrame:: GetMenuRows ()
{
   CRect rcFrame,rcClient;
   GetWindowRect (rcFrame);
   GetClientRect (rcClient);
   return (rcFrame.Height () -rcClient.Height ()-
         :: GetSystemMetrics (SM_CYCAPTION) -
         (:: getSystemMetrics (SM_CYFRAME) *2)) /
         :: GetSystemMetrics (SM_CYMENU);
}

60、在用户环境中如何确定系统显示元素的颜色

  调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何
在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。

void CMiniFrameWnd:: OnNcPaint ()
{
   …
   dc.SetTextColor (:: GetSysColor (m_bActive ?
       COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
   …
}


61、如何查询和设置系统参数

  在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可
以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体
以及桌面覆盖位图等等。

//Create a font that is used for icon titles.
LOGFONT stFont;
:: SystemParametersInfo (SPIF_GETICONTITLELOGFONT,
   sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE);
m_font.CreateFontIndirect (&stFont);

//Change the wallpaper to leaves.bmp.
:: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0,
     _T (" forest.bmp"), SPIF_UPDATEINIFILE);

62、如何使用一个预定义的Windows光标

  调用CWinApp:: LoadStandardCursor并传送光标标识符。
   BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
{
   //Display wait cursor if busy.
   if (m_bBusy)
   {
       SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));
       return TRUE;
   }

   return CDialog:: OnSetCursor (pWnd. nHitTest,message);
}

63、如何确定当前屏幕分辨率

  调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如
标题大小、边界大小以及滚动条大小等等。

//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
   GetSystemMetrics (SM_CYSCREEN));

64、如何检索原先的Task Manager应用程序使用的任务列表

  原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口
必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以
检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner
可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。

void GetTadkList (CListBox&list)
{
   CString strCaption;        //Caption of window.

   list.ResetContent ();       //Clear list box.

   //Get first Window in window list.
   ASSERT_VALID (AfxGetMainWnd ());
   CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST);

   //Walk window list.
   while (pWnd)
   {
       // I window visible, has a caption, and does not have an owner?
       if (pWnd ->IsWindowVisible () &&
          pWnd ->GetWindowTextLength () &&! pWnd ->GetOwner ())
       {
          //Add caption o window to list box.
          pWnd ->GetWindowText  (strCaption);
          list.AddString (strCaption);
       }
       //Get next window in window list.
       pWnd=pWnd->GetWindow (GW_HWNDNEXT);
   }
}

65、如何确定Windows和Windows系统目录

  有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,
下例说明了如何使用这两个函数:

TCHAR szDir [MAX_PATH];
//Get the full path of the windows directory.
:: GetWindowsDirectory (szDir, MAX_PATH);
TRACE ("Windows directory %s/n", szDir);
//Get the full path of the windows system directory.
:: GetSystemDirectory (szDir, MAX_PATH);
TRACE ("Windows system directory %s/n", szDir);

66、在哪儿创建临文件

  调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径
检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。
下例说明了如何创建一个临时文件。

   //get unique temporary file.
   CString strFile;
   GetUniqueTempName (strFile);

   TRY
   {
      //Create file and write data.Note that file is closed
      //in the destructor of the CFile object.
      CFile file (strFile,Cfile:: modeCreate | Cfile:: modeWrite);

      //write data
   }

   CATCH (CFileException, e)
   {
      //error opening file
   }
   END_CATCH


Void GetuniqueTempName (CString& strTempName)
{
   //Get the temporary files directory.
   TCHAR szTempPath  [MAX_PATH];
   DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);
   ASSERT (dwResult);

   //Create a unique temporary file.
   TCHAR szTempFile  [MAX_PATH];
   UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile);
   ASSERT (nResult);

   strTempName=szTempFile;
}

67、如何访问桌面窗口

  静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC
函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。

void CFrameWnd::BeginModalState ()
{
   …

   //first count all windows that need to be disabled
   UINT nCount=0;
   HWND hWnd=:: GetWindow (:: GetDesktopWindow (), GW_CHILD);
   while (hWnd!=NULL)
   {
      if (:: IsWindowEnabled (hwnd) &&
          CWnd::FromHandlePermanent (hWnd)!=NULL &&
          AfxIsDescendant (pParent->m_hWnd, hWnd) &&
          :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
      {
          ++nCount;
      }
      hWnd=:: GetWindow (hWnd, GW_HWNDNEXT);
   }    
   …
}

 

 
编辑  发贴时间2002/03/12 12:41pm IP: 已设置保密
  

 
 
 该主题只有一页<script language="JavaScript" type="text/javascript"> </script>

快速回复主题:vc编程指南67篇
输入用户名和密码:用户名: 没有注册?  密码: 忘记密码?

显示您的签名?
有回复时使用邮件通知您?
使用表情字符转换?
 预览?是 

 
 顶端主题管理精华 | 固顶 | 取消固顶 | 提升 | 锁定 | 解锁 | 删除 | 移动 

 

 


<script type="text/javascript"> var tc_user="cnleo"; var tc_class="2"; var tc_union="*"; var tc_type="1"; var tc_user; if (tc_user==null) tc_user=""; _dw(''); function _dw(string) {document.write(string);} </script> © 版权所有,瑞软软件
本论坛言论纯属发表者个人意见,与 瑞软论坛 立场无关
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VC++编程指南(中文版),不错的一本电子书。啥也不说了,直接看内容预览: 第一课 Windows编程和面向对象技术   1.1 Windows发展历史   1.2 Windows操作系统特点   1.3 Windows应用程序设计的特点   1.4 Windows应用程序的开发工具   1.5 面向对象和Windows编程 第二课 使用Visual C++ 5.0   2.1 Visual C++可视化集成开发环境   2.2 创建、组织文件、工程和工作区   2.3 WIN32开发   2.4 MFC编程   2.5 移植C Windows程序到MFC   2.6 Visual C++5.0新特性 第三课 窗口、菜单与消息框   3.1 编写第一个窗口程序   3.2 AppWizard所创建的文件   3.3 编译和链接Hello程序   3.4 应用程序执行机制   3.5几种窗口类型   3.6 使用菜单   3.7 更新命令用户接口(UI)消息   3.8 快捷菜单 第四课 工具条和状态栏   4.1 工具条的可视化设计   4.2 工具条的编程技术   4.3 状态栏的设计与实现 第五课 对话框   5.1对话框和控件的基本概念   5.2 对话框模板的设计   5.3 对话框类的设计   5.4 非模态对话框   5.5 标签式对话框   5.6 公用对话框   5.7 小结 第六课 控件 6.1 传统控件   6.2 新型Win32控件   6.3 控件的技术总结   6.4 在非对话框窗口中使用控件   6.5 如何设计新的控件   6.6 小结 第七课 文档视结构   7.1 文档/视图概念   7.2 文档视结构程序实例   7.3 让文档视结构程序支持卷滚   7.4 定制串行化   7.5 不使用串行化的文档视结构程序   7.6 小 结 第八课 多文档界面MDI   8.1多文档界面窗口   8.2图形设备接口(GDI)   8.3 绘图程序   8.4访问当前活动视图和活动文档   8.5分隔视图   8.6打印和打印预览   8.7支持多个文档类型的文档视结构程序   8.8防止应用程序运行时创建空白窗口   8.9小结 第九课 创建用户模块   9.1用户模块   9.2静态连接库   9.3创建动态库   9.4小结 第十课 数据库编程   10.1 数据库的基本概念   10.2 ODBC基本概念   10.3 MFC的ODBC类简介   10.4 CDatabase类   10.5 CRecordset类   10.6 CRecordView类   10.7 编写Enroll数据库应用例程   10.8 DAO和DAO类   10.9 自动注册DSN和创建表   10.10 小结 第十一课 多媒体编程   11.1 调色板   11.2位图   11.3依赖于设备的位图(DDB)   1.4与设备无关的位图(DIB)   11.5动画控件   11.6媒体控制接口(MCI).   11,7小结  第十二章 多线程与串行通信   12.1 多任务、进程和线程   12.2 线程的同步   12.3 串行通信与重叠I/O   12.4 一个通信演示程序   12.5 小结
第2章 控件应用 75 2.1 按钮控件典型实例 76 实例049 AVI动画按钮 76 实例050 GIF动画按钮 78 实例051 图文按钮 80 实例052 不规则按钮 82 实例053 热点按钮 84 2.2 编辑框控件典型实例 86 实例054 为编辑框设置新的系统菜单 87 实例055 为编辑框控件添加列表选择框 88 实例056 多彩边框的编辑框 90 实例057 改变编辑框文本颜色 91 实例058 不同文本颜色的编辑框 92 实例059 位图背景编辑框 93 2.3 静态文本控件典型实例 94 实例060 电子计时器 94 实例061 使用静态文本控件设计群组框 96 实例062 制作超链接控件 97 2.4 列表框控件典型实例 99 实例063 利用列表框控件实现标签式数据选择 99 实例064 具有水平滚动条的列表框控件 100 实例065 列表项的提示条 101 实例066 位图背景列表框控件 104 2.5 组合框控件典型实例 105 实例067 将数据表中的字段添加到组合框控件 106 实例068 带查询功能的组合框控件 107 实例069 自动调整组合框的宽度 108 实例070 颜色组合框 109 实例071 多列显示的组合框 111 实例072 带图标的组合框 113 实例073 显示系统盘符组合框 114 2.6 列表视图控件典型实例 115 实例074 Windows资源管理器 115 实例075 利用列表视图控件浏览数据 118 实例076 利用列表视图控件制作导航界面 120 实例077 在列表视图中拖动视图项 121 实例078 具有排序功能的列表视图控件 123 实例079 具有文本录入功能的列表视图控件 126 实例080 使用列表视图设计登录界面 128 2.7 树视图控件典型实例 129 实例081 多级数据库树状结构数据显示 129 实例082 节点拖动功能的树控件 131 实例083 带复选功能的树状结构 134 实例084 三态效果树控件 135 实例085 修改树控件节点连线颜色 137 实例086 位图背景树控件 138 实例087 显示磁盘目录 140 实例088 树型提示框 141 2.8 RichEdit控件典型实例 143 实例089 利用RichEdit显示Word文档 143 实例090 利用RichEdit控件实现文字定位与标识 144 实例091 利用RichEdit控件显示图文数据 146 实例092 在RichEdit中显示不同字体和颜色的文本 148 实例093 在RichEdit中显示GIF动画 149 2.9 滚动条控件典型实例 157 实例094 自定义滚动条控件 157 2.10 进度条控件典型实例 162 实例095 进度条百分比显示 162 实例096 渐变颜色的进度条 164 2.11 工具提示控件典型实例 165 实例097 应用工具提示控件 165 2.12 滑块控件典型实例 167 实例098 使用滑块控件设置颜色值 167 实例099 绘制滑块控件 168 2.13 标签控件典型实例 170 实例100 应用标签控件 170 实例101 自定义标签控件 172 2.14 控件数组典型实例 175 实例102 向窗体中动态添加控件 175 实例103 公交线路模拟 177
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值