|
Visual C++编程技巧83例
Visual C++编程技巧之四
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用 ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage 来确定所选中的菜单项。 viod CMainFrame : : OnCommmonMenuHandler ( ) { //Display selected menu item in debug window . TRACE ("Menu item %u was selected . \n" , GetCruuentMessage ( ) —> wParam ); } 可以使用新的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 ; } 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条 有一个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); 如果设置了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 ); } 工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,例子如下: int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct ) { … // Set the caption of the toolbar . m_wndToolBar.SetWindowText (_T "Standdard"); 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 ) ; } 这要归功于Win 32先进的静态控件和Microsoft的资源编辑器, 在对话框中显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。 调用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 ); } |