昨天学习了窗口的自绘,即去掉窗口的非客户区,自己来模拟窗口的客户区与非客户区,然后来对其进行操作。。
发现问题:
今天早上运行时候发现一个问题:即当我把窗口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
return HTRIGHT;
}
else if((point.y <= rcWindow.top+BORDERWIDTH) && (point.x>BORDERWIDTH) && (point.x
return HTTOP;
}
else if((point.y >= rcWindow.bottom-BORDERWIDTH) && (point.x>BORDERWIDTH) && (point.x
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);
}