有图有真相,先看效果:
这份代码的关键点在于: 创建完groupbox后将其本身隐藏
--------这样做的好处不言而喻: 不必担心被其覆盖的控件消息处理的问题,否则你可找了一个天大的麻烦.
代码很少,我就直接上代码吧,相信代码能解释一切真相:
#pragma once // QGroupBox #include "DrawOper.h" class QGroupBox : public CStatic { DECLARE_DYNAMIC(QGroupBox) public: QGroupBox(); virtual ~QGroupBox(); void SetHeaderTheme(COLORREF clrs[],UINT nEffect); inline void SetBorderColor(COLORREF clr) {m_crBorder = clr;}; inline void SetTextColor(COLORREF clr) { m_crText = clr; } void SetHeaderHeight(int nY); void Draw(CDC *pDC=NULL); protected: DECLARE_MESSAGE_MAP() afx_msg void OnPaint(); private: int m_nHeaderHeight; COLORREF m_crBorder; COLORREF m_crText; QDrawSchema m_dsHeader; };
Cpp
// QGroupBox IMPLEMENT_DYNAMIC(QGroupBox, CStatic) QGroupBox::QGroupBox() { m_crBorder = RGB(157,185,224); COLORREF cr3[] = {RGB(255,255,255), RGB(202,220,246), RGB(150,180,222)}; m_crText = 0; m_nHeaderHeight = 0; SetHeaderTheme(cr3,11); } QGroupBox::~QGroupBox() { } BEGIN_MESSAGE_MAP(QGroupBox, CStatic) ON_WM_PAINT() END_MESSAGE_MAP() void QGroupBox::SetHeaderTheme( COLORREF clrs[],UINT nEffect ) { m_dsHeader.SetBkColor(clrs,nEffect); } void QGroupBox::SetHeaderHeight( int nY ) { m_nHeaderHeight = nY; if (m_nHeaderHeight > 0) { CRect rect; GetClientRect(&rect); m_dsHeader.SetArea(CSize(rect.Width(),m_nHeaderHeight)); } } void QGroupBox::OnPaint() { // 此代码的关键就是在自己被创建之后隐藏 // 假如不隐藏自己的话,就要处理接受到的消息,转发给被自己覆盖的sibling控件, // 这样相当麻烦,而且容易多次重绘,引起闪烁 ShowWindow(SW_HIDE); } void QGroupBox::Draw(CDC *pDC) { BOOL bReleaseDC = FALSE; if (pDC == NULL) { pDC = GetParent()->GetDC(); bReleaseDC = FALSE; } int nSaveDC = pDC->SaveDC(); CRect rc; GetWindowRect(rc); GetParent()->ScreenToClient(&rc); // 表头 if (m_nHeaderHeight <= 0) SetHeaderHeight(22); CRect rcTemp = rc; rcTemp.bottom = rc.top + m_nHeaderHeight; m_dsHeader.Draw(pDC->GetSafeHdc(),NULL,&rcTemp); // 表头文字 CString sText; GetWindowText(sText); CFont *pFont = GetParent()->GetFont(); CFont *pOldFont = pDC->SelectObject(pFont); pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(m_crText); pDC->DrawText(sText,&rcTemp,DT_SINGLELINE | DT_END_ELLIPSIS | DT_CENTER | DT_VCENTER); pDC->SelectObject(pOldFont); // 边界 CBrush bru; bru.CreateSolidBrush(m_crBorder); pDC->FrameRect(&rc,&bru); bru.DeleteObject(); // 重建DC pDC->RestoreDC(nSaveDC); //释放 if (bReleaseDC) GetParent()->ReleaseDC(pDC); }