tatic控件默认是不支持响应鼠标消息的,如果把其ID从IDC_STATIC改成其他的,可见其可以响应BN_CLICKED消息,但这远远不够。但是MS也没有把路堵死,我们可以利用SetWindowLong,动态增加 其SS_NOTIFY风格,使其支持鼠标响应。
1、不重载CStatic,使静态文本控件支持鼠标消息的办法
//可以在InitDialog中添加 DWORD dwStyle = m_static1.GetStyle(); dwStyle |= SS_NOTIFY; SetWindowLong(m_static1.GetSafeHwnd(), GWL_STYLE, dwStyle); SetWindowLong(m_static2.GetSafeHwnd(), GWL_STYLE, dwStyle); dwStyle = m_skBmp.GetStyle();//m_skBmp指的是picture控件(关联的CStatic的变量) dwStyle |= SS_NOTIFY; SetWindowLong(m_skBmp.GetSafeHwnd(), GWL_STYLE, dwStyle);
当然,也可以不关联CStatic的成员变量,直接GetDlgItem是一样的。
对其添加消息响应,以双击为例:
分别添加
afx_msg void OnStaticDblClick(); …… ON_STN_DBLCLK(IDC_STATIC2, OnStaticDblClick) …… 最后实现 void CTestDlg::OnStaticDblClick() { //在这里添加操作 MessageBox(_T("静态控件被DblClicked啦!")); } 利用这个,还可用picture控件做一个简单的按钮,比较简单,详见附件代码。
2、为实现更强大的功能,最好的办法是重载CStatic类。这里以CHyperLinker类为例,给大家讲讲实现方法
增加SS_NOTIFY属性方法类似,可以在PreSubClass中完成, 这里代码略去
实现滑过效果、点击效果(颜色变化等效果),主要是在对应消息响应函数中调用Invalidate, 在CtlColor实现重画。
在CtlColor(注意响应的是WM_CTLCOLOR_REFLECT)里面无非是对各种状态的判断,并SetTextColor等而已
HBRUSH CHyperLinker::CtlColor(CDC* pDC, UINT nCtlColor) { ASSERT(nCtlColor == CTLCOLOR_STATIC); DWORD dwStyle = GetStyle(); /* if (!(dwStyle & SS_NOTIFY)) { // Turn on notify flag to get mouse messages and STN_CLICKED. // Otherwise, I'll never get any mouse clicks! ::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle | SS_NOTIFY); }*/ HBRUSH hbr = NULL; if ((dwStyle & 0xFF) <= SS_RIGHT) { // Modify the font to be underline if (!((HFONT) m_Font)) { LOGFONT lf; GetFont()->GetObject(sizeof(lf), &lf); lf.lfUnderline = m_bUnderLine; m_Font.CreateFontIndirect(&lf); } pDC->SelectObject(&m_Font); //set the text colors if(m_bVisited==TRUE) { pDC->SetTextColor(m_VisitedColor); // AfxMessageBox("Click"); } else { if(m_bAboveControl==TRUE) { pDC->SetTextColor(m_CoverColor); // AfxMessageBox("Above"); } else { pDC->SetTextColor(this->m_InitColor); // AfxMessageBox("init"); } } pDC->SetBkMode(TRANSPARENT); // return hollow brush to preserve parent background color hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH); } return hbr; }再重点介绍一下响应鼠标滑动消息。先看一下代码:
void CHyperLinker::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rect; GetClientRect(rect); // static BOOL bIsIn=FALSE; //判断是否前一此鼠标就已经在static控件区域类 if (rect.PtInRect(point)) { m_bAboveControl=TRUE; /*以下被注释的几行为无效代码, C瓜哥注*/ //if(bIsIn==FALSE) //{ SetCapture(); bIsIn=TRUE; Invalidate(); //} } else { m_bAboveControl=FALSE; //if (bIsIn==TRUE) //{ ReleaseCapture(); bIsIn=FALSE; Invalidate(); //} } CStatic::OnMouseMove(nFlags, point);