MFC学习之第四天 (一)

来源:互联网 发布:华为怎么清除缓存数据 编辑:程序博客网 时间:2024/04/27 14:00

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

发现问题:

             今天早上运行时候发现一个问题:即当我把窗口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