第2章控件应用

2.1 按钮控件典型实例

个性化的按钮可以美化界面,从而吸引更多的用户,本节将介绍创建各种不同风格的按钮的方法。

实例040 AVI动画按钮

本实例是一个人性化的实例

实例位置:光盘\mingrisoft\02\040

实例说明

在开发程序的时候,经常会用到个性化按钮来美化程序界面,其中,能播放AVI动画的按钮会吸引更多年轻人的目光。运行程序,当鼠标光标在控件上方移动时,按钮将产生动画效果,效果如图2.1所示。

图2.1 AVI动画按钮

技术要点

本实例主要是通过使用动画控件和设置鼠标的消息响应来实现的。

首先通过CAnimateCtrl类来创建和使用动画控件,CAnimateCtrl类的方法如下所示。

(1)Open方法。从一个文件或资源打开一个AVI文件,并显示第一帧。语法如下:

            BOOL Open( LPCTSTR lpszFileName );
            BOOL Open( UINT nID );

参数说明:

● lpszFileName:AVI文件名。

● nID:资源ID。

(2)Play方法。播放AVI文件。语法如下:

BOOL Play( UINT nFrom, UINT nTo, UINT nRep );

参数说明:

● nFrom:起始帧索引。

● nTo:结束帧索引。

● nRep:是否循环播放。

(3)Seek方法。显示AVI文件中的指定帧,语法如下:

BOOL Seek( UINT nTo );

参数说明:

● nTo:指定帧索引。

(4)Stop方法。停止播放AVI文件,语法如下:

BOOL Stop( );

(5)Close方法。关闭已打开的AVI文件,语法如下:

BOOL Close( );

设置鼠标的WM_MOUSEMOVE消息,消息响应函数原型如下:

afx_msg void OnMouseMove(UINT nFlags, CPoint point);

参数说明:

● nFlags:指示是否按下了各种虚键。

● point:指出光标的横坐标和纵坐标。

实现过程

(1)新建一个基于对话框的应用程序。

(2)向窗体中添加一个按钮控件,用鼠标右键单击按钮控件,在弹出的菜单中选择Properties选项,选择Owner Draw属性。

(3)单击Insert/Resource菜单项,在打开的Insert Resource对话框中单击Import按钮,添加一个AVI文件,在弹出的Custom Resource Type对话框中定制新的资源类型。

(4)以CButton类为基类派生一个CButtonAvi类。

(5)重载CButtonAvi类的DrawItem虚方法,在该方法中创建播放AVI的动画控件,代码如下:

        void CButtonAvi::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
        {
          CRect rect;
          GetClientRect(rect);                                   //获得按钮的客户区域
          if (!::IsWindow(m_Animate))
          {
            m_Animate.Create(WS_CHILD|WS_VISIBLE,rect,this,0);   //创建动画控件
            m_Animate.Open(m_id);                                //打开AVI文件资源
            m_Animate.GetClientRect(rect);                       //获得动画控件的客户区域
            VERIFY(SetWindowPos(NULL,0,0, rect.Width()+2, rect.Height()+2,SWP_NOMOVE));//设置按钮控件显示位置
            m_Animate.MoveWindow(rect);                          //移动动画控件位置
          }
          CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);        //获得按钮控件设备上下文
          UINT State=lpDrawItemStruct->itemState;                 //获得按钮控件状态
          DrawButton(pDC,State,rect);                            //调用自定义函数绘制按钮
        }

(6)添加自定义DrawButton,在该函数中绘制按钮控件,代码如下:

        void CButtonAvi::DrawButton(CDC *pDC,UINT nState,CRect rect)
        {
          COLORREF UpCol,DownCol;
          if((nState&ODS_SELECTED)==ODS_SELECTED)             //选中状态
          {
            UpCol=RGB(0,0,0);                                 //设置上边颜色为黑色
            DownCol=RGB(0,0,0);                               //设置下边颜色为黑色
            m_play = false;
          }
          else if((nState&ODS_DISABLED)!=ODS_DISABLED)         //如果不可用
          {
            UpCol=RGB(255,255,255);                           //设置上边颜色为白色
            DownCol=RGB(128,128,128);                         //设置下边颜色为灰色
          }
          //画按钮的左边和上边
          CPen pen1,pen2;
          pen1.CreatePen(PS_SOLID,3,UpCol);                   //创建画笔
          pDC->SelectObject(&pen1);                           //选入画笔
          pDC->MoveTo(0,rect.Height()-1);
          pDC->LineTo(0,0);
          pDC->LineTo(rect.Width()-1,0);
          //画按钮的右边和下边
          pen2.CreatePen(PS_SOLID,2,DownCol);                 //创建画笔
          pDC->SelectObject(&pen2);                           //选入画笔
          pDC->MoveTo(rect.Width()-1,0);
          pDC->LineTo(rect.Width()-1,rect.Height()-1);
          pDC->LineTo(0,rect.Height()-1);
          pen1.DeleteObject();
          pen2.DeleteObject();
        }

(7)设置鼠标的WM_MOUSEMOVE消息,在该消息的响应函数中捕获鼠标光标位置,判断是否播放AVI文件,代码如下:

        void CButtonAvi::OnMouseMove(UINT nFlags, CPoint point)
        {
          ClientToScreen(&point);                    //将鼠标光标位置转换为屏幕坐标
          CRect rc;
          GetWindowRect(rc);                         //获得按钮窗口的区域
          if(rc.PtInRect(point))                     //判断鼠标光标是否在按钮区域内
          {
            if (::IsWindow(m_Animate) && !m_play)
            {
            m_Animate.Play(0,-1,1);               //播放AVI动画
            m_play = true;
            SetCapture();                         //捕获鼠标
            }
            }
              else
              {
            m_play = false;
            ReleaseCapture();                     //释放鼠标
            }
            CButton::OnMouseMove(nFlags, point);
        }

举一反三

根据本实例,读者可以:

开发AVI文件播放器。

实例041 GIF动画按钮

本实例是一个人性化的实例

实例位置:光盘\mingrisoft\02\041

实例说明

通常情况下,动画按钮会比其他形式的按钮更加吸引人,可是Visual C++中的动画控件只能显示简单的AVI动画,显然这并不能满足用户的要求。本实例将创建一个可以显示GIF动画的按钮,运行程序,效果如图2.2所示。

图2.2 GIF动画按钮

技术要点

本实例使用API函数FindResource、SizeofResource和LoadResource来装载GIF资源。

(1)FindResource函数:该函数确定指定模块中指定类型和名称的资源所在的位置。函数原型如下:

HRSRC FindResource(HMODULE hModule,LPCTSTR lpName,LPCTSTR lpType);

参数说明:

● hModule:处理包含资源的可执行文件的模块。NULL值指定模块句柄指向操作系统,通常情况下创建最近过程的相关位图文件。

● lpName:指定资源名称。

● lpType:指定资源类型。

(2)SizeofResource函数:该函数返回指定资源字节数大小。函数原型如下:

DWORD SizeofResource(HMODULE hModule,HRSRC hReslnfo);

参数说明:

● hModule:包含资源的可执行文件模块的句柄。

● hReslnfo:资源句柄,此句柄必须由函数FindResource或FindResourceEx来创建。

(3)LoadResource函数:该函数装载指定资源到全局存储器。函数原型如下:

HGLOSAL LoadResouare(HMODULE hModule,HRSRC hReslnfo);

参数说明:

● hModule:处理包含资源的可执行文件的模块句柄。若hModule为NULL,系统从当前过程的模块中装载资源。

● hReslnfo:将被装载资源的句柄,它必须由函数FirtdResource或FindResourceEx创建。

实现过程

(1)新建一个基于对话框的应用程序。

(2)向窗体中添加一个按钮控件,选择Owner Draw属性。

(3)以CButton类为基类创建一个按钮类CButtonGif。

(4)主要程序代码如下:

        //显示GIF动画
        static UINT GifThread(LPVOID GifDC)
        {
          CDC* pDC = (CDC*)GifDC;
          HINSTANCE hAndle = ::AfxGetResourceHandle();
          HRSRC hRsrc=::FindResource(hAndle,MAKEINTRESOURCE(IDR_GIF1),"GIF"); //查找资源位置
          DWORD word=::SizeofResource(hAndle,hRsrc);                          //获得资源大小
          BYTE*lpBy=(BYTE*)LoadResource(hAndle,hRsrc);                       //加载资源
          BYTE* pByte[200];
          DWORD nu[200];
          int num = 0;
          DWORD firstLocation = 0;
          for(DWORD i=0;i<word;i++)
          {
            if(lpBy[i]==0x2c)                                                //如果是图像分隔符
            {
            if(num==0)
            {
                firstLocation = i;
            }
            pGif nImage = (pGif)&lpBy[i+1];
            DWORD number = 1+sizeof(Gif);
            while(lpBy[i+number]!=0)
            {
                number = number+(DWORD)lpBy[i+number]+1;
            }
            number++;
            pByte[num] = new BYTE[number];
            for(DWORD n=0;n<number;n++)
            {
                *(BYTE*)(pByte[num]+n) = lpBy[i+n];
            }
            nu[num] = number;
            i = i+number-1;
            num++;
            }
          }
          while(1)
          {
            for(int m=0;m<num;m++)
            {
            DWORD dWord;
            VirtualProtect(lpBy,word,PAGE_READWRITE,&dWord);
            for(DWORD n=0;n<nu[m];n++)
            {
            lpBy[firstLocation+n] = *(BYTE*)(pByte[m]+n);
            }
            VirtualProtect(lpBy,word,dWord,NULL);
            CMemFile mfile(lpBy,word);                                         //构造驻留文件类对象
            CArchive aRc(&mfile,CArchive::load|CArchive::bNoFlushOnDelete);    //构造CArchive对象
            CArchiveStream aRcstream(&aRc);
            CComQIPtr<IPicture> m_picture;
            OleLoadPicture((LPSTREAM)&aRcstream,0,false,IID_IPicture,(void**)&m_picture);
            long x,y;
            m_picture->get_Width(&x);
            m_picture->get_Height(&y);
            CSize size(x,y);
            pDC->HIMETRICtoDP(&size);
            CRect rect;
            m_picture->Render(*pDC,0,0,size.cx,size.cy,0,y,x,-y,&rect);
            Sleep(30);
            }
          }
          return 1;
        }
        //播放GIF动画
        void CButtonGif::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
        {
            CDC*pDC=this->GetDC();                      //获得设备上下文指针
            if(!m_play)
            {
            AfxBeginThread(GifThread,(LPVOID)pDC);      //开启线程
            m_play = true;
            }
            CRect rect(-1,-1,180,59);
            UINT State=lpDrawItemStruct->itemState;      //设置按钮状态
            DrawButton(pDC,State,rect);                 //绘制按钮
        }

举一反三

根据本实例,读者可以:

开发GIF播放器。

实例042 图文按钮

本实例是一个提高效率、人性化的程序

实例位置:光盘\mingrisoft\01\042

实例说明

通常情况下,MFC提供的按钮CButton并不能显示图标。如果在应用程序的按钮中显示一个图标,将使程序更加美观。运行程序,图文按钮效果如图2.3所示。

图2.3 图文按钮

技术要点

在Visual C++中,可以通过改写CButton的DrawItem方法实现自定义按钮的绘制。在按钮中绘制图标主要使用了DrawItem方法中lpDrawItemStruct参数的hDC成员来实现。DrawItem方法是一个虚拟方法,用于绘制控件的外观。当按钮控件包含BS_OWNERDRAW风格时,应用程序将自动调用DrawItem方法绘制按钮。语法如下:

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );

参数说明:

● lpDrawItemStruct:是一个DRAWITEMSTRUCT结构指针。其结构成员如下。

● CtlType:表示控件的类型。可选值如下。

■ ODT_BUTTON:按钮。

■ ODT_COMBOBOX:组合框。

■ ODT_LISTBOX :列表框。

■ ODT_MENU :菜单。

■ ODT_LISTVIEW:列表视图。

■ ODT_STATIC:静态控件。

■ ODT_TAB:标签控件。

● CtlID:表示控件ID。

● ItemID:表示菜单项ID或列表框、组合框中的项目索引。

● ItemAction:表示绘画的动作。可选值如下。

■ ODA_DRAWENTIRE:整个控件需要被绘制时设置该标识。

■ ODA_FOCUS:控件获得或失去焦点时设置该标识。

■ ODA_SELECT:表示控件处于选中状态时设置该标识。

● ItemState:表示需要绘画的状态。可选值如下。

■ ODS_CHECKED:菜单项被选中。

■ ODS_DISABLED:控件不可用。

■ ODS_FOCUS:控件获得焦点。

■ ODS_GRAYED:控件处于灰色状态,只用于菜单控件。

■ ODS_SELECTED:控件被选中。

■ ODS_COMBOBOXEDIT:组合框中编辑控件的文本被选中。

■ ODS_DEFAULT:默认状态。

■ HwndItem:表示控件的句柄。

■ HDC:控件的画布句柄。

■ RcItem:控件的矩形区域。

■ ItemData:控件的附加信息。

实现过程

(1)新建一个基于对话框的应用程序。

(2)向窗体中添加4个按钮控件,全都选择Owner Draw属性,向工程中添加4个ICO图标资源。

(3)以CButton类为基类创建一个按钮类CImageButton。

(4)主要程序代码如下:

        void ImageButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
        {
          CDC dc ;
          dc.Attach(lpDrawItemStruct->hDC);                          //获得设备上下文
          if (m_pImagelist)
          {
            UINT state=lpDrawItemStruct->itemState;                   //获取状态
            UINT action = lpDrawItemStruct ->itemAction;
            //获取图像列中图像的大小
            IMAGEINFO imageinfo;
            m_pImagelist->GetImageInfo(m_ImageIndex,&imageinfo);
            CSize imagesize;
            imagesize.cx = imageinfo.rcImage.right-imageinfo.rcImage.left;
            imagesize.cy = imageinfo.rcImage.bottom - imageinfo.rcImage.top;
            //在按钮垂直方向居中显示图标
            CRect rect;
            GetClientRect(rect);
            CPoint point;
            point.x = 5;
            point.y = (rect.Height() - imagesize.cy)/2;
            m_pImagelist->Draw(&dc,m_ImageIndex,point,ILD_NORMAL|ILD_TRANSPARENT);//绘制图标
            //按钮被选中或者获得焦点时
            if ((state&ODS_SELECTED)||(state&ODS_FOCUS))
            {
            CRect focusRect(rect);                                    //焦点矩形
            focusRect.DeflateRect(4,4,4,4);                          //设置区域
            CPen pen(PS_DASHDOTDOT,1,RGB(0,0,0));                     //创建画笔
            CBrush brush;
            brush.CreateStockObject(NULL_BRUSH);                     //创建画刷
            dc.SelectObject(&brush);                                 //选入画刷
            dc.SelectObject(&pen);                                   //选入画笔
            //绘制焦点矩形
            dc.DrawFocusRect(focusRect);
            //绘制立体效果
            dc.DrawEdge(rect,BDR_RAISEDINNER|BDR_RAISEDOUTER,BF_BOTTOMLEFT|BF_TOPRIGHT);
            //获得焦点时绘制黑色边框
            dc.Draw3dRect(rect,RGB(51,51,51),RGB(0,0,0));
            }
            else  //默认情况下
            {
            CRect focusRect(rect);                                    //焦点矩形
            focusRect.DeflateRect(4,4,4,4);
            CPen pen(PS_DOT,1,RGB(192,192,192));                      //创建画笔
            CBrush brush;
            brush.CreateStockObject(NULL_BRUSH);                     //创建画刷
            dc.SelectObject(&brush);
            dc.SelectObject(&pen);
            dc.Rectangle(focusRect);                                       //绘制矩形
            //绘制立体效果
            dc.DrawEdge(rect,BDR_RAISEDINNER|BDR_RAISEDOUTER,BF_BOTTOMLEFT|BF_TOPRIGHT);
            }
            if (IsPressed) //在按钮被按下时绘制按下效果
            {
            CRect focusRect1(rect);
            focusRect1.DeflateRect(4,4,4,4);
            dc.DrawFocusRect(focusRect1);                                  //绘制焦点矩形
            dc.DrawEdge(rect,BDR_SUNKENINNER |BDR_SUNKENOUTER ,BF_BOTTOMLEFT|BF_TOPRIGHT);
            dc.Draw3dRect(rect,RGB(51,51,51),RGB(0,0,0));                  //绘制3D边框
            }
                  CString text;
                  GetWindowText(text);                                     //获得按钮文本
            rect.DeflateRect(point.x+imagesize.cx+2,0,0,0);                //设置文本显示区域
            dc.SetBkMode(TRANSPARENT);                                     //设置背景透明
            dc.DrawText(text,rect,DT_LEFT|DT_SINGLELINE|DT_VCENTER);  //绘制按钮文本
            }
            }

举一反三

根据本实例,读者可以:

实现位图按钮。

实例043 热点按钮

本实例是一个提高效率、人性化的程序

实例位置:光盘\mingrisoft\02\043

实例说明

通常情况下,人们的眼睛会追随动态的东西,所以当鼠标滑过热点按钮时,按钮发生变化,自然就可以引起用户的注意了,热点按钮就可以起到这样的效果。运行程序,热点按钮效果如图2.4所示。

图2.4 热点按钮

技术要点

要实现具有热点效果的按钮控件,主要用到GetCursorPos方法和PtInRect方法。

(1)GetCursorPos方法。GetCursorPos方法用于获得鼠标的当前坐标,语法如下:

BOOL GetCursorPos( LPPOINT lpPoint );

参数说明:

● lpPoint:指向鼠标当前位置的POINT结构指针。

(2)PtInRect方法。PtInRect方法用于判断指定点是否在指定矩形区域内,语法如下:

BOOL PtInRect( POINT point ) const;

参数说明:

● point:包含一个POINT结构或CPoint对象。

实现过程

(1)新建一个基于对话框的应用程序。

(2)以CButton类为基类派生一个CButtonHot类。

(3)向工程中导入4个BMP位图资源,并向对话框中添加2个按钮控件,为按钮控件选择Owner Draw属性。

(4)在CButtonHot类的头文件中声明变量,代码如下:

            UINT m_DownPic;                       //鼠标按下时显示的图片
            UINT m_NomalPic;                      //正常情况下显示的图片
            UINT m_EnablePic;                     //按钮失效时显示的图片
            UINT m_MovePic;                       //鼠标经过按钮时显示的图片
            BOOLm_IsInRect;                       //是否在按钮区域内

(5)在CButtonHot类的构造函数中初始化变量,代码如下:

        CButtonHot::CButtonHot()
        {
            m_DownPic    =IDB_BUTTONDOWN;       //鼠标按下时显示的图片
            m_NomalPic   =IDB_BUTTONUP;         //正常情况下显示的图片
            m_EnablePic  =IDB_BUTTONENABLE;     //按钮失效时显示的图片
            m_MovePic    =IDB_BUTTONMOVE;       //鼠标经过按钮时显示的图片
            m_IsInRect   =FALSE;
        }

(6)在CButtonHot类中,添加自定义函数DrawBK,该函数用于绘制按钮控件的背景位图,代码如下:

        void CButtonHot::DrawBK(CDC *pDC, UINT ResID)
        {
            CDC memDC;
            memDC.CreateCompatibleDC(pDC);                                //创建兼容的设备上下文
            CRect rect;                                                    //声明区域对象
            GetClientRect(rect);                                          //获得编辑框客户区域
            CBitmap bitmap;
            BITMAP bitStruct;
            bitmap.LoadBitmap(ResID);                                     //加载位图资源
            bitmap.GetBitmap(&bitStruct);                                 //获得位图资源信息
            memDC.SelectObject(&bitmap);                                  //选入位图对象
            pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,bitStruct.bmWidth
                ,bitStruct.bmHeight,SRCCOPY);                             //绘制背景
            memDC.DeleteDC();                                             //删除设备上下文
            bitmap.DeleteObject();                                        //删除位图对象
        }

(7)在CButtonHot类中,重载DrawItem虚函数,在该虚函数中根据按钮状态绘制按钮的背景图片,代码如下:

        void CButtonHot::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
        {
            CDC dc;                                                        //声明设备上下文
            dc.Attach(lpDrawItemStruct->hDC);                             //获得绘制按钮设备上下文
            UINT state=lpDrawItemStruct->itemState;                        //获取状态
            CRect rect;                                                    //声明区域对象
            GetClientRect(rect);                                          //获得编辑框客户区域
            CString text;                                                  //声明字符串变量
            GetWindowText(text);                                          //获得控件显示文本
            if(state&ODS_DISABLED)                                        //如果不可用
            {
                DrawBK(&dc,m_EnablePic);                                  //绘制不可用背景
                dc.SetTextColor(RGB(0,0,0));                              //设置文本颜色
            }
            else if(state&ODS_SELECTED)                                    //如果选择按钮
            {
                DrawBK(&dc,m_DownPic);                                    //绘制选择状态背景
                dc.SetTextColor(RGB(0,0,255));                            //设置文本颜色
            }
            else if(m_IsInRect==TRUE)                                      //如果是热点
            {
                DrawBK(&dc,m_MovePic);                                    //绘制热点状态背景
                dc.SetTextColor(RGB(255,0,0));                            //绘制文本颜色
            }
            else                                                          //默认情况下
            {
                DrawBK(&dc,m_NomalPic);                                   //绘制默认按钮状态背景
                dc.SetTextColor(RGB(0,0,0));                              //绘制文本颜色
            }
            if(state&ODS_FOCUS)                                           //如果获得焦点
            {
                CRect FocTect(rect);                                       //构造焦点区域
                FocTect.DeflateRect(2,2,2,2);                             //设置焦点区域大小
                dc.DrawFocusRect(&FocTect);                               //绘制焦点框
                lpDrawItemStruct->itemAction = ODA_FOCUS ;
            }
            dc.SetBkMode(TRANSPARENT);                                    //设置背景透明
            dc.DrawText(text,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);   //绘制按钮文本
        }

(8)在CButtonHot类中,重载PreSubclassWindow虚函数,在该虚函数中设置定时器,代码如下:

        void CButtonHot::PreSubclassWindow()
        {
            SetTimer(1,10,NULL);                                       //设置定时器
            CButton::PreSubclassWindow();
        }

(9)在CButtonHot类中,处理按钮的WM_TIMER事件,在该事件的处理函数中判断按钮是否为热点效果,代码如下:

        void CButtonHot::OnTimer(UINT nIDEvent)
        {
            CPoint point;                                        //声明Cpoint变量
            GetCursorPos(&point);                               //获得鼠标光标位置
            CRect rcWnd;                                         //声明区域对象
            GetWindowRect(&rcWnd);                              //获得按钮区域
            if(rcWnd.PtInRect(point))                           //判断鼠标光标是否在按钮上
            {
                  if(m_IsInRect==TRUE)                          //判断鼠标光标是否一直在按钮上
                    goto END;                                    //跳转到标记
                  else                                          //鼠标光标移动到按钮上
                  {
                    m_IsInRect=TRUE;                            //设置m_IsInRect变量值
                    Invalidate();                               //重绘按钮
                  }
            }
            else                                                //不在按钮区域内
            {
                  if(m_IsInRect==FALSE)                         //判断鼠标光标一直在按钮外
                    goto END;                                    //跳转到标记
                  else                                          //鼠标光标移动到按钮外
                  {
                    Invalidate();                               //重绘按钮
                    m_IsInRect=FALSE;                           //设置m_IsInRect变量值
                  }
            }
        END:CButton::OnTimer(nIDEvent);                         //设置标记,调用基类方法
        }

(10)在CButtonHot类中,处理按钮的WM_ERASEBKGND事件,在该事件的处理函数中禁止调用基类方法重绘按钮控件,代码如下:

        BOOL CButtonHot::OnEraseBkgnd(CDC* pDC)
        {
            return true;//CButton::OnEraseBkgnd(pDC);              //不调用基类方法
        }

(11)在CButtonHot类中,重载PreTranslateMessage虚函数,在该函数中截获回车键按下和释放事件,并修改为鼠标左键的按下和释放事件,代码如下:

        BOOL CButtonHot::PreTranslateMessage(MSG* pMsg)
        {
            //截获回车键的按下事件
            if(pMsg->hwnd==this->GetSafeHwnd()&&pMsg->message==WM_KEYDOWN && pMsg->wParam==13)
            {
                  pMsg->lParam  =0;
                  pMsg->message=WM_LBUTTONDOWN;          //改为鼠标左键的按下事件
            }
            //截获回车键的释放事件
            if(pMsg->hwnd==this->GetSafeHwnd()&&pMsg->message==WM_KEYUP && pMsg->wParam==13)
            {
                  pMsg->lParam  =0;
                  pMsg->message=WM_LBUTTONUP;            //改为鼠标左键的释放事件
            }
            return CButton::PreTranslateMessage(pMsg);
        }

举一反三

根据本实例,读者可以:

根据按钮状态显示不同的位图。