www.pudn.com > BesidesFTPServer.rar > IconButton.cpp
/********************************************************************/
/* */
/* IconButton.cpp */
/* */
/* Implementation of the CIconButton. */
/* */
/* This class make it possible to display an icon and text on a */
/* button, which unfortunately can't be done with CButton... */
/* */
/* CIconButton also has support for XP themes, so you can have */
/* themed buttons that have an icon! */
/* */
/* Programmed by Pablo van der Meer */
/* Copyright Pablo Software Solutions 2002 */
/* http://www.pablovandermeer.nl */
/* */
/* Last updated: 19 September 2002 */
/* */
/********************************************************************/
#include "stdafx.h"
#include "IconButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CIconButton::CIconButton()
{
m_hIcon = NULL;
}
CIconButton::~CIconButton()
{
if(m_hIcon != NULL)
DeleteObject(m_hIcon);
}
BEGIN_MESSAGE_MAP(CIconButton, CButton)
//{{AFX_MSG_MAP(CIconButton)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/********************************************************************/
/* */
/* Function name : DrawItem */
/* Description : Called by the framework when a visual aspect of */
/* an owner-draw button changes. */
/* */
/********************************************************************/
void CIconButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
UINT uStyle = DFCS_BUTTONPUSH;
// if button is pushed, add the pushed style to DrawFrameControl
if (lpDrawItemStruct->itemState & ODS_SELECTED)
uStyle |= DFCS_PUSHED;
// is button flat ?
if (GetButtonStyle() & BS_FLAT)
uStyle |= DFCS_FLAT;
// clear background
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, ::GetSysColor(COLOR_BTNFACE));
// XP theme support
if (m_Theme.IsThemingSupported())
{
int nStateId = 0;
if (m_Theme.OpenThemeData(GetSafeHwnd(), L"BUTTON"))
{
nStateId = PBS_NORMAL;
// unfortunately an ownerdrawn button can't also have the BS_DEFPUSHBUTTON style
// if (lpDrawItemStruct->itemState & ODS_DEFAULT)
// nStateId = PBS_DEFAULTED;
if (lpDrawItemStruct->itemState & ODS_FOCUS)
nStateId = PBS_HOT;
if (lpDrawItemStruct->itemState & ODS_SELECTED)
nStateId = PBS_PRESSED;
if (lpDrawItemStruct->itemState & ODS_DISABLED)
nStateId = PBS_DISABLED;
m_Theme.DrawThemeBackground(pDC->GetSafeHdc(), BP_PUSHBUTTON, nStateId, &lpDrawItemStruct->rcItem);
m_Theme.CloseThemeData();
}
else
{
// draw the button frame
::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle);
}
}
else
{
// draw the button frame
::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle);
}
// get button text
CString strText;
GetWindowText(strText);
// set default button colors
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_BTNFACE));
pDC->SetBkMode(TRANSPARENT);
// is button disabled ?
BOOL bDisabled = (lpDrawItemStruct->itemState & ODS_DISABLED);
CRect rcIcon(0,0,0,0);
// icon loaded ?
if(m_hIcon)
{
// calculate icon's rectangle
rcIcon = lpDrawItemStruct->rcItem;
CalcIconRect(pDC, rcIcon);
CPoint pt = rcIcon.TopLeft();
if (lpDrawItemStruct->itemState & ODS_SELECTED)
pt.Offset(1, 1);
// draw icon
pDC->DrawState(pt, CSize(m_nIconWidth, m_nIconHeight), (HICON)m_hIcon, DST_ICON | (bDisabled ? DSS_DISABLED : DSS_NORMAL), (CBrush *)NULL);
}
else
{
// if no icon is loaded, just display text
}
// calculate text's rectangle
CRect rcText = lpDrawItemStruct->rcItem;
CalcTextRect(pDC, strText, rcText, rcIcon);
if (lpDrawItemStruct->itemState & ODS_SELECTED)
rcText.OffsetRect(1, 1);
// draw text
pDC->DrawState(rcText.TopLeft(), rcText.Size(), (LPCTSTR)strText, (bDisabled ? DSS_DISABLED : DSS_NORMAL), TRUE, 0, (CBrush*)NULL);
// and finally draw the focus rectangle
if(lpDrawItemStruct->itemState & ODS_FOCUS)
{
rcText = lpDrawItemStruct->rcItem;
::InflateRect(&rcText, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE));
pDC->DrawFocusRect(&rcText);
}
}
/********************************************************************/
/* */
/* Function name : PreSubclassWindow */
/* Description : Initialize some stuff */
/* */
/********************************************************************/
void CIconButton::PreSubclassWindow()
{
// set default style
ModifyStyle(NULL, BS_OWNERDRAW | BS_ICON | BS_VCENTER | BS_LEFT);
CButton::PreSubclassWindow();
}
/********************************************************************/
/* */
/* Function name : SetIcon */
/* Description : Set button's icon */
/* */
/********************************************************************/
BOOL CIconButton::SetIcon(UINT nID, int nWidth, int nHeight)
{
HINSTANCE hInstance = AfxFindResourceHandle(MAKEINTRESOURCE(nID), RT_GROUP_ICON);
m_hIcon = (HICON)::LoadImage(hInstance, MAKEINTRESOURCE(nID), IMAGE_ICON, nWidth, nHeight, LR_DEFAULTCOLOR);
if (m_hIcon == NULL)
return FALSE;
m_nIconWidth = nWidth;
m_nIconHeight = nHeight;
return TRUE;
}
/********************************************************************/
/* */
/* Function name : CalcIconRect */
/* Description : Calculate icon's rectangle depending on button */
/* style. */
/* */
/********************************************************************/
BOOL CIconButton::CalcIconRect(CDC *pDC, CRect &rcIcon)
{
DWORD dwStyle = GetStyle();
CRect rc = rcIcon;
// calculate icon rectangle
rc.right = rc.left + m_nIconWidth;
rc.bottom = rc.top + m_nIconHeight;
int nOffset;
switch(dwStyle & (BS_CENTER|BS_RIGHT))
{
case BS_LEFT:
rc.left += 5;
rc.right += 5;
break;
case BS_CENTER:
nOffset = rc.right - rc.left;
rc.left = rcIcon.left + ((rcIcon.right - rcIcon.left) - nOffset) / 2;
rc.right = rc.left + nOffset;
break;
case BS_RIGHT:
nOffset = rc.right - rc.left;
rc.right = rcIcon.right - 5;
rc.left = rc.right - nOffset;
break;
}
switch (dwStyle & (BS_VCENTER|BS_BOTTOM))
{
case BS_TOP:
rc.top += 4;
rc.bottom += 4;
break;
case BS_VCENTER:
nOffset = rc.bottom - rc.top;
rc.top = rcIcon.top + ((rcIcon.bottom - rcIcon.top) - nOffset) / 2;
rc.bottom = rc.top + nOffset;
break;
case BS_BOTTOM:
nOffset = rc.bottom - rc.top;
rc.bottom = rcIcon.bottom - 4;
rc.top = rc.bottom - nOffset;
break;
}
rcIcon = rc;
return TRUE;
}
/********************************************************************/
/* */
/* Function name : CalcTextRect */
/* Description : Calculate text's rectangle depending on button */
/* style. */
/* */
/********************************************************************/
BOOL CIconButton::CalcTextRect(CDC *pDC, LPCTSTR lpszText, CRect &rcText, CRect &rcIcon)
{
DWORD dwStyle = GetStyle();
CRect rc = rcText;
switch(dwStyle & (BS_CENTER|BS_RIGHT))
{
case BS_LEFT:
rc.left = rcIcon.right;
break;
case BS_CENTER:
rc.top = rcIcon.bottom;
break;
case BS_RIGHT:
rc.right = rcIcon.left;
break;
}
rcText = rc;
// calculate text size
pDC->DrawText(lpszText, -1, &rc, DT_SINGLELINE | DT_CALCRECT);
switch (dwStyle & (BS_VCENTER|BS_BOTTOM))
{
case BS_TOP:
rc.OffsetRect((rcText.Width() - rc.Width())/2, rcIcon.top + rcIcon.Height()/2 - rc.Height()/2);
break;
case BS_VCENTER:
rc.OffsetRect((rcText.Width() - rc.Width())/2, (rcText.Height() - rc.Height())/2);
rc.OffsetRect(0, -1);
break;
case BS_BOTTOM:
rc.OffsetRect((rcText.Width() - rc.Width())/2, rcIcon.top + rcIcon.Height()/2 - rc.Height()/2);
break;
}
rcText = rc;
return TRUE;
}