📄 flatbutton.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998 by Yuheng Zhao
// All rights reserved
//
// Distribute freely, except: don't remove my name from the source or
// documentation (don't take credit for my work), mark your changes (don't
// get me blamed for your possible bugs), don't alter or remove this
// notice.
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// If you have any questions, I can be reached as follows:
// yuheng@ministars.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "flatbutton.h"
/////////////////////////////////////////////////////////////////////////////
// CFlatButton
CFlatButton::CFlatButton()
{
dwFlags = FBS_BORDER|FBS_FOCUS|FBS_ROLLOVER;
m_bMouseIn = FALSE;
m_bChecked = FALSE;
m_bClickAgain = FALSE;
}
CFlatButton::~CFlatButton()
{
}
BEGIN_MESSAGE_MAP(CFlatButton, CButton)
//{{AFX_MSG_MAP(CFlatButton)
ON_WM_MOUSEMOVE()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
ON_WM_TIMER()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFlatButton message handlers
void CFlatButton::OnMouseMove(UINT nFlags, CPoint point)
{
// If the mouse enter the button with the left button pressed
// then do nothing
//if (nFlags & MK_LBUTTON && m_bMouseIn == FALSE) return;
CWnd* pWnd = GetActiveWindow();
CWnd* pParent = GetOwner();
CRect rect;
GetClientRect(&rect);
if (!rect.PtInRect(point))
{
if (m_bMouseIn == TRUE)
{
m_bMouseIn = FALSE;
if (nFlags & MK_LBUTTON || (dwFlags&FBS_ROLLOVER))
Invalidate();
}
}else if (m_bMouseIn == FALSE && ((pWnd != NULL) && (pParent != NULL)))
{
m_bMouseIn = TRUE;
KillTimer(14);
SetTimer(14, 10, NULL);
if (nFlags & MK_LBUTTON || (dwFlags&FBS_ROLLOVER))
InvalidateRect(NULL, FALSE);
}
CButton::OnMouseMove(nFlags, point);
}
void CFlatButton::OnKillFocus(CWnd* pNewWnd)
{
CButton::OnKillFocus(pNewWnd);
if (m_bMouseIn == TRUE)
{
m_bMouseIn = FALSE;
InvalidateRect(NULL, FALSE);
UpdateWindow();
}
}
#define _FBS_SPACE_ 4
#define _FBS_ARROWWIDTH_ 11
void CFlatButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rcClient = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState;
COLORREF colorFace = GetSysColor(COLOR_BTNFACE);
COLORREF colorShadow = GetSysColor(COLOR_3DSHADOW);
COLORREF colorLight = GetSysColor(COLOR_3DHILIGHT);
CDC memDC;
memDC.CreateCompatibleDC( pDC );
// Select a compatible bitmap into the memory DC
CBitmap bitmap;
bitmap.CreateCompatibleBitmap( pDC, rcClient.Width(), rcClient.Height() );
CBitmap* pOldBitmap = memDC.SelectObject( &bitmap );
if (m_bChecked && (!m_bMouseIn || dwFlags & FBS_MENU_BUTTON || !(dwFlags&FBS_ROLLOVER)))
{
CBrush *pBrush = CDC::GetHalftoneBrush();
memDC.SetTextColor(colorLight);
memDC.SetBkColor(colorFace);
memDC.FillRect(rcClient, pBrush);
//dc.SetTextColor(RGB(0,0,0));
//dc.SetBkColor(clrRect);
}else
memDC.FillSolidRect(rcClient, colorFace);
int nIconOffset = 0;
CString strText;
GetWindowText(strText);
bool bHasText = !strText.IsEmpty();
CSize szText;
if (bHasText)
{
CFont *pFont = GetFont();
CFont* pOldFont = memDC.SelectObject (pFont);
szText = memDC.GetTextExtent(strText);
memDC.SelectObject (pOldFont);
}
if (dwFlags & FBS_HAS_ICON)
{
ASSERT(m_hIcon!=0);
CRect rcIcon(rcClient);
int nOffset = 0;
if (!bHasText)
nOffset = ((rcIcon.Width() - m_nIconWidth)/2);
else
nOffset = ((rcIcon.Width() - m_nIconWidth - szText.cx)/3);
rcIcon.left += nOffset;
rcIcon.top += ((rcIcon.Height() - m_nIconHeight)/2);
if (state & ODS_SELECTED)
rcIcon.OffsetRect(1, 1);
/*::DrawIconEx(memDC.GetSafeHdc(), rcIcon.left, rcIcon.top,
m_hIcon, m_nIconHeight, m_nIconWidth, 0, NULL,
DI_NORMAL);*/
memDC.DrawState(rcIcon.TopLeft(),
CSize(m_nIconWidth,m_nIconHeight),
m_hIcon,
((state & ODS_DISABLED)? DSS_DISABLED : DSS_NORMAL),
(CBrush*)NULL);
//memDC.DrawIcon(rcIcon.TopLeft(), m_hIcon);
nIconOffset = nOffset*2+m_nIconWidth;
}
if ( bHasText)
{
CFont *pFont = GetFont();
CFont* pOldFont = memDC.SelectObject (pFont);
int iOldMode = memDC.GetBkMode();
memDC.SetBkMode( TRANSPARENT );
COLORREF crOldText ;
crOldText = memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
//CSize szText = memDC.GetTextExtent(strText);
CPoint ptText;
if (dwFlags & FBS_ARROW_UP || dwFlags & FBS_ARROW_DOWN)
{
int nTotalWidth = szText.cx + _FBS_SPACE_ + _FBS_ARROWWIDTH_;
if (nIconOffset) // If has icon
ptText.x = nIconOffset;
else // Centrum
ptText.x = (rcClient.Width()-nTotalWidth)/2;
ptText.y = (rcClient.Height()-szText.cy)/2;
// Draw Arrows if nessesary
CPoint pt;
pt.x = ptText.x + szText.cx + _FBS_SPACE_;
pt.y = (rcClient.Height() - _FBS_ARROWWIDTH_/2) / 2;
if (state & ODS_SELECTED)
pt.Offset(1,1);
memDC.SelectStockObject(BLACK_PEN);
memDC.SelectStockObject(BLACK_BRUSH);
DrawArrow(&memDC, pt, _FBS_ARROWWIDTH_, dwFlags);
}else
{
if (nIconOffset) // If has icon
ptText.x = nIconOffset;
else // Centrum
ptText.x = (rcClient.Width()-szText.cx)/2;
ptText.y = (rcClient.Height()-szText.cy)/2;
}
if (state & ODS_SELECTED)
ptText.Offset(1,1);
if (state & ODS_DISABLED)
memDC.DrawState(ptText, szText, strText, DSS_DISABLED,
TRUE, 0, (HBRUSH)NULL);
else
memDC.DrawText(strText, CRect(ptText,szText), DT_CENTER|DT_VCENTER);
memDC.SetBkMode( iOldMode );
memDC.SetTextColor( crOldText );
memDC.SelectObject (pOldFont);
}
if (state & ODS_SELECTED )
memDC.DrawEdge(rcClient, BDR_SUNKENOUTER, BF_RECT);
else if (m_bChecked)
{
if (!(dwFlags&FBS_CHECKED_NOBORDER))
memDC.DrawEdge(rcClient, BDR_SUNKENOUTER, BF_RECT);
}else if ((!m_bMouseIn) || !(dwFlags&FBS_ROLLOVER))
{
if (dwFlags & FBS_BORDER)
memDC.DrawEdge(rcClient, BDR_RAISEDINNER, BF_RECT);
//memDC.Draw3dRect(rcClient, colorLight, colorShadow);
}else
{
if (dwFlags & FBS_BORDER)
memDC.DrawEdge(rcClient, EDGE_RAISED, BF_RECT);
else
memDC.Draw3dRect(rcClient, colorLight, colorShadow);
}
pDC->BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC,
0, 0, SRCCOPY );
if (state & ODS_FOCUS && dwFlags & FBS_FOCUS)
{
CRect r(rcClient);
r.DeflateRect(3,3);
pDC->DrawFocusRect(r);
//memDC.DrawEdge(r, EDGE_RAISED, BF_RECT);
//::DrawFocusRect(memDC.m_hDC, r);
}
memDC.SelectObject( pOldBitmap);
}
void CFlatButton::PreSubclassWindow()
{
SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
CButton::PreSubclassWindow();
}
void CFlatButton::OnTimer(UINT nIDEvent)
{
if (m_bMouseIn == FALSE)
{
KillTimer(14);
return;
}
CRect rect;
GetClientRect(&rect);
CPoint point;
GetCursorPos(&point);
ScreenToClient(&point);
if (!rect.PtInRect(point) && m_bMouseIn == TRUE)
{
KillTimer(14);
m_bMouseIn = FALSE;
if (dwFlags&FBS_ROLLOVER)
Invalidate();
}
}
void CFlatButton::ModifyFlag(const DWORD & dwRemove, const DWORD & dwAdd, const UINT bRedraw)
{
if (dwRemove) dwFlags &= ~(dwRemove);
if (dwAdd) dwFlags |= dwAdd;
if (bRedraw)
InvalidateRect(NULL);
}
void CFlatButton::DrawArrow(CDC* pDC, const CPoint& ptTopLeft, int nWidth, DWORD dwType)
{
POINT ptArray[3];
if (((dwType & FBS_ARROW_DOWN) && !m_bChecked) || ((dwType & FBS_ARROW_UP) && m_bChecked))
{
ptArray[0] = ptTopLeft;
ptArray[1].x = ptTopLeft.x + nWidth - nWidth%2;
ptArray[1].y = ptTopLeft.y;
ptArray[2].x = ptTopLeft.x + nWidth / 2;
ptArray[2].y = ptTopLeft.y + nWidth / 2;
pDC->Polygon(ptArray, 3);
}else if (((dwType & FBS_ARROW_UP) && !m_bChecked) || ((dwType & FBS_ARROW_DOWN) && m_bChecked))
{
ptArray[0].x = ptTopLeft.x;
ptArray[0].y = ptTopLeft.y + nWidth / 2;
ptArray[1].x = ptTopLeft.x + nWidth - nWidth%2;
ptArray[1].y = ptTopLeft.y + nWidth / 2;
ptArray[2].x = ptTopLeft.x + nWidth / 2;
ptArray[2].y = ptTopLeft.y;
pDC->Polygon(ptArray, 3);
}
}
void CFlatButton::SetCheck(BOOL b)
{
m_bChecked = b;
InvalidateRect(NULL);
}
BOOL CFlatButton::GetCheck()
{
return m_bChecked;
}
void CFlatButton::SetIcon(HICON hIcon, BYTE cx, BYTE cy)
{
m_hIcon = hIcon;
m_nIconWidth = cx;
m_nIconHeight = cy;
}
void CFlatButton::DoMenu()
{
if (dwFlags & FBS_MENU_BUTTON)
{
if (m_bClickAgain)
{
m_bClickAgain = FALSE;
return;
}
ASSERT(m_pMenu!=NULL);
SetCheck(TRUE);
CRect rect;
GetWindowRect(&rect);
CPoint pt;
pt = rect.TopLeft();
DWORD dwMenu = TPM_LEFTALIGN;
if (dwFlags & FBS_MENU_ALIGN_RIGHT)
pt.x += rect.Width();
if (!(dwFlags & FBS_MENU_ALIGN_TOP))
pt.y += rect.Height();
if (dwFlags & FBS_MENU_ALIGN_RIGHT && !(dwFlags & FBS_MENU_ALIGN_TOP))
dwMenu = TPM_RIGHTALIGN;
else if (!(dwFlags & FBS_MENU_ALIGN_RIGHT) && (dwFlags & FBS_MENU_ALIGN_TOP))
dwMenu = TPM_RIGHTALIGN;
GetOwner()->SendMessage(WM_FB_NOTIFY, FB_NOTIFY_INITMENU, (LPARAM)m_pMenu);
int n = m_pMenu->TrackPopupMenu(dwMenu|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, GetOwner());
SetCheck(FALSE);
if (n>0)
{
GetOwner()->SendMessage(WM_COMMAND, n, NULL);
}else
{
CPoint pt;
GetCursorPos(&pt);
if (rect.PtInRect(pt))
m_bClickAgain = TRUE;
else
m_bClickAgain = FALSE;
}
}
}
void CFlatButton::OnLButtonDown(UINT nFlags, CPoint point)
{
CButton::OnLButtonDown(nFlags, point);
DoMenu();
}
LRESULT CFlatButton::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_LBUTTONDBLCLK && !(dwFlags & FBS_MENU_BUTTON))
{
message = WM_LBUTTONDOWN;
}
return CButton::DefWindowProc(message, wParam, lParam);
}
void CFlatButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CButton::OnLButtonDblClk(nFlags, point);
DoMenu();
}
BOOL CFlatButton::PreTranslateMessage(MSG* pMsg)
{
if (m_ToolTip.GetSafeHwnd()!=NULL)
m_ToolTip.RelayEvent(pMsg);
return CButton::PreTranslateMessage(pMsg);
}
void CFlatButton::SetTooltipText(int nId, BOOL bActivate)
{
CString str;
str.LoadString(nId);
if (!str.IsEmpty())
SetTooltipText(str, bActivate);
}
void CFlatButton::SetTooltipText(LPCTSTR strTooltip, BOOL bActivate)
{
if (!m_ToolTip.GetSafeHwnd())
m_ToolTip.Create(this);
if (!m_ToolTip.GetToolCount())
{
CRect rc;
GetClientRect(rc);
m_ToolTip.AddTool(this, strTooltip, rc, GetDlgCtrlID());
}
m_ToolTip.UpdateTipText(strTooltip, this, GetDlgCtrlID());
m_ToolTip.Activate(bActivate);
}
void CFlatButton::EnableTooltip(BOOL bEnable)
{
if (!m_ToolTip.GetSafeHwnd())
return;
if (!m_ToolTip.GetToolCount())
return;
m_ToolTip.Activate(bEnable);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -