www.pudn.com > HCdemo.zip > ButtonSSL.cpp
// CButtonSSL.cpp : implementation file
//
#include "stdafx.h"
#include "ButtonSSL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DROP_BUTTON_WIDTH 16
#define BS_TYPEMASK SS_TYPEMASK
/////////////////////////////////////////////////////////////////////////////
// CButtonSSL
/////////////////////////////////////////////////////////////////////////////
// Construction
CButtonSSL::CButtonSSL () : COddButton () {
m_bImageLoaded = FALSE;
m_bMenuLoaded = FALSE;
m_bMenuPushed = FALSE;
m_bBtnPushed = FALSE;
m_bMouseOnBtn = FALSE;
m_nStyle = SSL_BS_FLAT;
m_nTextAlign = SSL_TEXT_CENTER | SSL_TEXT_VCENTER;
m_nImageAlign = SSL_IMAGE_LEFT | SSL_IMAGE_TOP;
m_nImageWidth = 0;
m_nImageHeight = 0;
m_ToolTip.m_hWnd = NULL;
m_hCursor = NULL;
SetSSLDefaultColors (FALSE);
ZeroMemory(&m_bmp, sizeof m_bmp);
ZeroMemory(&m_szURL, sizeof(m_szURL));
m_bsState = SSL_STATE_UP;
m_nCheck = 0;
}
/////////////////////////////////////////////////////////////////////////////
// Destruction
CButtonSSL::~CButtonSSL () {
m_font.DeleteObject ();
}
BEGIN_MESSAGE_MAP(CButtonSSL, COddButton)
//{{AFX_MSG_MAP(CButtonSSL)
ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_SETFOCUS()
ON_WM_SETCURSOR()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
ON_MESSAGE (BM_GETCHECK, OnGetCheck)
ON_MESSAGE (BM_SETCHECK, OnSetCheck)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CButtonSSL message handlers
void CButtonSSL::PreSubclassWindow() {
// Determine what type of button this is
COddButton::PreSubclassWindow ();
if (NULL == (HFONT)m_font) {
// If a font isn't already set, get the default font
CFont* pFont = GetFont();
if (!pFont) {
HFONT hFont = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
if (NULL == hFont) {
hFont = (HFONT) GetStockObject (ANSI_VAR_FONT);
}
if (hFont) {
pFont = CFont::FromHandle (hFont);
}
}
ASSERT (pFont->GetSafeHandle ());
LOGFONT lf;
pFont->GetLogFont (&lf);
m_font.CreateFontIndirect (&lf);
}
}
// Thanks to Tomasz Sowinski for helping me with the DDX problems
LRESULT CButtonSSL::OnGetCheck () {
UINT nType = GetControlType ();
if (BS_CHECKBOX == (BS_CHECKBOX & nType) ||
BS_AUTOCHECKBOX == (BS_AUTOCHECKBOX & nType) ||
BS_RADIOBUTTON == (BS_RADIOBUTTON & nType) ||
BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & nType)) {
if (0 == m_nCheck) {
return BST_UNCHECKED;
}
else {
return BST_CHECKED;
}
}
return 0;
}
// Thanks to Tomasz Sowinski for helping me with the DDX problems
LRESULT CButtonSSL::OnSetCheck (WPARAM fCheck) {
if (BST_CHECKED == fCheck) {
m_nCheck = 1;
m_bBtnPushed = TRUE;
}
else if (BST_UNCHECKED == fCheck) {
m_nCheck = 0;
m_bBtnPushed = FALSE;
}
Invalidate ();
return 0;
}
BOOL CButtonSSL::OnClicked () {
// Update the check state for radio buttons and check boxes
UINT nType = GetControlType ();
if (BS_CHECKBOX == (BS_CHECKBOX & nType) || BS_AUTOCHECKBOX== (BS_AUTOCHECKBOX & nType) /*||
BS_RADIOBUTTON & nType || BS_AUTORADIOBUTTON & nType*/) {
m_nCheck = !m_nCheck;
m_bBtnPushed = !m_bBtnPushed;
Invalidate ();
}
else if (BS_RADIOBUTTON == (BS_RADIOBUTTON & nType) ||
BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & nType)) {
// Send BM_SETCHECK (BST_CHECKED) to this button nad
// BM_SETCHECK (BST_UNCHECKED) to all other buttons in this group
SendMessage (BM_SETCHECK, BST_CHECKED, 0);
// Start by searching forwards
HWND hWndDlg = this->GetParent ()->m_hWnd;
CWnd* pWnd = FromHandle (::GetNextDlgGroupItem (hWndDlg, this->m_hWnd, FALSE));
while (NULL != pWnd && this != pWnd) {
pWnd->SendMessage (BM_SETCHECK, BST_UNCHECKED, 0);
pWnd = FromHandle (::GetNextDlgGroupItem (hWndDlg, pWnd->m_hWnd, FALSE));
}
// Then search backwards
pWnd = FromHandle (::GetNextDlgGroupItem (hWndDlg, this->m_hWnd, TRUE));
while (NULL != pWnd && this != pWnd) {
pWnd->SendMessage (BM_SETCHECK, BST_UNCHECKED, 0);
pWnd = FromHandle (::GetNextDlgGroupItem (hWndDlg, pWnd->m_hWnd, TRUE));
}
}
else {
// Handle the URL (if any)
if (::lstrlen(m_szURL) > 0) {
::ShellExecute(NULL, _T("open"), m_szURL, NULL, NULL, SW_SHOWMAXIMIZED);
}
}
return FALSE; // Allow the parent to handle the click event
}
void CButtonSSL::OnMouseMove (UINT nFlags, CPoint point) {
CWnd* pWnd; // Active window
CWnd* pParent; // Window that owns the button
CButton::OnMouseMove (nFlags, point);
// Ignore if left button pressed on entering button
if ((nFlags & MK_LBUTTON) && FALSE == m_bMouseOnBtn) {
return;
}
pWnd = GetActiveWindow();
pParent = GetOwner();
if ((GetCapture () != this) && (pParent != NULL)) {
m_bMouseOnBtn = TRUE;
SetCapture ();
Invalidate ();
}
else {
ClientToScreen (&point);
CWnd* wndUnderMouse = WindowFromPoint (point);
if (NULL != wndUnderMouse && wndUnderMouse->m_hWnd != this->m_hWnd) {
// Redraw only if mouse goes out
if (TRUE == m_bMouseOnBtn) {
m_bMouseOnBtn = FALSE;
Invalidate ();
}
// Release capture if the left button is not pressed
if (!(nFlags & MK_LBUTTON)) {
ReleaseCapture ();
}
}
}
}
void CButtonSSL::OnLButtonDown(UINT nFlags, CPoint point) {
if (TRUE == m_bMenuPushed) {
m_bMenuPushed = FALSE;
Invalidate();
return;
}
// Show the menu if the click is on the drop-arrow
// and the SSL_BS_MENU_BTN style is set
if (TRUE == HitMenuButton(point) && (SSL_BS_MENU_BTN & m_nStyle)) {
m_bMenuPushed = TRUE;
Invalidate();
CRect rect;
GetWindowRect (rect);
int x = rect.right;
int y = rect.bottom;
CMenu* pMenu = m_menu.GetSubMenu (0);
pMenu->TrackPopupMenu (TPM_RIGHTALIGN | TPM_LEFTBUTTON, x, y, GetParent ());
m_bMenuPushed = FALSE;
}
else {
m_bBtnPushed = TRUE;
}
Invalidate();
CButton::OnLButtonDown (nFlags, point);
}
void CButtonSSL::OnLButtonUp(UINT nFlags, CPoint point) {
CButton::OnLButtonUp (nFlags, point);
// Check box state updating done in Clicked handler
UINT nType = GetControlType ();
if (BS_CHECKBOX != (BS_CHECKBOX & nType) &&
BS_AUTOCHECKBOX != (BS_AUTOCHECKBOX & nType) &&
BS_RADIOBUTTON != (BS_RADIOBUTTON & nType) &&
BS_AUTORADIOBUTTON != (BS_AUTORADIOBUTTON & nType)) {
if (TRUE == m_bBtnPushed) {
m_bBtnPushed = FALSE;
ReleaseCapture();
Invalidate();
}
}
}
void CButtonSSL::OnSetFocus(CWnd* pOldWnd) {
CButton::OnSetFocus (pOldWnd);
Invalidate ();
}
BOOL CButtonSSL::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {
// Use the specifed cursor if there is one
if (NULL != m_hCursor) {
::SetCursor (m_hCursor);
return TRUE;
}
return CButton::OnSetCursor(pWnd, nHitTest, message);
}
HBRUSH CButtonSSL::CtlColor (CDC* pDC, UINT nCtlColor) {
return (HBRUSH)::GetStockObject (NULL_BRUSH);
}
void CButtonSSL::DrawBackground (CDC* pDC, LPCRECT pRect) {
COLORREF crColor = ::GetSysColor (COLOR_BTNFACE);
if (SSL_STATE_UP == m_bsState) {
crColor = m_crColors[SSL_UP_BK_COLOR];
}
if (SSL_STATE_OVER == m_bsState) {
crColor = m_crColors[SSL_OVER_BK_COLOR];
}
if (SSL_STATE_DOWN == m_bsState) {
crColor = m_crColors[SSL_DOWN_BK_COLOR];
}
CBrush brBackground(crColor);
pDC->FillRect(pRect, &brBackground);
}
void CButtonSSL::DrawBorder (CDC* pDC, LPRECT lpRect) {
if (TRUE == m_bBtnPushed) {
pDC->Draw3dRect (lpRect, ::GetSysColor (COLOR_BTNSHADOW), ::GetSysColor (COLOR_BTNHIGHLIGHT));
return;
}
if (!(SSL_BS_FLAT & m_nStyle)) {
if (TRUE == m_bBtnPushed) {
pDC->DrawFrameControl (lpRect, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);
}
else {
pDC->DrawFrameControl (lpRect, DFC_BUTTON, DFCS_BUTTONPUSH);
}
return;
}
if (TRUE == m_bMouseOnBtn && FALSE == m_bBtnPushed) {
pDC->Draw3dRect (lpRect, ::GetSysColor (COLOR_BTNHIGHLIGHT), ::GetSysColor (COLOR_BTNSHADOW));
}
}
void CButtonSSL::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
if (lpDrawItemStruct->CtlType != ODT_BUTTON) {
return;
}
CDC cdcMem;
CBitmap bmp;
CRect btnRect (lpDrawItemStruct->rcItem);
CRect trueRect (btnRect);
CDC* pDC = CDC::FromHandle (lpDrawItemStruct->hDC);
// Check to see if it's a checked checkbox or radio button
UINT nType = GetControlType ();
if ((BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & nType) ||
BS_RADIOBUTTON == (BS_RADIOBUTTON & nType) ||
BS_AUTOCHECKBOX == (BS_AUTOCHECKBOX & nType) ||
BS_CHECKBOX == (BS_CHECKBOX & nType)) &&
FALSE == m_bBtnPushed) {
if (0 == m_nCheck) {
m_bBtnPushed = FALSE;
}
else {
m_bBtnPushed = TRUE;
}
}
// Check to see if the button is disabled
m_bDisabled = (ODS_DISABLED == (ODS_DISABLED & lpDrawItemStruct->itemState));
// Update the button state
if (TRUE == m_bDisabled) {
m_bsState = SSL_STATE_DISABLED;
}
else {
m_bsState = SSL_STATE_UP;
if (TRUE == m_bMouseOnBtn) {
m_bsState = SSL_STATE_OVER;
}
if (TRUE == m_bBtnPushed) {
m_bsState = SSL_STATE_DOWN;
}
}
#ifdef _TRACESTATE
TraceState (m_bsState);
#endif
if (TRUE == IsDefault ()) {
btnRect.DeflateRect (1, 1);
}
// Button Background and Border
DrawBackground (pDC, &trueRect);
DrawBorder (pDC, &btnRect);
CRect rectFocus (btnRect); // Focus rectangle
rectFocus.DeflateRect (3, 3);
if (SSL_BS_MENU_BTN & m_nStyle) {
rectFocus.right -= DROP_BUTTON_WIDTH; // Exclude drop button from focus rectangle
}
// Default Button State
if (TRUE == IsDefault () && FALSE == m_bDisabled && !(SSL_BS_FLAT & m_nStyle)) {
pDC->FrameRect (&lpDrawItemStruct->rcItem,
CBrush::FromHandle ((HBRUSH)GetStockObject (BLACK_BRUSH)));
if (TRUE == m_bBtnPushed && FALSE == m_bMenuPushed) {
pDC->FrameRect (&btnRect, CBrush::FromHandle (GetSysColorBrush (COLOR_3DSHADOW)));
}
}
// State Focus
if ((lpDrawItemStruct->itemState & ODS_FOCUS || TRUE == m_bBtnPushed) && !(SSL_BS_FLAT & m_nStyle) &&
BS_AUTOCHECKBOX != (BS_AUTOCHECKBOX & nType) && BS_CHECKBOX != (BS_CHECKBOX & nType)) {
if (FALSE == m_bMenuPushed) {
pDC->DrawFocusRect (&rectFocus);
}
}
// Action Focus
if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && !(SSL_BS_FLAT & m_nStyle)) {
if (FALSE == m_bMenuPushed) {
pDC->DrawFocusRect (&rectFocus);
}
}
// Draw the image on the button.
// Extract the image as an icon regardless of what was added originally
if (TRUE == m_bImageLoaded) {
HICON hIcon = m_imageList.ExtractIcon (m_bsState);
// Defer to the Up image. This should only happen if there isn't a disabled image
if (NULL == hIcon) {
hIcon = m_imageList.ExtractIcon (SSL_STATE_UP);
pDC->DrawState (GetImagePoint (trueRect),
CSize (m_nImageWidth, m_nImageHeight), hIcon,
DST_ICON | (m_bsState == SSL_STATE_DISABLED ? DSS_DISABLED : DSS_NORMAL), (CBrush*)NULL);
}
else {
pDC->DrawState (GetImagePoint (trueRect),
CSize (m_nImageWidth, m_nImageHeight), hIcon,
DST_ICON | DSS_NORMAL, (CBrush*)NULL);
}
}
// Draw out text
pDC->SelectObject (&m_font);
CRect rectText (rectFocus);
CString strCaption;
GetWindowText (strCaption);
pDC->SetBkMode (TRANSPARENT);
if (ODS_DISABLED & lpDrawItemStruct->itemState) {
pDC->SetBkColor (GetSysColor (COLOR_BTNFACE));
rectFocus.OffsetRect (1,1);
pDC->SetTextColor (GetSysColor (COLOR_WINDOW));
pDC->DrawText (strCaption, rectFocus, DT_SINGLELINE | m_nTextAlign);
rectFocus.OffsetRect (-1,-1);
pDC->SetTextColor (GetSysColor (COLOR_GRAYTEXT));
pDC->DrawText (strCaption, rectFocus, DT_SINGLELINE | m_nTextAlign);
}
else {
if (SSL_STATE_UP == m_bsState) {
pDC->SetBkColor (m_crColors[SSL_UP_BK_COLOR]);
pDC->SetTextColor (m_crColors[SSL_UP_TEXT_COLOR]);
}
if (SSL_STATE_OVER == m_bsState ) {
pDC->SetBkColor (m_crColors[SSL_OVER_BK_COLOR]);
pDC->SetTextColor (m_crColors[SSL_OVER_TEXT_COLOR]);
}
if (SSL_STATE_DOWN == m_bsState) {
pDC->SetBkColor (m_crColors[SSL_DOWN_BK_COLOR]);
pDC->SetTextColor (m_crColors[SSL_DOWN_TEXT_COLOR]);
}
pDC->DrawText (strCaption, rectFocus, DT_SINGLELINE | m_nTextAlign);
}
if (SSL_BS_MENU_BTN & m_nStyle) {
// Drop down split
CRect rectSplit (btnRect);
rectSplit.DeflateRect (2,2);
rectSplit.right -= DROP_BUTTON_WIDTH;
if (!(SSL_BS_FLAT & m_nStyle) || TRUE == m_bMouseOnBtn) {
CPen brFace (PS_SOLID, 1, ::GetSysColor (COLOR_BTNSHADOW));
pDC->SelectObject (&brFace);
pDC->MoveTo (rectSplit.right, rectSplit.top);
pDC->LineTo (rectSplit.right, rectSplit.bottom);
CPen brLite (PS_SOLID, 1, ::GetSysColor (COLOR_BTNHIGHLIGHT));
pDC->SelectObject (&brLite);
pDC->MoveTo (rectSplit.right + 1 , rectSplit.top);
pDC->LineTo (rectSplit.right + 1, rectSplit.bottom);
}
rectSplit.left = rectSplit.right;
rectSplit.right += DROP_BUTTON_WIDTH;
CPoint pt (rectSplit.CenterPoint ());
pt += CPoint (m_bBtnPushed, m_bBtnPushed);
CPen penBlack (PS_SOLID, 1, m_bDisabled ?
GetSysColor (COLOR_GRAYTEXT) : GetSysColor (COLOR_WINDOWTEXT));
pDC->SelectObject (&penBlack);
DrawArrow (pDC, pt);
// Drop down state
if (TRUE == m_bMenuPushed && FALSE == m_bDisabled) {
rectSplit.InflateRect (1, 1);
pDC->DrawEdge (rectSplit, BDR_SUNKENOUTER, BF_RECT);
}
}
}
BOOL CButtonSSL::PreTranslateMessage(MSG* pMsg)
{
// Initialise the tooltip if necessary
InitToolTipCtrl ();
m_ToolTip.RelayEvent (pMsg);
return CButton::PreTranslateMessage(pMsg);
}
/////////////////////////////////////////////////////////////////////////////
// CButtonSSL implementation
/////////////////////////////////////////////////////////////////////////////
// Initialisation
void CButtonSSL::SetSSLButtonStyle (UINT nStyle) {
m_nStyle = nStyle;
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
if (TRUE == IsDefault ()) {
PostMessage (BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
}
else {
PostMessage (BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
}
}
UINT CButtonSSL::GetSSLButtonStyle () {
return m_nStyle;
}
/////////////////////////////////////////////////////////////////////////////
// Image Functions
BOOL CButtonSSL::SetSSLButtonBitmap(UINT nResourceID, COLORREF crMask) {
BOOL bReturn = m_bmpImage.LoadBitmap (nResourceID);
if (TRUE == bReturn) {
m_bmpImage.GetObject (sizeof m_bmp, &m_bmp);
m_nImageWidth = m_bmp.bmWidth;
m_nImageHeight = m_bmp.bmHeight;
if (NULL != m_imageList.m_hImageList) {
m_imageList.Detach ();
}
bReturn = m_imageList.Create (m_bmp.bmWidth, m_bmp.bmHeight, ILC_MASK | ILC_COLOR32, 1, 1);
if (TRUE == bReturn) {
if (m_imageList.Add (&m_bmpImage, crMask) > -1) {
m_bImageLoaded = TRUE;
}
else {
m_bImageLoaded = FALSE;
}
}
else {
m_bImageLoaded = FALSE;
}
}
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
BOOL CButtonSSL::SetSSLButtonBitmaps (UINT nUpID, COLORREF crUpMask,
UINT nOverID/* = 0*/, COLORREF crOverMask/* = SSL_MASK*/,
UINT nDownID/* = 0*/, COLORREF crDownMask/* = SSL_MASK*/,
UINT nDisabledID/* = 0*/, COLORREF crDisabledMask/* = SSL_MASK*/) {
ASSERT (0 != nUpID);
BOOL bReturn = m_bmpImage.LoadBitmap (nUpID);
if (TRUE == bReturn) {
m_bmpImage.GetObject (sizeof m_bmp, &m_bmp);
m_nImageWidth = m_bmp.bmWidth;
m_nImageHeight = m_bmp.bmHeight;
if (NULL != m_imageList.m_hImageList) {
m_imageList.Detach ();
}
bReturn = m_imageList.Create (m_nImageWidth, m_nImageHeight, ILC_MASK | ILC_COLOR32, 4, 0);
if (TRUE == bReturn) {
if (m_imageList.Add (&m_bmpImage, crUpMask) > -1) {
m_bImageLoaded = TRUE;
BOOL bOver = FALSE;
// Add the Over image
if (nOverID > 0) {
AddBitmap (nOverID, crOverMask);
bOver = TRUE;
}
else {
// Use Up image if Over not supplied
AddBitmap (nUpID, crUpMask);
}
// Add the Down image
if (nDownID > 0) {
AddBitmap (nDownID, crDownMask);
}
else {
// If there's no Down image supplied
if (TRUE == bOver) {
// Use the Over image is supplied
AddBitmap (nOverID, crOverMask);
}
else {
// Otherwise use the Up image
AddBitmap (nUpID, crUpMask);
}
}
// Add the Disabled image
// If one isn't one DrawState will use the Up image and draw it disabled.
if (nDisabledID > 0) {
AddBitmap (nDisabledID, crDisabledMask);
}
}
else {
m_bImageLoaded = FALSE;
}
}
}
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
BOOL CButtonSSL::SetSSLButtonIcon(UINT nResourceID) {
BOOL bReturn = FALSE;
HINSTANCE hInstance = AfxFindResourceHandle (MAKEINTRESOURCE (nResourceID), RT_GROUP_ICON);
m_hIcon = (HICON)::LoadImage (hInstance, MAKEINTRESOURCE (nResourceID), IMAGE_ICON, 0, 0, 0);
if (NULL != m_hIcon) {
ICONINFO iconInfo;
ZeroMemory (&iconInfo, sizeof (ICONINFO));
bReturn = ::GetIconInfo (m_hIcon, &iconInfo);
if (TRUE == bReturn) {
m_nImageWidth = iconInfo.xHotspot * 2;
m_nImageHeight = iconInfo.yHotspot * 2;
::DeleteObject(iconInfo.hbmMask);
::DeleteObject(iconInfo.hbmColor);
if (NULL != m_imageList.m_hImageList) {
m_imageList.Detach ();
}
bReturn = m_imageList.Create (m_nImageWidth, m_nImageHeight, ILC_MASK | ILC_COLOR32, 1, 1);
if (TRUE == bReturn) {
if (m_imageList.Add (m_hIcon) > -1) {
m_bImageLoaded = TRUE;
}
else {
m_bImageLoaded = FALSE;
}
}
}
}
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
BOOL CButtonSSL::SetSSLButtonIcons (UINT nUpID, UINT nOverID/* = 0*/,
UINT nDownID/* = 0*/, UINT nDisabledID/* = 0*/) {
ASSERT (0 != nUpID);
BOOL bReturn = FALSE;
HINSTANCE hInstance = AfxFindResourceHandle (MAKEINTRESOURCE (nUpID), RT_GROUP_ICON);
m_hIcon = (HICON)::LoadImage (hInstance, MAKEINTRESOURCE (nUpID), IMAGE_ICON, 0, 0, 0);
if (NULL != m_hIcon) {
ICONINFO iconInfo;
ZeroMemory (&iconInfo, sizeof (ICONINFO));
bReturn = ::GetIconInfo (m_hIcon, &iconInfo);
if (TRUE == bReturn) {
m_nImageWidth = iconInfo.xHotspot * 2;
m_nImageHeight = iconInfo.yHotspot * 2;
::DeleteObject (iconInfo.hbmMask);
::DeleteObject (iconInfo.hbmColor);
if (NULL != m_imageList.m_hImageList) {
m_imageList.Detach ();
}
bReturn = m_imageList.Create (m_nImageWidth, m_nImageHeight, ILC_MASK | ILC_COLOR32, 4, 0);
if (TRUE == bReturn) {
if (m_imageList.Add (m_hIcon) > -1) {
m_bImageLoaded = TRUE;
BOOL bOver = FALSE;
// Add the Over image
if (nOverID > 0) {
AddIcon (nOverID);
bOver = TRUE;
}
else {
// Use Up image if Over not supplied
AddIcon (nUpID);
}
// Add the Down image
if (nDownID > 0) {
AddIcon (nDownID);
}
else {
// If there's no Down image supplied
if (TRUE == bOver) {
// Use the Over image is supplied
AddIcon (nOverID);
}
else {
// Otherwise use the Up image
AddIcon (nUpID);
}
}
// Add the Disabled image
// If one isn't one DrawState will use the Up image and draw it disabled.
if (nDisabledID > 0) {
AddIcon (nDisabledID);
}
}
else {
m_bImageLoaded = FALSE;
}
}
}
}
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
void CButtonSSL::SetSSLImageAlign (UINT nImageAlign) {
m_nImageAlign = nImageAlign;
Invalidate ();
}
UINT CButtonSSL::GetSSLImageAlign () {
return m_nImageAlign;
}
/////////////////////////////////////////////////////////////////////////////
// Text Functions
void CButtonSSL::SetSSLTextAlign (UINT nTextAlign) {
m_nTextAlign = nTextAlign;
Invalidate ();
}
UINT CButtonSSL::GetSSLTextAlign () {
return m_nTextAlign;
}
BOOL CButtonSSL::SetSSLButtonFont (LPCTSTR lpszFaceName, int nSizePoints/* = 8*/,
BOOL bUnderline/* = FALSE*/, BOOL bBold/* = FALSE*/,
BOOL bStrikeOut/* = FALSE*/, BOOL bItalic/* = FALSE*/) {
if (NULL != (HFONT)m_font) {
m_font.DeleteObject ();
}
CDC* pDC = GetDC ();
LOGFONT lf;
memset (&lf, 0, sizeof(LOGFONT));
strcpy (lf.lfFaceName, lpszFaceName);
lf.lfHeight = -MulDiv (nSizePoints, GetDeviceCaps (pDC->m_hDC, LOGPIXELSY), 72);
lf.lfUnderline = bUnderline;
if (TRUE == bBold) {
lf.lfWeight = FW_BOLD;
}
lf.lfStrikeOut = bStrikeOut;
lf.lfItalic = bItalic;
BOOL bReturn = m_font.CreateFontIndirect (&lf);
Invalidate ();
ReleaseDC (pDC);
return bReturn;
}
BOOL CButtonSSL::SetSSLButtonFont (CFont& font) {
if (NULL != (HFONT)m_font) {
m_font.DeleteObject ();
}
LOGFONT lf;
font.GetLogFont (&lf);
BOOL bReturn = m_font.CreateFontIndirect (&lf);
Invalidate ();
return bReturn;
}
/////////////////////////////////////////////////////////////////////////////
// Colour Functions
void CButtonSSL::SetSSLDefaultColors (BOOL bRedraw/* = TRUE*/) {
m_crColors[SSL_UP_BK_COLOR] = ::GetSysColor(COLOR_BTNFACE);
m_crColors[SSL_UP_TEXT_COLOR] = ::GetSysColor(COLOR_BTNTEXT);
m_crColors[SSL_OVER_BK_COLOR] = ::GetSysColor(COLOR_BTNFACE);
m_crColors[SSL_OVER_TEXT_COLOR] = ::GetSysColor(COLOR_BTNTEXT);
m_crColors[SSL_DOWN_BK_COLOR] = ::GetSysColor(COLOR_BTNFACE);
m_crColors[SSL_DOWN_TEXT_COLOR] = ::GetSysColor(COLOR_BTNTEXT);
if (TRUE == bRedraw) {
Invalidate();
}
}
BOOL CButtonSSL::SetSSLColor (BYTE byColorIndex, COLORREF crColor, BOOL bRedraw/* = TRUE*/) {
if (byColorIndex > SSL_MAX_COLORS) {
return FALSE;
}
m_crColors[byColorIndex] = crColor;
if (TRUE == bRedraw) {
Invalidate ();
}
return TRUE;
}
BOOL CButtonSSL::GetSSLColor (BYTE byColorIndex, COLORREF* pcrColor) {
if (byColorIndex > SSL_MAX_COLORS) {
return FALSE;
}
*pcrColor = m_crColors[byColorIndex];
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Check Box Functions
void CButtonSSL::SetSSLCheck (int nCheck, BOOL bRedraw/* = TRUE*/) {
UINT nType = GetControlType ();
if (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & nType) ||
BS_RADIOBUTTON == (BS_RADIOBUTTON & nType) ||
BS_AUTOCHECKBOX == (BS_AUTOCHECKBOX & nType) ||
BS_CHECKBOX == (BS_CHECKBOX & nType)) {
if (0 == nCheck) {
m_nCheck = 0;
}
else {
m_nCheck = 1;
}
if (TRUE == bRedraw) {
Invalidate ();
}
}
}
int CButtonSSL::GetSSLCheck () {
return m_nCheck;
}
/////////////////////////////////////////////////////////////////////////////
// Menu Functions
BOOL CButtonSSL::SetSSLButtonMenu (UINT nMenuResourceID) {
// Ensure the SSL_BS_MENU_BTN style is set
m_nStyle |= SSL_BS_MENU_BTN;
if (NULL != m_menu.m_hMenu) {
m_menu.DestroyMenu ();
}
BOOL bReturn = m_menu.LoadMenu (nMenuResourceID);
m_bMenuLoaded |= bReturn;
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
BOOL CButtonSSL::SetSSLButtonMenu (LPCTSTR lpszResourceName) {
// Ensure the SSL_BS_MENU_BTN style is set
m_nStyle |= SSL_BS_MENU_BTN;
if (NULL != m_menu.m_hMenu) {
m_menu.DestroyMenu ();
}
BOOL bReturn = m_menu.LoadMenu (lpszResourceName);
m_bMenuLoaded |= bReturn;
// Resize the button if necessary
if (SSL_BS_AUTOSIZE == (SSL_BS_AUTOSIZE & m_nStyle)) {
SetSize ();
}
return bReturn;
}
UINT CButtonSSL::CheckSSLMenuItem (UINT nIDCheckItem, UINT nCheck/* = MF_CHECKED*/) {
if (FALSE == m_bMenuLoaded) {
return MF_DOES_NOT_EXIST;
}
return m_menu.CheckMenuItem (nIDCheckItem, nCheck);
}
BOOL CButtonSSL::CheckSSLMenuRadioItem (UINT nIDFirst, UINT nIDLast, UINT nIDItem, UINT nFlags) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.CheckMenuRadioItem (nIDFirst, nIDLast, nIDItem, nFlags);
}
UINT CButtonSSL::EnableSSLMenuItem (UINT nIDEnableItem, UINT nEnable) {
if (FALSE == m_bMenuLoaded) {
return MF_DOES_NOT_EXIST;
}
return m_menu.EnableMenuItem (nIDEnableItem, nEnable);
}
UINT CButtonSSL::GetSSLMenuItemCount () const {
if (FALSE == m_bMenuLoaded) {
return MF_DOES_NOT_EXIST;
}
return m_menu.GetMenuItemCount ();
}
UINT CButtonSSL::GetSSLMenuItemID (int nPos) const {
if (FALSE == m_bMenuLoaded) {
return MF_DOES_NOT_EXIST;
}
return m_menu.GetMenuItemID (nPos);
}
UINT CButtonSSL::GetSSLMenuState (UINT nID, UINT nFlags) {
if (FALSE == m_bMenuLoaded) {
return MF_DOES_NOT_EXIST;
}
return m_menu.GetMenuState (nID, nFlags);
}
int CButtonSSL::GetSSLMenuString (UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) {
if (FALSE == m_bMenuLoaded) {
return 0;
}
return m_menu.GetMenuString (nIDItem, lpString, nMaxCount, nFlags);
}
int CButtonSSL::GetSSLMenuString (UINT nIDItem, CString& rString, UINT nFlags) {
if (FALSE == m_bMenuLoaded) {
return 0;
}
return m_menu.GetMenuString (nIDItem, rString, nFlags);
}
BOOL CButtonSSL::GetSSLMenuItemInfo (UINT nIDItem, LPMENUITEMINFO lpMenuItemInfo,
BOOL ByPos/*=FALSE*/) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.GetMenuItemInfo (nIDItem, lpMenuItemInfo, ByPos);
}
BOOL CButtonSSL::ModifySSLMenu (UINT nPosition, UINT nFlags, UINT nIDNewItem/*=0*/,
LPCTSTR lpszNewItem/*=NULL*/) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.ModifyMenu (nPosition, nFlags, nIDNewItem, lpszNewItem);
}
BOOL CButtonSSL::ModifySSLMenu (UINT nPosition, UINT nFlags, UINT nIDNewItem,
const CBitmap* pBmp) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.ModifyMenu (nPosition, nFlags, nIDNewItem, pBmp);
}
BOOL CButtonSSL::RemoveSSLMenu (UINT nPosition, UINT nFlags) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.RemoveMenu (nPosition, nFlags);
}
BOOL CButtonSSL::SetSSLMenuItemBitmaps (UINT nPosition, UINT nFlags,
const CBitmap* pBmpUnchecked,
const CBitmap* pBmpChecked) {
if (FALSE == m_bMenuLoaded) {
return FALSE;
}
return m_menu.SetMenuItemBitmaps (nPosition, nFlags, pBmpUnchecked,
pBmpChecked);
}
/////////////////////////////////////////////////////////////////////////////
// Miscellaneous Functions
BOOL CButtonSSL::SetSSLButtonCursor (UINT nResourceID) {
HINSTANCE hInstResource;
// Destroy any previous cursor
if (NULL != m_hCursor) {
::DestroyCursor (m_hCursor);
m_hCursor = NULL;
}
// If we want a cursor
if (nResourceID != NULL) {
hInstResource = AfxFindResourceHandle (MAKEINTRESOURCE (nResourceID), RT_GROUP_CURSOR);
// Load icon resource
m_hCursor = (HCURSOR)::LoadImage (hInstResource, MAKEINTRESOURCE (nResourceID),
IMAGE_CURSOR, 0, 0, 0);
// If something wrong then return FALSE
if (NULL == m_hCursor) {
return FALSE;
}
}
return TRUE;
}
void CButtonSSL::SetSSLButtonToolTip (LPCTSTR lpszTipText, BOOL bActivate) {
// Can't have a NULL text string
if (NULL == lpszTipText) {
return;
}
// Initialise the tooltip
InitToolTipCtrl ();
// Need to add a tooltip if none defined
if (0 == m_ToolTip.GetToolCount ()) {
CRect rectBtn;
GetClientRect (rectBtn);
m_ToolTip.AddTool (this, lpszTipText, rectBtn, 1);
}
// Set the text
m_ToolTip.UpdateTipText (lpszTipText, this, 1);
m_ToolTip.Activate (bActivate);
}
void CButtonSSL::SetSSLButtonToolTip (UINT nResourceID, BOOL bActivate) {
CString strTipText;
strTipText.LoadString (nResourceID);
if (FALSE == strTipText.IsEmpty ()) {
SetSSLButtonToolTip ((LPCTSTR)strTipText, bActivate);
}
}
void CButtonSSL::GetSSLButtonToolTip (CString& strTipText) {
m_ToolTip.GetText (strTipText, this, 1);
}
// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CButtonSSL::SetSSLButtonURL (LPCTSTR lpszURL) {
if (NULL != lpszURL) {
// Store the URL
::lstrcpyn(m_szURL, lpszURL, _MAX_PATH);
if (NULL == m_hCursor) {
// Try to load the 'standard' hand cursor
CString szWndDir;
GetWindowsDirectory (szWndDir.GetBuffer (MAX_PATH), MAX_PATH);
szWndDir.ReleaseBuffer ();
// Try cursor #106 in WinHlp32.exe
CString szHlp32 = szWndDir + _T("\\winhlp32.exe");
HMODULE hModule = LoadLibrary (szHlp32);
if (NULL != hModule) {
HCURSOR hHandCursor;
hHandCursor = ::LoadCursor (hModule, MAKEINTRESOURCE (106));
if (NULL != hHandCursor) {
m_hCursor = CopyCursor (hHandCursor);
}
}
}
}
else {
// Remove any existing URL
::ZeroMemory(&m_szURL, sizeof(m_szURL));
}
}
/////////////////////////////////////////////////////////////////////////////
// CButtonSSL helper functions
void CButtonSSL::DrawArrow (CDC* pDC, CPoint ptTip) {
CPoint ptDest;
pDC->SetPixel (ptTip, RGB (0, 0, 0));
ptTip -= CPoint (1, 1);
pDC->MoveTo (ptTip);
ptDest = ptTip;
ptDest += CPoint (3, 0);
pDC->LineTo (ptDest);
ptTip -= CPoint (1, 1);
pDC->MoveTo (ptTip);
ptDest = ptTip;
ptDest += CPoint (5, 0);
pDC->LineTo (ptDest);
ptTip -= CPoint (1, 1);
pDC->MoveTo (ptTip);
ptDest = ptTip;
ptDest += CPoint (7, 0);
pDC->LineTo (ptDest);
}
BOOL CButtonSSL::HitMenuButton (CPoint pt)
{
if (FALSE == m_bMenuLoaded)
return FALSE; // Don't allow menu button drop down if no menu items are loaded
ClientToScreen(&pt);
CRect rect;
GetWindowRect (rect);
rect.left = rect.right - DROP_BUTTON_WIDTH;
return rect.PtInRect (pt);
}
void CButtonSSL::InitToolTipCtrl () {
if (NULL == m_ToolTip.m_hWnd) {
m_ToolTip.Create (this);
m_ToolTip.Activate(FALSE); // Inactive initially
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 300); // Enable multiline tooltip
}
}
void CButtonSSL::AddBitmap (UINT nResourceID, COLORREF crMask) {
m_bmpImage.Detach ();
m_bmpImage.LoadBitmap (nResourceID);
m_imageList.Add (&m_bmpImage, crMask);
}
void CButtonSSL::AddIcon (UINT nResourceID) {
HINSTANCE hInstance = AfxFindResourceHandle (MAKEINTRESOURCE (nResourceID), RT_GROUP_ICON);
m_hIcon = (HICON)::LoadImage (hInstance, MAKEINTRESOURCE (nResourceID), IMAGE_ICON, 0, 0, 0);
if (NULL != m_hIcon) {
ICONINFO iconInfo;
ZeroMemory (&iconInfo, sizeof (ICONINFO));
::GetIconInfo (m_hIcon, &iconInfo);
::DeleteObject(iconInfo.hbmMask);
::DeleteObject(iconInfo.hbmColor);
m_imageList.Add (m_hIcon);
}
}
CPoint CButtonSSL::GetImagePoint (CRect btnRect) {
int nLeft = 3, nTop = 3; // Default position for SSL_IMAGE_LEFT / _TOP
// Determine the left coordinate
if (SSL_IMAGE_CENTER == (SSL_IMAGE_CENTER & m_nImageAlign)) {
if (SSL_BS_MENU_BTN == (SSL_BS_MENU_BTN & m_nStyle)) {
nLeft = (btnRect.Width () - m_nImageWidth - DROP_BUTTON_WIDTH) / 2;
}
else {
nLeft = (btnRect.Width () - m_nImageWidth) / 2;
}
}
else if (SSL_IMAGE_RIGHT == (SSL_IMAGE_RIGHT & m_nImageAlign)) {
nLeft = btnRect.right - m_nImageWidth - 3;
if (SSL_BS_MENU_BTN == (SSL_BS_MENU_BTN & m_nStyle)) {
nLeft -= DROP_BUTTON_WIDTH;
}
}
// Determine the top coordinate
if (SSL_IMAGE_VCENTER == (SSL_IMAGE_VCENTER & m_nImageAlign)) {
nTop = (btnRect.Height () - m_nImageHeight) / 2;
}
else if (SSL_IMAGE_BOTTOM == (SSL_IMAGE_BOTTOM & m_nImageAlign)) {
nTop = btnRect.bottom - m_nImageHeight - 3;
}
return CPoint (nLeft + m_bBtnPushed, nTop + m_bBtnPushed);
}
void CButtonSSL::SetSize () {
// Get the size of the button text
CDC* pDC = GetDC ();
SIZE size;
CString szText;
GetWindowText (szText);
// Need to select the font to ensure correct sizing for GetTextExtentPoint32
pDC->SelectObject (&m_font);
GetTextExtentPoint32 (pDC->m_hDC, szText, szText.GetLength (), &size);
// Get the current size of the button
CRect btnRect;
GetWindowRect (btnRect);
// Adjust the size according to the contents
btnRect.right = btnRect.left + max (m_nImageWidth, size.cx) + 6;
btnRect.bottom = btnRect.top + max (m_nImageHeight, size.cy) + 6;
// Take in to account the drop button if there is one
if (SSL_BS_MENU_BTN == (SSL_BS_MENU_BTN & m_nStyle)) {
btnRect.right += DROP_BUTTON_WIDTH + 3;
}
// Resize the button
SetWindowPos (NULL, 0, 0, btnRect.Width (), btnRect.Height (), SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
void CButtonSSL::TraceState (ButtonState state) {
CString strState = _T("Button State: ");
switch (state) {
case SSL_STATE_UP:
strState += _T("Up");
break;
case SSL_STATE_OVER:
strState += _T("Over");
break;
case SSL_STATE_DOWN:
strState += _T("Down");
break;
case SSL_STATE_DISABLED:
strState += _T("Disabled");
break;
default:
strState += _T("Invalid");
}
TRACE ("%s. m_bDisabled: %i. m_bMouseOnBtn: %i. m_bBtnPushed: %i. m_bMenuPushed: %i.\n",
strState, m_bDisabled, m_bMouseOnBtn, m_bBtnPushed, m_bMenuPushed);
}