#include "stdafx.h"
#include "BtnST.h"
#ifdef BTNST_USE_SOUND
#pragma comment(lib, "winmm.lib")
#include <Mmsystem.h>
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Warnings on level 4... naughty naughty
#pragma warning(disable:4244)
#pragma warning(disable:4100)
#pragma warning(disable:4005)
// ... and it will still complain about "note C6311"
/////////////////////////////////////////////////////////////////////////////
// CButtonST
// Mask for control's type
#define BS_TYPEMASK SS_TYPEMASK
#ifndef TTM_SETTITLE
#define TTM_SETTITLEA (WM_USER + 32) // wParam = TTI_*, lParam = char* szTitle
#define TTM_SETTITLEW (WM_USER + 33) // wParam = TTI_*, lParam = wchar* szTitle
#ifdef UNICODE
#define TTM_SETTITLE TTM_SETTITLEW
#else
#define TTM_SETTITLE TTM_SETTITLEA
#endif
#endif
#ifndef TTS_BALLOON
#define TTS_BALLOON 0x40
#endif
CButtonST::CButtonST()
{
m_bIsPressed = FALSE;
m_bIsFocused = FALSE;
m_bIsDisabled = FALSE;
m_bMouseOnButton = FALSE;
FreeResources(FALSE);
// Default type is "flat" button
m_bIsFlat = TRUE;
// Button will be tracked also if when the window is inactive (like Internet Explorer)
m_bAlwaysTrack = TRUE;
// By default draw border in "flat" button
m_bDrawBorder = TRUE;
// By default icon is aligned horizontally
m_byAlign = ST_ALIGN_HORIZ;
// By default use usual pressed style
SetPressedStyle(BTNST_PRESSED_LEFTRIGHT, FALSE);
// By default, for "flat" button, don't draw the focus rect
m_bDrawFlatFocus = FALSE;
// By default the button is not the default button
m_bIsDefault = FALSE;
// Invalid value, since type still unknown
m_nTypeStyle = BS_TYPEMASK;
// By default the button is not a checkbox
m_bIsCheckBox = FALSE;
m_nCheck = 0;
// Set default colors
SetDefaultColors(FALSE);
// No tooltip created
m_ToolTip.m_hWnd = NULL;
m_dwToolTipStyle = 0;
// Do not draw as a transparent button
m_bDrawTransparent = FALSE;
m_pbmpOldBk = NULL;
// No URL defined
SetURL(NULL);
// No cursor defined
m_hCursor = NULL;
// No associated menu
#ifndef BTNST_USE_BCMENU
m_hMenu = NULL;
#endif
m_hParentWndMenu = NULL;
m_bMenuDisplayed = FALSE;
m_bShowDisabledBitmap = TRUE;
m_ptImageOrg.x = 3;
m_ptImageOrg.y = 3;
// No defined callbacks
::ZeroMemory(&m_csCallbacks, sizeof(m_csCallbacks));
#ifdef BTNST_USE_SOUND
// No defined sounds
::ZeroMemory(&m_csSounds, sizeof(m_csSounds));
#endif
} // End of CButtonST
CButtonST::~CButtonST()
{
// Restore old bitmap (if any)
if (m_dcBk.m_hDC && m_pbmpOldBk)
{
m_dcBk.SelectObject(m_pbmpOldBk);
} // if
FreeResources();
// Destroy the cursor (if any)
if (m_hCursor) ::DestroyCursor(m_hCursor);
// Destroy the menu (if any)
#ifdef BTNST_USE_BCMENU
if (m_menuPopup.m_hMenu) m_menuPopup.DestroyMenu();
#else
if (m_hMenu) ::DestroyMenu(m_hMenu);
#endif
} // End of ~CButtonST
BEGIN_MESSAGE_MAP(CButtonST, CButton)
//{{AFX_MSG_MAP(CButtonST)
ON_WM_SETCURSOR()
ON_WM_KILLFOCUS()
ON_WM_MOUSEMOVE()
ON_WM_SYSCOLORCHANGE()
ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
ON_WM_ACTIVATE()
ON_WM_ENABLE()
ON_WM_CANCELMODE()
ON_WM_GETDLGCODE()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
#ifdef BTNST_USE_BCMENU
ON_WM_MENUCHAR()
ON_WM_MEASUREITEM()
#endif
ON_MESSAGE(BM_SETSTYLE, OnSetStyle)
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(BM_SETCHECK, OnSetCheck)
ON_MESSAGE(BM_GETCHECK, OnGetCheck)
END_MESSAGE_MAP()
void CButtonST::FreeResources(BOOL bCheckForNULL)
{
if (bCheckForNULL)
{
// Destroy icons
// Note: the following two lines MUST be here! even if
// BoundChecker says they are unnecessary!
if (m_csIcons[0].hIcon) ::DestroyIcon(m_csIcons[0].hIcon);
if (m_csIcons[1].hIcon) ::DestroyIcon(m_csIcons[1].hIcon);
// Destroy bitmaps
if (m_csBitmaps[0].hBitmap) ::DeleteObject(m_csBitmaps[0].hBitmap);
if (m_csBitmaps[1].hBitmap) ::DeleteObject(m_csBitmaps[1].hBitmap);
// Destroy mask bitmaps
if (m_csBitmaps[0].hMask) ::DeleteObject(m_csBitmaps[0].hMask);
if (m_csBitmaps[1].hMask) ::DeleteObject(m_csBitmaps[1].hMask);
} // if
::ZeroMemory(&m_csIcons, sizeof(m_csIcons));
::ZeroMemory(&m_csBitmaps, sizeof(m_csBitmaps));
} // End of FreeResources
void CButtonST::PreSubclassWindow()
{
UINT nBS;
nBS = GetButtonStyle();
// Set initial control type
m_nTypeStyle = nBS & BS_TYPEMASK;
// Check if this is a checkbox
if (nBS & BS_CHECKBOX) m_bIsCheckBox = TRUE;
// Set initial default state flag
if (m_nTypeStyle == BS_DEFPUSHBUTTON)
{
// Set default state for a default button
m_bIsDefault = TRUE;
// Adjust style for default button
m_nTypeStyle = BS_PUSHBUTTON;
} // If
// You should not set the Owner Draw before this call
// (don't use the resource editor "Owner Draw" or
// ModifyStyle(0, BS_OWNERDRAW) before calling PreSubclassWindow() )
ASSERT(m_nTypeStyle != BS_OWNERDRAW);
// Switch to owner-draw
ModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);
CButton::PreSubclassWindow();
} // End of PreSubclassWindow
UINT CButtonST::OnGetDlgCode()
{
UINT nCode = CButton::OnGetDlgCode();
// Tell the system if we want default state handling
// (losing default state always allowed)
nCode |= (m_bIsDefault ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
return nCode;
} // End of OnGetDlgCode
BOOL CButtonST::PreTranslateMessage(MSG* pMsg)
{
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
if (pMsg->message == WM_LBUTTONDBLCLK)
pMsg->message = WM_LBUTTONDOWN;
return CButton::PreTranslateMessage(pMsg);
} // End of PreTranslateMessage
HBRUSH CButtonST::CtlColor(CDC* pDC, UINT nCtlColor)
{
return (HBRUSH)::GetStockObject(NULL_BRUSH);
} // End of CtlColor
void CButtonST::OnSysColorChange()
{
CButton::OnSysColorChange();
m_dcBk.DeleteDC();
m_bmpBk.DeleteObject();
SetDefaultColors();
} // End of OnSysColorChange
LRESULT CButtonST::OnSetStyle(WPARAM wParam, LPARAM lParam)
{
UINT nNewType = (wParam & BS_TYPEMASK);
// Update default state flag
if (nNewType == BS_DEFPUSHBUTTON)
{
m_bIsDefault = TRUE;
} // if
else if (nNewType == BS_PUSHBUTTON)
{
// Losing default state always allowed
m_bIsDefault = FALSE;
} // if
// Can't change control type after owner-draw is set.
// Let the system process changes to other style bits
// and redrawing, while keeping owner-draw style
return DefWindowProc(BM_SETSTYLE,
(wParam & ~BS_TYPEMASK) | BS_OWNERDRAW, lParam);
} // End of OnSetStyle
LRESULT CButtonST::OnSetCheck(WPARAM wParam, LPARAM lParam)
{
ASSERT(m_bIsCheckBox);
switch (wParam)
{
case BST_CHECKED:
case BST_INDETERMINATE: // Indeterminate state is handled like checked state
SetCheck(1);
break;
default:
SetCheck(0);
break;
} // switch
return 0;
} // End of OnSetCheck
LRESULT CButtonST::OnGetCheck(WPARAM wParam, LPARAM lParam)
{
ASSERT(m_bIsCheckBox);
return GetCheck();
} // End of OnGetCheck
#ifdef BTNST_USE_BCMENU
LRESULT CButtonST::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu)
{
LRESULT lResult;
if (BCMenu::IsMenu(pMenu))
lResult = BCMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
else
lResult = CButton::OnMenuChar(nChar, nFlags, pMenu);
return lResult;
} // End of OnMenuChar
#endif
#ifdef BTNST_USE_BCMENU
void CButtonST::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
BOOL bSetFlag = FALSE;
if (lpMeasureItemStruct->CtlType == ODT_MENU)
{
if (IsMenu((HMENU)lpMeasureItemStruct->itemID) && BCMenu::IsMenu((HMENU)lpMeasureItemStruct->itemID))
{
m_menuPopup.MeasureItem(lpMeasureItemStruct);
bSetFlag = TRUE;
} // if
} // if
if (!bSetFlag) CButton::OnMeasureItem(nIDCtl, lpMeas