首先定义的模板 TrackControl // TrackControl.h: interface for the CTrackControl class. // // #if !defined(AFX_TRACKCONTROL_H__78722A99_73FD_41D5_85FB_8868C2F10223__INCLUDED_) #define AFX_TRACKCONTROL_H__78722A99_73FD_41D5_85FB_8868C2F10223__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 template<class BaseClass> class CTrackControl : public BaseClass { // Construction public: CTrackControl() { m_bTracking=m_bHover=FALSE; } virtual ~CTrackControl() {} BOOLEAN IsHover() { return m_bHover; } // Implementation public: virtual void OnHoverEnter()=0; virtual void OnHoverLeave()=0; // Generated message map functions protected: virtual LRESULT WindowProc(UINT nMessage, WPARAM wParam, LPARAM lParam) { LRESULT nResult=BaseClass::WindowProc(nMessage,wParam,lParam); switch(nMessage) { case WM_MOUSEMOVE: { if (!m_bTracking) { TRACKMOUSEEVENT Tme; Tme.cbSize = sizeof(Tme); Tme.hwndTrack = GetSafeHwnd(); Tme.dwFlags = TME_LEAVE|TME_HOVER; Tme.dwHoverTime = 1; if (_TrackMouseEvent(&Tme)) m_bTracking=TRUE; } break; } case WM_MOUSEHOVER: m_bHover=TRUE; OnHoverEnter(); break; case WM_MOUSELEAVE: m_bTracking=m_bHover=FALSE; OnHoverLeave(); break; } return nResult; } private: BOOLEAN m_bTracking; BOOLEAN m_bHover; }; #endif // !defined(AFX_TRACKCONTROL_H__78722A99_73FD_41D5_85FB_8868C2F10223__INCLUDED_) 美化的 CEdit 后的CNiceEdit代码: #if !defined(AFX_OWNEREDIT_H__5B37DFCE_8988_42D5_9A07_689E1C69844E__INCLUDED_) #define AFX_OWNEREDIT_H__5B37DFCE_8988_42D5_9A07_689E1C69844E__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // OwnerEdit.h : header file // #include "TrackControl.h" / // CNiceEdit window class CNiceEdit : public CTrackControl<CEdit> { // Construction public: CNiceEdit(); // Attributes public: //edit的外边框颜色 CBrush m_BoundryBrush; // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CNiceEdit) protected: //}}AFX_VIRTUAL // Implementation public: void Redraw(); void OnHoverLeave(); void OnHoverEnter(); virtual ~CNiceEdit(); // Generated message map functions protected: //{{AFX_MSG(CNiceEdit) afx_msg void OnNcPaint(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; / //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_OWNEREDIT_H__5B37DFCE_8988_42D5_9A07_689E1C69844E__INCLUDED_) // OwnerEdit.cpp : implementation file // #include "stdafx.h" #include "NiceEdit.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif / // CNiceEdit CNiceEdit::CNiceEdit() { m_BoundryBrush.CreateSolidBrush(RGB(187,200,143)); } CNiceEdit::~CNiceEdit() { m_BoundryBrush.DeleteObject(); } BEGIN_MESSAGE_MAP(CNiceEdit, CEdit) //{{AFX_MSG_MAP(CNiceEdit) ON_WM_NCPAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() / // CNiceEdit message handlers void CNiceEdit::OnHoverEnter() { Redraw(); } void CNiceEdit::OnHoverLeave() { Redraw(); } void CNiceEdit::OnNcPaint() { // TODO: Add your message handler code here CWindowDC DC(this); CRect Rect; GetWindowRect(&Rect); if (IsHover()) { DC.SelectObject(&m_BoundryBrush); DC.Rectangle(0,0,Rect.Width(),Rect.Height()); } else { DC.DrawEdge(CRect(0,0,Rect.Width(),Rect.Height()),EDGE_SUNKEN,BF_FLAT|BF_RECT); } // Do not call CEdit::OnNcPaint() for painting messages } void CNiceEdit::Redraw() { RedrawWindow(NULL,NULL,RDW_FRAME|RDW_INVALIDATE); }