MFC学习之第四天 (一)

本文介绍了在MFC中如何自定义按钮控件,包括鼠标经过、离开、按下状态的处理,以及如何实现窗口的自由拖动和改变大小效果。通过重载基类方法,实现按钮的自绘,并在对话框中添加并响应自定义按钮事件。
摘要由CSDN通过智能技术生成

               昨天学习了窗口的自绘,即去掉窗口的非客户区,自己来模拟窗口的客户区与非客户区,然后来对其进行操作。。

发现问题:

             今天早上运行时候发现一个问题:即当我把窗口Dialog的属性页面上的sys_menu选项设置成为True,将会出现运行程序不能出现对话框的情景。

                                                                       后来发现原来是我SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewExStyle)写错了。。

 

今天来学习按钮的重绘:

            按钮基本上是Windows应用程序编写时候必不可少的控件。而Windows提供的按钮可能不尽人意,这就需要我们对BUtton重写了。

                一,定义一个类叫做CMyButton,其基类为CButton。

                二, 按钮在操作的时候应该实现以下几种状态:

1、鼠标经过,当鼠标经过的时候,按钮应该改变颜色或者变为高亮状态。这是就要用到WM_MOUSEMOVE消息。我们通过重写OnMouseMove函数:

 void CMyButtonEx::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 if(!m_bHovering)
 {
  m_bHovering = true;
  Invalidate(false);

  TRACKMOUSEEVENT TrackMouseEvent;
  TrackMouseEvent.cbSize = sizeof(TrackMouseEvent);
  TrackMouseEvent.dwFlags = TME_LEAVE;
  TrackMouseEvent.dwHoverTime = HOVER_DEFAULT;
  TrackMouseEvent.hwndTrack = GetSafeHwnd();

  _TrackMouseEvent(&TrackMouseEvent);
 }

 CButton::OnMouseMove(nFlags, point);
}

其中m_bHovering是一个bool变量,表示鼠标是否在按钮上。。

2、鼠标离开,按钮要恢复到正常状态。。这里我们用到WM_MOUSELEAVE消息。重写OnMouseLeave函数:

void CMyButtonEx::OnMouseLeave()
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 m_bHovering = false;
 Invalidate(FALSE);          //清楚缓冲区,强制按钮进行重绘

 return;

 CButton::OnMouseLeave();
}

3、按钮被按下,实现一种下陷的效果。我们用ON_LBUTTONDOWN消息。重写OnLButtonDown函数:

void CMyDialogEx::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值

(在这里添加代码,可以贴一张有下陷感觉的图片。。)


 CButton::OnLButtonDown(nFlags, point);
}

4、按钮不可用,这里实际上也是可以通过贴图实现。

                     三、重载基类的 PreSubclassWindow。这个函数其实是在 CWnd 里定义的。当控件子类化是由 framework 知道调用。我们常常在这个函数里修改控件的 style。在这里我们要将控件改为自绘的。

oid CMyButtonEx::PreSubclassWindow()
{
 // TODO: 在此添加专用代码和/或调用基类

 CButton::PreSubclassWindow();

 SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
}

                  四、最后,也是最重要的。是具体的绘制操作,在这里重载DrawItem()函数就可以了。。 这个函数是在宿主类的OnDrawItem()函数中呗调用。。

宿主类的OnDrawItem()函数作用是为了绘制各个子控件,宿主类通过调用控件累的DrowItem()函数来实现子控件的自我绘制。。

 

五、按钮重绘完成后,然后我们在重绘的窗口上添加这三个按钮。

CMyButton m_btClose;

m_btClose.Create(NULL, WS_VISIBLE | WS_CHILD, rcControl, this, IDCANCEL);

。。。

可以自定义消息对着几个按钮的事件进行响应。。

在对话框程序中重写OnCommand函数。对消息进行响应

switch(LOWORD(wParam))

{

     case:

            break;

}

 

六、实现窗口可以随意拖动的效果:

           添加WM_LBUTTONDOWN消息

void CMyDialogEx::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 if(!m_bIsZoomed)
 {
                 PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));

                 return ;
 }

 CDialog::OnLButtonDown(nFlags, point);
}

 

七、实现窗口可以随意改变大小的效果:

             这里只需要处理WM_NVHITTEST和WM_NCLBUTTONDOWN消息就可以了。。

LRESULT CMyDialogEx::OnNcHitTest(CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 if(m_bExtrude && !m_bIsZoomed)
 {
  CRect rcWindow;
  GetWindowRect(&rcWindow);

  if((point.x <= rcWindow.left + BORDERWIDTH) && (point.y > BORDERWIDTH) && (point.y < rcWindow.bottom - BORDERWIDTH * 2))
  {
   return HTLEFT;
  }
  else if((point.x >= rcWindow.right-BORDERWIDTH) && (point.y>BORDERWIDTH) && (point.y<rcWindow.bottom-BORDERWIDTH*2))
  {
   return HTRIGHT;
  }
  else if((point.y <= rcWindow.top+BORDERWIDTH) && (point.x>BORDERWIDTH) && (point.x<rcWindow.right-BORDERWIDTH*2))
  {
   return HTTOP;
  }
  else if((point.y >= rcWindow.bottom-BORDERWIDTH) && (point.x>BORDERWIDTH) && (point.x<rcWindow.right-BORDERWIDTH*2))
  {
   return HTBOTTOM;
  }
  else if((point.x <= rcWindow.left+BORDERWIDTH*2) && (point.y <= rcWindow.top+BORDERWIDTH*2))
  {
   return HTTOPLEFT;
  }
  else if((point.x <= rcWindow.left+BORDERWIDTH*2) && (point.y <= rcWindow.top+BORDERWIDTH*2))
  {
   return HTTOPRIGHT;
  }
  else if((point.x <= rcWindow.left+BORDERWIDTH*2) && (point.y >= rcWindow.bottom-BORDERWIDTH*2))
  {
   return HTBOTTOMLEFT;
  }
  else if((point.x >= rcWindow.right-BORDERWIDTH*2) && (point.y >= rcWindow.bottom-BORDERWIDTH*2))
  {
   return HTBOTTOMRIGHT;
  }
  else
  {
   return CWnd::OnNcHitTest(point);
  }
  return 0;
 }


 return CDialog::OnNcHitTest(point);
}

void CMyDialogEx::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 if( m_bExtrude )
 {        
  if (nHitTest == HTTOP)                  
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTBOTTOM)
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOM, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTLEFT)
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_LEFT, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTRIGHT)
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_RIGHT, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTTOPLEFT)
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPLEFT, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTTOPRIGHT)
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPRIGHT, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTBOTTOMLEFT) 
   PostMessage( WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMLEFT, MAKELPARAM(point.x, point.y));
  else if (nHitTest == HTBOTTOMRIGHT)
   PostMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMRIGHT, MAKELPARAM(point.x, point.y));
  else if (nHitTest==HTCAPTION)
   PostMessage(WM_SYSCOMMAND, SC_MOVE | 4, MAKELPARAM(point.x, point.y));
 }

 CDialog::OnNcLButtonDown(nHitTest, point);
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值