CoolBtn.cpp. #1

  • //
  • guest/
  • YourUncleBob/
  • p4win/
  • main/
  • gui/
  • CoolBtn.cpp.
  • View
  • Commits
  • Open Download .zip Download (19 KB)
// CoolButton.cpp : implementation file
//

#include "stdafx.h"
#include "p4win.h"
#include "CoolBtn.h"
#if _MFC_VER >= 0x0700
#define USE_THEMES
#include <uxtheme.h>
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const int nDropBtnWidth =  16;
/////////////////////////////////////////////////////////////////////////////
// CCoolButton
// ========
// 
// To Use:
// 1.	In the RC file, create the button as BS_OWNERDRAW.
//		Optionally, create a Bitmap resource 16x15 Pixels
//		- normal default size for a toolbar bitmap.
// 
// 2.	in the header for the dialog class:
//			#include "CoolBtn.h"
//		then create the necessary button widgets in the //{{AFX_DATA() section:
//			CCoolButton  m_DblBtn;
//
// 3.	In the InitDialog() for the dialog:
//
//	a)	Optionally, Call SetButtonImage specificing the
//		Transparency color reference.
//			(Usally RGB(255, 0, 255) magenta)
//		m_DblBtn.SetButtonImage(IDC_BTNIMAGE, RGB(255,0,255));
//
//	b)	Either call CCoolButton's SetIDs function:
//			m_DblBtn.SetIDs(IDC_BTNPUSH, IDC_BTNMENU);
//		the first ID must be the same as the ID in the RC file!
//			--or--
//		Add menu item(s) to the button:
//			m_DblBtn.AddMenuItem(nMenuId1, strMenu1, nMenuFlags1);
//			m_DblBtn.AddMenuItem(nMenuId2, strMenu2, nMenuFlags2);
//
//		If you do both SetIDs() and AddMenuItem()s, only the AddMenuItem
//		will be called and the second ID will be ignored.
//
//	c)	Optionally, call CCoolButton's show split function:
//			m_DblBtn.SetSplit(bSplit);
//		The default is to show the split (TRUE). If set to FALSE, only
//		the AddMenuItem()s or 2nd ID in SetIDs() will be called and the
//		base id (1st ID in SetIDs()==ID in RC file) will be ignored.
//
//	d)	Optionally call m_DblBtn.SetAsDefaultBtn(TRUE) to make the button
//		the default button.
//
// 4.	Add the appropiate ON_COMMAND handlers in the parent windows message map
//
// 5.	You can also call SetIDs() or SetSplit() later to dynamically change the
//		button and you can later add more AddMenuItem().
////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  CCoolButton
//
// DESCRIPTION:	
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin as CCoolBtn
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
CCoolButton::CCoolButton()
{
	m_nID2 = 0;
	m_bPushed = FALSE;
	m_bLoaded = FALSE;
	m_bMenuPushed = FALSE;
	m_bMenuLoaded = FALSE;
	m_bDefaultBtn = m_bActAsDefaultBtn = FALSE;
	m_bSplit = TRUE;

	m_bOverControl = FALSE;
	m_bTracking = FALSE;

	ZeroMemory(&m_bm, sizeof m_bm);
	m_menu.CreatePopupMenu();

	m_themeLib = LoadLibrary(_T("UxTheme.dll"));
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  ~CCoolButton
//
// DESCRIPTION:	
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100	1.0			  Origin
//
////////////////////////////////////////////////////////////////////////////////
CCoolButton::~CCoolButton()
{
	if(m_themeLib)
		FreeLibrary(m_themeLib);
}


BEGIN_MESSAGE_MAP(CCoolButton, CButton)
	//{{AFX_MSG_MAP(CCoolButton)
	ON_WM_KEYDOWN()
	ON_WM_SYSKEYDOWN()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_SYSCOLORCHANGE()
	ON_WM_GETDLGCODE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(BM_SETSTYLE, OnSetStyle)
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover )
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave )
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCoolButton message handlers

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  SetIDs
//
// DESCRIPTION:	Set the IDs
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// L Brasington 03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
BOOL CCoolButton::SetIDs( UINT nID1, UINT nID2 )
{
	m_nID1 = nID1;
	m_nID2 = nID2;
	return TRUE;
}

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

UINT CCoolButton::OnGetDlgCode() 
{
	UINT nCode = CButton::OnGetDlgCode();
	nCode |= (m_bActAsDefaultBtn ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
  	return nCode;
}

// mask for control's type
#undef	BS_TYPEMASK
#define BS_TYPEMASK SS_TYPEMASK

LRESULT CCoolButton::OnSetStyle(WPARAM wParam, LPARAM lParam)
{
	m_bActAsDefaultBtn = wParam & BS_DEFPUSHBUTTON;
	// 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);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  DrawItem
//
// DESCRIPTION:	Called in response to draw the button
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton, Added XP support
//
////////////////////////////////////////////////////////////////////////////////
#ifdef USE_THEMES
typedef HTHEME(__stdcall *PFNOPENTHEMEDATA)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT(__stdcall *PFNCLOSETHEMEDATA)(HTHEME hTheme);
typedef HRESULT(__stdcall *PFNDRAWTHEMEBACKGROUND)(HTHEME hTheme, HDC hdc, 
	int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect);
typedef HRESULT(__stdcall *PFNGETTHEMEBACKGROUNDCONTENTRECT)(HTHEME hTheme, HDC hdc, 
	int iPartId, int iStateId, const RECT *pRect, RECT *pContentRect);
#endif

void CCoolButton::DrawItem(DRAWITEMSTRUCT* lpDIS) 
{
	if (lpDIS->CtlType != ODT_BUTTON)
		return;

	CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT));

	CDC dcMem;
	CBitmap bmp;

	CRect btnRect(lpDIS->rcItem);
	CRect trueRect(btnRect);
	CRect rectFocus(btnRect);

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

	BOOL bDisabled = ODS_DISABLED & lpDIS->itemState;

#ifdef USE_THEMES
	HTHEME hTheme = 0;
	if(m_themeLib)
	{
		PFNOPENTHEMEDATA pOpenThemeData = (PFNOPENTHEMEDATA)
			GetProcAddress(m_themeLib, "OpenThemeData");
		if(pOpenThemeData)
			hTheme = (pOpenThemeData)(m_hWnd, L"Button");
	}
	if(hTheme)
	{
		// attempt to map owner draw states to theme pushbutton states
		int iState = PBS_NORMAL;
		if(m_bOverControl)//lpDIS->itemState & ODS_HOTLIGHT)
			iState = PBS_HOT;
		else if(m_bDefaultBtn || m_bActAsDefaultBtn)//lpDIS->itemState & ODS_DEFAULT)
			iState = PBS_DEFAULTED;
		else if(lpDIS->itemState & ODS_SELECTED)
			iState = PBS_PRESSED;
		HRESULT hr;

		HDC hDC = lpDIS->hDC;
		RECT rc = lpDIS->rcItem;

		// let theme draw background
		PFNDRAWTHEMEBACKGROUND pDrawThemeBackground = (PFNDRAWTHEMEBACKGROUND)
			GetProcAddress(m_themeLib, "DrawThemeBackground");
		if(!pDrawThemeBackground)
			return;
		hr = (pDrawThemeBackground)(hTheme, hDC, 
			BP_PUSHBUTTON, iState, &rc, 0);
		if(hr != S_OK)
			return;

		// get rect to put content in
		RECT rcContent;
		PFNGETTHEMEBACKGROUNDCONTENTRECT pGetThemeBackgroundContentRect = 
			(PFNGETTHEMEBACKGROUNDCONTENTRECT)
			GetProcAddress(m_themeLib, "GetThemeBackgroundContentRect");
		if(!pGetThemeBackgroundContentRect)
			return;
		hr = (pGetThemeBackgroundContentRect)(hTheme, hDC,
			BP_PUSHBUTTON, iState, &rc, &rcContent);
		if(hr != S_OK)
			return;

		rectFocus = rcContent;
		if (!m_bMenuPushed)
			rectFocus.OffsetRect(m_bPushed,m_bPushed);
		if (m_bSplit)
			rectFocus.right -= nDropBtnWidth;
		if (lpDIS->itemState & ODS_FOCUS || m_bPushed)
		{
			if (!m_bMenuPushed)
				::DrawFocusRect(lpDIS->hDC, &rcContent);
		}
	}
	else
#endif
	{
		////////////////////////////////////////
		// Button Background                  //
		////////////////////////////////////////
		CBrush brush(GetSysColor(COLOR_BTNFACE));
		pDC->FillRect(trueRect,&brush);

		if (m_bDefaultBtn)
			btnRect.DeflateRect(1,1);

		rectFocus.DeflateRect(4,4);

		if (!m_bMenuPushed)
			rectFocus.OffsetRect(m_bPushed,m_bPushed);

		if (m_bSplit)
			rectFocus.right -= nDropBtnWidth;


		////////////////////////////////////////
		// Button in a normal state           //
		////////////////////////////////////////
		if (!m_bPushed || m_bMenuPushed)
			pDC->DrawFrameControl(&btnRect,DFC_BUTTON,DFCS_BUTTONPUSH);


		////////////////////////////////////////
		// Default Button State               //
		////////////////////////////////////////
		if ((m_bDefaultBtn || m_bPushed) && !bDisabled)
		{
			pDC->FrameRect(&lpDIS->rcItem,CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
			if (m_bPushed && !m_bMenuPushed)
				pDC->FrameRect(&btnRect,CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH))); 
		}


		////////////////////////////////////////
		// State Focus                        //
		////////////////////////////////////////
		if (lpDIS->itemState & ODS_FOCUS || m_bPushed) 
		{
			pDC->FrameRect(&lpDIS->rcItem,CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
			if (!m_bMenuPushed)
				pDC->DrawFocusRect(&rectFocus);
		}


		////////////////////////////////////////
		// Action Focus                       //
		////////////////////////////////////////
		if ((lpDIS->itemAction & ODA_FOCUS))
			if (!m_bMenuPushed)
				pDC->DrawFocusRect(&rectFocus);

	}
	////////////////////////////////////////
	// Draw out bitmap                    //
	////////////////////////////////////////

	// Draw out bitmap
	if (m_bLoaded)
	{
		if (!bDisabled)
		{
			m_IL.DrawIndirect(pDC,0,CPoint(6+m_bPushed,6+m_bPushed), CSize(m_bm.bmWidth, m_bm.bmHeight), CPoint(0,0),ILD_NORMAL);
		}
		else
		{
  			pDC->DrawState(CPoint(6+m_bPushed,6+m_bPushed), CSize(m_bm.bmWidth, m_bm.bmHeight), m_hbmpDisabled, DST_BITMAP | DSS_DISABLED);
		}
	}


	////////////////////////////////////////
	// Draw out text                      //
	////////////////////////////////////////
	pDC->SelectObject(pFont);
	CRect rectText(rectFocus);
	if (!m_bSplit)
		rectText.right -= nDropBtnWidth;
	rectText.left += m_bm.bmWidth + 2;

	CString strCaption;
	GetWindowText(strCaption);
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetBkColor(GetSysColor(COLOR_BTNFACE));

	if (ODS_DISABLED & lpDIS->itemState)
	{
		rectText.OffsetRect(1,1);
		pDC->SetTextColor(GetSysColor(COLOR_WINDOW));
		pDC->DrawText(strCaption,rectText,DT_SINGLELINE|DT_CENTER|DT_VCENTER);

		rectText.OffsetRect(-1,-1);
		pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
		pDC->DrawText(strCaption,rectText,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	}
	else
	{
		pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
		pDC->DrawText(strCaption,rectText,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	}


	CRect rectSplit(btnRect);
	rectSplit.DeflateRect(2,2);
	rectSplit.right -= nDropBtnWidth;


	////////////////////////////////////////
	// Drop down split                    //
	////////////////////////////////////////
	if (m_bSplit)
	{
		CPen brFace(PS_SOLID,1,GetSysColor(COLOR_3DSHADOW));
		pDC->SelectObject(&brFace);
		pDC->MoveTo(rectSplit.right, rectSplit.top);
		pDC->LineTo(rectSplit.right, rectSplit.bottom);


		CPen brLite(PS_SOLID,1,GetSysColor(COLOR_3DHILIGHT));
		pDC->SelectObject(&brLite);
		pDC->MoveTo(rectSplit.right+1 , rectSplit.top);
		pDC->LineTo(rectSplit.right+1, rectSplit.bottom);
	}

	////////////////////////////////////////
	// Draw Arrow                         //
	////////////////////////////////////////
	rectSplit.left = rectSplit.right;
	rectSplit.right += nDropBtnWidth;

	CPoint pt(rectSplit.CenterPoint());
	pt += CPoint(m_bPushed,m_bPushed);

	CPen penBlack(PS_SOLID, 1, bDisabled ? GetSysColor(COLOR_GRAYTEXT) : GetSysColor(COLOR_WINDOWTEXT));
	pDC->SelectObject(&penBlack);
	DrawArrow(pDC,pt);

	////////////////////////////////////////
	// Drop down state                    //
	////////////////////////////////////////
	if (m_bMenuPushed && !bDisabled)
	{    
		rectSplit.InflateRect(1,1);
		pDC->DrawEdge(rectSplit,BDR_SUNKENOUTER, BF_RECT);
	}

	if(hTheme)
	{
		PFNCLOSETHEMEDATA pCloseThemeData = (PFNCLOSETHEMEDATA)GetProcAddress(m_themeLib, "CloseThemeData");
		if(!pCloseThemeData)
			return;
		(pCloseThemeData)(hTheme);
	}
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  DrawArrow
//
// DESCRIPTION:	Draws drop down arrow, we could use DrawFrameControl - a bit too 
//              messy
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100	1.0			  Origin
//
////////////////////////////////////////////////////////////////////////////////
void CCoolButton::DrawArrow(CDC* pDC,CPoint ArrowTip)
{

  CPoint ptDest;

  pDC->SetPixel(ArrowTip,RGB(0,0,0));

  ArrowTip -= CPoint(1,1);
  pDC->MoveTo(ArrowTip);
  
  ptDest = ArrowTip;
  ptDest += CPoint(3,0);
  pDC->LineTo(ptDest);

  ArrowTip -= CPoint(1,1);
  pDC->MoveTo(ArrowTip);

  ptDest = ArrowTip;
  ptDest += CPoint(5,0);
  pDC->LineTo(ptDest);

  ArrowTip -= CPoint(1,1);
  pDC->MoveTo(ArrowTip);

  ptDest = ArrowTip;
  ptDest += CPoint(7,0);
  pDC->LineTo(ptDest);
}


////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  OnLButtonDown
//
// DESCRIPTION:	handles button pressed state, including drop down menu
//              
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
void CCoolButton::OnLButtonDown(UINT nFlags, CPoint point) 
{
	SetFocus();
	if (m_bMenuPushed)
	{
		m_bMenuPushed = FALSE;
		Invalidate();
		return;
	}

	if (!m_bSplit || HitMenuBtn(point))
	{
		OnMenuBtn();
		return;
	}

	m_bPushed = TRUE;
	Invalidate();
	CButton::OnLButtonDown(nFlags, point);
}

BOOL CCoolButton::OnMenuBtn()
{
	if (!m_bMenuLoaded)
	{
		if (m_nID2)
		{
			GetParent()->PostMessage(WM_COMMAND, m_nID2, 0);
			m_bMenuPushed = TRUE;
			Invalidate();
			return TRUE;
		}
	}
	else
	{
		m_bMenuPushed = TRUE;
		Invalidate();

		CRect rc;
		GetWindowRect(rc);
		int x = rc.left;
		int y = rc.bottom;

		m_menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,x,y,GetParent());

		m_bMenuPushed = FALSE;
		Invalidate();
		return TRUE;
	}
	return FALSE;
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  OnLButtonUp
//
// DESCRIPTION:	Redraws button in normal state
//              
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
void CCoolButton::ClearButtonPushed()
{
	if (m_bPushed)
	{
		m_bPushed = FALSE;
		Invalidate();
	}
	if (m_bMenuPushed)
	{
		m_bMenuPushed = FALSE;
		Invalidate();
	}
}

void CCoolButton::OnLButtonUp(UINT nFlags, CPoint point) 
{
	ClearButtonPushed();
	CButton::OnLButtonUp(nFlags, point);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  OnMouseMove
//
// DESCRIPTION:	Tracks mouse whilst pressed
//              
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
LRESULT CCoolButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
{
	m_bOverControl=TRUE;
	Invalidate();
	return 1;
}

LRESULT CCoolButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
	m_bTracking = FALSE;
	m_bOverControl = FALSE;
	Invalidate(FALSE);
	return 0;
}

void CCoolButton::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (m_bPushed)
	{
		ClientToScreen(&point);
		if (WindowFromPoint(point) != this)
		{
  			m_bPushed = FALSE;
			Invalidate();
		}
	}
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE|TME_HOVER;
		tme.dwHoverTime = 1;
		m_bTracking = _TrackMouseEvent(&tme) != FALSE;		
	}	
	CButton::OnMouseMove(nFlags, point);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  SetButtonImage
//
// DESCRIPTION:	Sets the button image, COLORREF crMask specifics the transparency
//              color              
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100	1.0			  Origin
//
////////////////////////////////////////////////////////////////////////////////
BOOL CCoolButton::SetButtonImage(UINT nResourceId, COLORREF crMask)
{
	// The ID must exist also as a bitmap resource!!!
	m_btnImage.LoadBitmap(nResourceId);  
	m_btnImage.GetObject(sizeof m_bm, &m_bm);
	m_IL.Create( nResourceId, m_bm.bmWidth, 1, crMask );
	m_bLoaded = TRUE;
	m_crMask = crMask;

	HBITMAP bmTemp;
	COLORMAP mapColor;
	mapColor.from = crMask;
	mapColor.to  = RGB(255,255,255);

	bmTemp = (HBITMAP)::CreateMappedBitmap(AfxGetApp()->m_hInstance, nResourceId, IMAGE_BITMAP, &mapColor, 1);
	m_hbmpDisabled = (HBITMAP)::CopyImage(bmTemp, IMAGE_BITMAP, m_bm.bmWidth, m_bm.bmHeight, LR_COPYDELETEORG);

	return m_bLoaded;
}

void CCoolButton::OnSetFocus(CWnd* pOldWnd) 
{
	CButton::OnSetFocus(pOldWnd);
	Invalidate();
}

void CCoolButton::OnKillFocus(CWnd* pNewWnd) 
{
	CButton::OnKillFocus(pNewWnd);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  OnSysColorChange
//
// DESCRIPTION:	Called when system colors change, force a button redraw
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100	1.0			  Origin
//
////////////////////////////////////////////////////////////////////////////////
void CCoolButton::OnSysColorChange() 
{
	CButton::OnSysColorChange();
	Invalidate();	
}
 
////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  HitMenuBtn
//
// DESCRIPTION:	Helper function to test for menu button hit...
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100		1.0		Origin
// L Brasington	03/06/06	2.0		Rewritten as CCoolButton
//
////////////////////////////////////////////////////////////////////////////////
BOOL CCoolButton::HitMenuBtn(CPoint point)
{
	if (!m_bMenuLoaded && !m_nID2)
		return FALSE; // Don't allow menu button drop down if no menu items are loaded

	ClientToScreen(&point);
	CRect rect;
	GetWindowRect(rect);
	rect.left = rect.right - nDropBtnWidth;

	return rect.PtInRect(point);
}


////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	  AddMenuItem
//
// DESCRIPTION:	Adds a menu item and id to our menu.
//
// NOTES:			
//
// MAINTENANCE:
// Name:		  Date:	  Version:	Notes:
// NT ALMOND	210100	1.0			  Origin
//
////////////////////////////////////////////////////////////////////////////////
BOOL CCoolButton::AddMenuItem(UINT nMenuId,const CString strMenu, UINT nMenuFlags)
{
	BOOL bRet = m_menu.AppendMenu(nMenuFlags | MF_STRING, nMenuId, (LPCTSTR)strMenu);
	m_bMenuLoaded |= bRet;
	return bRet;
}

////////////////////////////////////////////////////////////////////////////////
void CCoolButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (nChar == 'F' && GetKeyState(VK_CONTROL) & 0x8000)	// ^F == Find
		GetParent()->PostMessage(WM_COMMAND, ID_POSITIONTOPATTERN, 0);
	else if (nChar == VK_F3)
		GetParent()->PostMessage(WM_COMMAND, GetKeyState(VK_SHIFT) & 0x8000 
											 ? ID_FINDPREV : ID_FINDNEXT, 0);
	else
		CButton::OnChar(nChar, nRepCnt, nFlags);
}

void CCoolButton::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	switch ( nChar )
	{
	case VK_DOWN:
		OnMenuBtn();
		break;
	}
	
	CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
}
# Change User Description Committed
#1 19924 YourUncleBob Populate -o //guest/perforce_software/p4win/...
//guest/YourUncleBob/p4win/.....
//guest/perforce_software/p4win/main/gui/CoolBtn.cpp
#1 16169 perforce_software Move files to follow new path scheme for branches.
//guest/perforce_software/p4win/gui/CoolBtn.cpp
#1 8562 Matt Attaway These feet never stop running.

Initial commit of the P4Win source code.  To the best of our knowledge this
compiles and runs using the 2013.3 P4 API and VS 2010. Expect a few changes
as we refine the build process. Please post any build issues to the forums.