Visual C++编程技巧 (1)

导读:
  Visual C++编程技巧 (这些问题可能在CSDN里经常被人问到,现在列出来供大家参考,欢迎大家一起来完善之)
  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, shellexecute,createprocess可以使用。
  WinExec 最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说
  一下,比如泥用 SW_SHOWMAXMIZED 方式去加栽一个无最大化按钮的 程序,呵呵就是
  Neterm,calc 等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。
  ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的 Example就是直接打开
  c:/temp/1.txt,而不用加栽与 txt 文件关联的应用程序,很多安装程序完成后都会打开
  一个窗口,来显示Readme or Faq,偶猜就是这么作的啦.
  ShellExecute(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. 如何改变窗口的图标?
  向窗口发送 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风格将创建一个具-_Âu有空标题的窗口,可以调用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 =GetRValue (color);
  BYTE byGreen = GetGValue (color);
  BYTE byBlue = GetBValue (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 ;
  } //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 )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值