⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 custombutton.cpp

📁 Wifi扫描器和自定义MFC控件 Wifi scanner + custom MFC controls 在WINCE环境下工作。
💻 CPP
📖 第 1 页 / 共 3 页
字号:

#include "CustomButton.h"

IMPLEMENT_DYNAMIC(CCustomButton, CButton)
/////////////////////////////////////////////////////////////////////////////
// CCustomButton

CCustomButton::CCustomButton()
{
	m_crTxtIdle=::GetSysColor(COLOR_BTNTEXT);
	m_crBkgIdle=::GetSysColor(COLOR_BTNFACE);
	m_crTxtPressed=m_crTxtIdle;
	m_crBkgPressed=m_crBkgIdle;
	m_crFrame=m_crTxtIdle;
	m_crHGStart=RGB(0, 0, 0);
	m_crHGEnd=RGB(255, 255, 255);

	m_bPressed=false;

	m_bFlat=true;
	m_bTransparent=false;
	m_bHGradient=false;
	m_bIsGroup=false;

	m_hBmpActive=m_hBmpInactive=NULL;
	m_dwBmpW=m_dwBmpH=0;
	m_hCustomFont=NULL;
	m_ctType=btCustomButton;
	RegisterCustomClass();
}

//////////////////////////////////////////////////////////////
CCustomButton::~CCustomButton()
{
	if(m_hBmpActive != NULL)
	{
		DeleteObject(m_hBmpActive);
	}
	if(m_hBmpInactive != NULL)
	{
		DeleteObject(m_hBmpInactive);
	}
	m_DrawDC.SelectObject(m_hOldDCBmp);
	DeleteObject(m_hOldDCBmp);
	if(m_hCustomFont != NULL)
	{
		DeleteObject(m_hCustomFont);
	}
}

//////////////////////////////////////////////////////////////////////////
bool CCustomButton::RegisterCustomClass()
{
WNDCLASS wndcls;
HINSTANCE hInst;

	hInst = AfxGetInstanceHandle();

	if(!(::GetClassInfo(hInst, _T("CustomButtonClass"), &wndcls)))
	{
		// otherwise we need to register a new class
		wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
		wndcls.lpfnWndProc      = ::DefWindowProc;
		wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
		wndcls.hInstance        = hInst;
		wndcls.hIcon            = NULL;
		wndcls.hCursor          = NULL;
		wndcls.hbrBackground    = (HBRUSH)::GetStockObject(NULL_BRUSH);
		wndcls.lpszMenuName     = NULL;
		wndcls.lpszClassName    = _T("CustomButtonClass");

		if(FALSE == AfxRegisterClass(&wndcls))
		{
#ifdef _DEBUG
			OutputDebugString(_T("Failed to register class for Custom_button"));
#endif
			return false;
		}
	}
	return true;
}

//////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CCustomButton, CButton)
	//{{AFX_MSG_MAP(CCustomButton)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		ON_WM_LBUTTONDOWN()
		ON_WM_LBUTTONUP()
		ON_MESSAGE(BM_SETCHECK, OnBMSetCheck)
		ON_MESSAGE(BM_GETCHECK, OnBMGetCheck)
		//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////////
LRESULT CCustomButton::OnBMSetCheck(WPARAM wParam, LPARAM lParam)
{
	//if radio
	if(m_ctType == btCustomRadio || m_ctType == btCustomCheckBox)
	{
		if(wParam == BST_CHECKED)
		{
			m_bPressed=true;
			SetWindowText(m_strActiveCaption);
		}
		else
		{
			m_bPressed=false;
			SetWindowText(m_strCaption);
		}
		Invalidate();
	}
	//processed
	return 0;
}

//////////////////////////////////////////////////////////////////////////
LRESULT CCustomButton::OnBMGetCheck(WPARAM wParam, LPARAM lParam)
{
	if(m_bPressed == true)
	{
		return BST_CHECKED;
	}
	else
	{
		return BST_UNCHECKED;
	}
}

//////////////////////////////////////////////////////////////////////////
void CCustomButton::PreSubclassWindow()
{
LONG lStyle;

	lStyle=GetWindowLong(GetSafeHwnd(), GWL_STYLE);
	if((lStyle & BS_GROUPBOX) == BS_GROUPBOX)
	{
		m_bIsGroup=true;
		m_ctType=btCustomGroup;
	}
	else
	{
		m_bIsGroup=false;
		if(((lStyle & BS_GROUPBOX) == BS_CHECKBOX) || ((lStyle & BS_GROUPBOX) == BS_AUTOCHECKBOX))
		{
			m_ctType=btCustomCheckBox;
		}
		else
		if((lStyle & BS_GROUPBOX) == BS_RADIOBUTTON || ((lStyle & BS_GROUPBOX) == BS_AUTORADIOBUTTON))
		{
			m_ctType=btCustomRadio;
		}
		else
		{
			m_ctType=btCustomButton;
			if(lStyle & BS_FLAT)
			{
				m_bFlat=true;
			}
			else
			{
				m_bFlat=false;
			}
		}
	}

	GetWindowText(m_strCaption);
	m_strActiveCaption=m_strCaption;

	ModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);

	//at this stage we do have a HWND and a DC
	CDC *pDC;
	CRect rc;

	GetClientRect(&rc);
	pDC=GetDC();
	if(pDC != NULL)
	{
		m_DrawDC.CreateCompatibleDC(pDC);
		m_DrawBitmap.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
		m_hOldDCBmp=m_DrawDC.SelectObject(m_DrawBitmap.GetSafeHandle());
		ReleaseDC(pDC);
	}
#ifdef _DEBUG
	else
	{
		OutputDebugString(_T("Custom_button failed to get DC."));
	}
#endif


	CButton::PreSubclassWindow();
}

//////////////////////////////////////////////////////////////////////////
void CCustomButton::OnLButtonUp(UINT nFlags, CPoint point)
{
LONG lStyle;

	//if not disabled
	lStyle=GetWindowLong(GetSafeHwnd(), GWL_STYLE);
	if( !(lStyle & WS_DISABLED))
	{
		//depending on type...
		switch(m_ctType)
		{
			case btCustomButton:
			{
				//if regular button, state changes to not pressed
				if( !(lStyle & BS_PUSHLIKE))
				{
					m_bPressed=false;
					SetWindowText(m_strCaption);
					Invalidate();
				}
				else
				{
					//nothing to do
				}
				break;
			}//case Custom button
			case btCustomRadio:
			{
				break;
			}//Custom radio
			case btCustomCheckBox:
			{
				break;
			}
		}
	}
	CButton::OnLButtonUp(nFlags, point);
}

//////////////////////////////////////////////////////////////////////////
void CCustomButton::OnLButtonDown(UINT nFlags, CPoint point)
{
LONG lStyle;

	//if not disabled
	lStyle=GetWindowLong(GetSafeHwnd(), GWL_STYLE);
	if( !(lStyle & WS_DISABLED))
	{
		//depending on type...
		switch(m_ctType)
		{
			case btCustomButton:
			{
				//if regular button, state changes to pressed
				if( !(lStyle & BS_PUSHLIKE))
				{
					m_bPressed=true;
					SetWindowText(m_strActiveCaption);
					//			SetCheck(BST_CHECKED);
				}
				else
				{
					//toggle state
					m_bPressed= !m_bPressed;
					//			SetCheck(m_bPressed == true ? BST_CHECKED : BST_UNCHECKED);
					SetWindowText(m_bPressed == true ? m_strActiveCaption : m_strCaption);
				}
				Invalidate();
				break;
			}//Custom button
			case btCustomRadio:
			{
				//if not checked, check button
				if(m_bPressed == false)
				{
					m_bPressed=true;
					SetWindowText(m_strActiveCaption);
					SetCheck(BST_CHECKED);

					//uncheck all radios in the group
					CWnd *pParentWnd;
					pParentWnd=GetParent();
					if(pParentWnd != NULL)
					{
						CWnd *pStart, *pSibling;

						pStart=pSibling=pParentWnd->GetNextDlgGroupItem(this, TRUE);
						do
						{
							if(pSibling == NULL) 
							{
								break;
							}
							if(this != pSibling)
//							&&	((GetWindowLongW( sibling, GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
							{
								pSibling->SendMessage(BM_SETCHECK, BST_UNCHECKED, 0);
							}
							pSibling=pParentWnd->GetNextDlgGroupItem(pSibling, FALSE);
						}while(pSibling != pStart);
					}//if parent != NULL
				}
				break;
			}
			case btCustomCheckBox:
			{
				//toggle state
				m_bPressed= !m_bPressed;
				SetWindowText(m_bPressed == true ? m_strActiveCaption : m_strCaption);
				SetCheck(m_bPressed == true ? BST_CHECKED : BST_UNCHECKED);
				break;
			}
		}
	}
	//disable shell animation
	//call default handler instead of OnLButtonDown, which would call SHRecognizeGesture
	Default();
}

/////////////////////////////////////////////////////////////////////////////
void CCustomButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
{
CDC* pDC;
CRect itemRect;
LONG lStyle;
HGDIOBJ hOldFont;

	pDC=CDC::FromHandle(lpDIS->hDC);

	itemRect=lpDIS->rcItem;

	if(m_hCustomFont != NULL)
	{
		hOldFont=m_DrawDC.SelectObject((HGDIOBJ)m_hCustomFont);
	}

	lStyle=GetWindowLong(GetSafeHwnd(), GWL_STYLE);

	switch(m_ctType)
	{
		case btCustomButton:
		{
			DrawPB(&m_DrawDC, &itemRect);
			break;
		}
		case btCustomRadio:
		case btCustomCheckBox:
		{
			DrawRBCB(&m_DrawDC, &itemRect);
			break;
		}
		case btCustomGroup:
		{
			DrawGB(&m_DrawDC, &itemRect);
			break;
		}
	}

	if(m_hCustomFont != NULL)
	{
		m_DrawDC.SelectObject(hOldFont);
	}

	//finally blit mem DC to screen
	pDC->BitBlt(0, 0, itemRect.Width(), itemRect.Height(), &m_DrawDC, 0, 0, SRCCOPY);
}

//////////////////////////////////////////////////////////////////////////
//gradient background drawing
void CCustomButton::DrawGradient(CDC *pDC)
{
CRect rc;
double dHRStep, dHGStep, dHBStep, dR, dG, dB;
int i, w, h;

	GetClientRect(&rc);

	w=rc.Width();
	h=rc.Height();

	//horizontal step values for R, G, B colors
	if(m_bPressed == false)
	{
		dR=GetRValue(m_crHGEnd);
		dG=GetGValue(m_crHGEnd);
		dB=GetBValue(m_crHGEnd);
	}
	else
	{
		dR=GetRValue(m_crHGStart);
		dG=GetGValue(m_crHGStart);
		dB=GetBValue(m_crHGStart);
	}

	dHRStep=dR;
	dHGStep=dG;
	dHBStep=dB;

	if(m_bPressed == false)
	{
		dHRStep-=GetRValue(m_crHGStart);
		dHGStep-=GetGValue(m_crHGStart);
		dHBStep-=GetBValue(m_crHGStart);
	}
	else
	{
		dHRStep-=GetRValue(m_crHGEnd);
		dHGStep-=GetGValue(m_crHGEnd);
		dHBStep-=GetBValue(m_crHGEnd);
	}

	dHRStep/=h;
	dHGStep/=h;
	dHBStep/=h;

	//color start values
	if(m_bPressed == false)
	{
		dR=GetRValue(m_crHGStart);
		dG=GetGValue(m_crHGStart);
		dB=GetBValue(m_crHGStart);
	}
	else
	{
		dR=GetRValue(m_crHGEnd);
		dG=GetGValue(m_crHGEnd);
		dB=GetBValue(m_crHGEnd);
	}

	//draw horz lines
	for(i=2; i<h-2; i++)
	{
		CPen ptmp(PS_SOLID, 1, RGB(dR, dG, dB));

		HGDIOBJ hOldPen=pDC->SelectObject(ptmp);

		pDC->MoveTo(2, i);
		pDC->LineTo(w-2, i);

		pDC->SelectObject(hOldPen);

		//next color
		dR+=dHRStep;
		dG+=dHGStep;
		dB+=dHBStep;
	}

}

//////////////////////////////////////////////////////////////////////////
//draw group box
void CCustomButton::DrawGB(CDC* pDC, CRect* pRect)
{
CPen framepen;
CBrush framebrush, titlebrush;
HGDIOBJ hOldPen, hOldBrush;
CString str;
LONG lStyle;
UINT nFormat;
bool bIsTxtBottom;
CSize sTextSize;
CRect rcFrame, rcText;

	//get style
	lStyle=GetWindowLong(GetSafeHwnd(), GWL_STYLE);

	//is text bottom?
	if((m_cfFlags & bfMask) == bfTextBottom)
	{
		bIsTxtBottom=true;
	}
	else
	{
		bIsTxtBottom=false;
	}

	//get text dimensions
	GetWindowText(str);
	sTextSize=pDC->GetTextExtent(str);
	if(str == _T(""))
	{
		//if no title, get current text height with another call
//		CSize sTmp;
//		sTmp=pDC->GetTextExtent(_T("A"));
//		sTextSize.cy=sTmp.cy;
		sTextSize.cy=0;
	}

	//create frame pen
	framepen.CreatePen(PS_SOLID, 1, m_crFrame);

	framebrush.CreateSolidBrush(m_crBkgIdle);

	//create title brush
	titlebrush.CreateSolidBrush(m_crFrame);

	//draw frame box
	hOldPen=pDC->SelectObject(framepen);	
	hOldBrush=pDC->SelectObject(framebrush);

	rcFrame=*pRect;
	rcText=rcFrame;

	if(bIsTxtBottom == true)
	{
		rcText.top = rcFrame.bottom - sTextSize.cy;
		rcFrame.bottom -= sTextSize.cy/2;
	}
	else
	{
		rcText.bottom = rcFrame.top + sTextSize.cy;
		rcFrame.top += sTextSize.cy/2;
	}

	pDC->Rectangle(rcFrame);

	pDC->SelectObject(hOldPen);
	pDC->SelectObject(hOldBrush);

	//draw title rectangle, only if there is caption text
	if(str != _T(""))
	{
		pDC->FillRect(rcText, &titlebrush);
	}

	//prepare text
	GetClientRect(&rcText);
	if(str != _T(""))
	{
		rcText.left += 5;
		rcText.right -= 5;

		switch(lStyle & BS_CENTER)
		{
			case BS_CENTER:
			{
				nFormat=DT_CENTER;
				break;
			}
			case BS_RIGHT:
			{
				nFormat=DT_RIGHT;
				break;
			}
			default:
				nFormat=DT_LEFT;
		}

		if(bIsTxtBottom == true)
		{
			nFormat |= DT_BOTTOM;
		}
		else
		{
			nFormat |= DT_TOP;
		}

		pDC->SetTextColor(m_crTxtIdle);
/*
		if(m_bTransparent == true)
		{
			pDC->SetBkMode(TRANSPARENT);
		}
		else
		{
			pDC->SetBkMode(OPAQUE);
			pDC->SetBkColor(m_crFrame);
		}
*/
		pDC->SetBkMode(TRANSPARENT);
		pDC->DrawText(str, &rcText, nFormat | DT_SINGLELINE);
	}
}

//////////////////////////////////////////////////////////////////////////
//draw radio/checkbox
void CCustomButton::DrawRBCB(CDC* pDC, CRect* pRect)
{
COLORREF crColor;
HANDLE hCurrentBmp;
CString strTitle;
CRect rcText, rcBtn, rcImg;
LONG lStyle, lRight;
int tx, ty, ix, iy;
UINT nDTFormat;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -