Files
scummvm-cursorfix/engines/bagel/hodjnpodj/hnplibs/button.cpp
2026-02-02 04:50:13 +01:00

1718 lines
56 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/button.h"
namespace Bagel {
namespace HodjNPodj {
extern CPalette *pGamePalette;
IMPLEMENT_DYNCREATE(CBmpButton, CBitmapButton)
/*************************************************************************
*
* CBmpButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Constructor for button class. Initialize all fields
* to logical nullptr. Calls should then be made to other
* button routines to load palettes and bitmaps.
*
************************************************************************/
CBmpButton::CBmpButton() {
m_pPalette = nullptr; // no initial palette
}
/*************************************************************************
*
* ~CBmpButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Destructor for button class. It is important to tear
* things down in the order we built them; map out bitmap,
* map out the palette, then discard the device context -
* failure to release key resources will cause application
* or system crashes.
*
************************************************************************/
CBmpButton::~CBmpButton() {
if (m_pPalette != nullptr) { // release the palette resource
(*m_pPalette).DeleteObject();
delete m_pPalette;
m_pPalette = nullptr;
}
}
/*************************************************************************
*
* OnEraseBkgnd()
*
* Parameters: none
*
* Return Value: none
*
* Description: Do not let Windows automatically erase our window
* to white.
*
************************************************************************/
bool CBmpButton::OnEraseBkgnd(CDC *pDC) {
return true; // do not automatically erase background to white
}
/*************************************************************************
*
* DrawItem()
*
* Parameters: pointer to button structure information
*
* Return Value: none
*
* Description: Paint a button appropriately, based on its current state.
*
************************************************************************/
void CBmpButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC *pDC;
CPalette *pPalOld = nullptr;
//bool bActiveWindow = false;
//CWnd *pActiveWindow;
CBitmap *pBitmap;
CWnd *pParentWnd;
pParentWnd = GetParent();
if (!IsWindowVisible() || // punt if not visible
(pParentWnd == nullptr) ||
!(*pParentWnd).IsWindowVisible())
return;
/*
pActiveWindow = GetActiveWindow(); // get the active window and if it is
if ((this == pActiveWindow) || // ... us, then we will use the palette
(pActiveWindow == nullptr))
bActiveWindow = true; // ... in a foreground mode
*/
pDC = new CDC; // setup the device context given to us
(*pDC).Attach((*lpDrawItemStruct).hDC); // ... as a pointer to a CDC object
if (m_pPalette != nullptr) { // map the palette into the context
pPalOld = (*pDC).SelectPalette(m_pPalette, true);
(*pDC).RealizePalette(); // ... and tell the system to use it
}
if (((*lpDrawItemStruct).itemState & ODS_GRAYED) || // display the correct bitmap based on state
((*lpDrawItemStruct).itemState & ODS_DISABLED))
pBitmap = &m_bitmapDisabled;
else if ((*lpDrawItemStruct).itemState & ODS_SELECTED)
pBitmap = &m_bitmapSel;
else if ((*lpDrawItemStruct).itemState & ODS_FOCUS)
pBitmap = &m_bitmapFocus;
else
pBitmap = &m_bitmap;
PaintBitmap(pDC, nullptr, pBitmap, (*lpDrawItemStruct).rcItem.left, (*lpDrawItemStruct).rcItem.top);
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
(*pDC).Detach(); // dismantle the temporary CDC we built
delete pDC;
}
/*************************************************************************
*
* SetControl()
*
* Parameters:
* unsigned int nID control identifier for the dialog button
* CWnd * pParent pointer to parent window owning the button
*
* Return Value:
* bool success / failure condition
*
* Description: associate this button with a dialog control.
*
************************************************************************/
bool CBmpButton::SetControl(unsigned int nID, CWnd * pParent) {
if (!CBitmapButton::SubclassDlgItem(nID, pParent)) // attach the Button to the dialog control
return false;
return true;
}
/*************************************************************************
*
* AutoLoad()
*
* Parameters:
* unsigned int nID control identifier for the dialog button
* CWnd * pParent pointer to parent window owning the button
*
* Return Value:
* bool success / failure condition
*
* Description: associates this button with a dialog control and
* automatically load bitmaps for a dialog button.
*
************************************************************************/
bool CBmpButton::AutoLoad(unsigned int nID, CWnd * pParent) {
CString buttonName;
bool bSuccess;
if (!SetControl(nID, pParent)) // attach the Button to the dialog control
return false;
GetWindowText(buttonName); // get the button's title
ASSERT(!buttonName.IsEmpty());
// load the bitmaps
bSuccess = LoadBitmaps(buttonName + "U", buttonName + "D", buttonName + "F", buttonName + "X");
if (bSuccess)
CBitmapButton::SizeToContent(); // resize button to its content
return bSuccess;
}
/*************************************************************************
*
* LoadBitmaps()
*
* Parameters:
* CPalette *pPalatte palette for buttons
* CBitmap *pBase bitmap for UP state
* CBitmap *pSelected bitmap for SELECTED state
* CBitmap *pFocus bitmap for FOCUS state
* CBitmap *pDisabled bitmap for DISABLED state
*
* Return Value:
* bool success / failure condition
*
* Description: Setup the CBitmaps for the four button states of a CBmpButton.
*
************************************************************************/
bool CBmpButton::LoadBitmaps(CPalette *pPalette, CBitmap *pBase, CBitmap *pSelected, CBitmap *pFocus, CBitmap *pDisabled) {
HBITMAP hBitmap = nullptr;
if (pBase == nullptr)
return false;
if (pPalette == nullptr)
m_pPalette = nullptr;
else {
if (m_pPalette != nullptr)
delete m_pPalette;
m_pPalette = DuplicatePalette(pPalette);
}
m_bitmap.DeleteObject();
hBitmap = (HBITMAP)(*pBase).Detach();
m_bitmap.Attach(hBitmap);
delete pBase;
m_bitmapSel.DeleteObject();
if (pSelected != nullptr) {
hBitmap = (HBITMAP)(*pSelected).Detach();
m_bitmapSel.Attach(hBitmap);
delete pSelected;
}
m_bitmapFocus.DeleteObject();
if (pFocus != nullptr) {
hBitmap = (HBITMAP)(*pFocus).Detach();
m_bitmapFocus.Attach(hBitmap);
delete pFocus;
}
m_bitmapDisabled.DeleteObject();
if (pDisabled != nullptr) {
hBitmap = (HBITMAP)(*pDisabled).Detach();
m_bitmapDisabled.Attach(hBitmap);
delete pDisabled;
}
ensureSize();
return true;
}
/*************************************************************************
*
* LoadBitmaps()
*
* Parameters:
* const int nBase resource number for UP state
* const int nSelected resource number for SELECTED state
* const int nFocus resource number for FOCUS state
* const int nDisabled resource number for DISABLED state
*
* Return Value:
* bool success / failure condition
*
* Description: Read in the DDB bitmaps for the four button states of a CBmpButton.
*
************************************************************************/
bool CBmpButton::LoadBitmaps(const int nBase, const int nSelected, const int nFocus, const int nDisabled) {
CDC *pDC = nullptr;
CBitmap *pBitmap = nullptr;
HBITMAP hBitmap = nullptr;
bool bSuccess = true;
if (m_pPalette != nullptr) { // release any existing palette resource
(*m_pPalette).DeleteObject();
delete m_pPalette;
m_pPalette = nullptr;
}
pDC = GetDC(); // fetch a device context we can use
if (pDC == nullptr)
bSuccess = false;
if (bSuccess) { // get a CBitmap for the UP button
pBitmap = FetchResourceBitmap(pDC, &m_pPalette, nBase);
if (pBitmap != nullptr) { // ... and plug it into our instance
m_bitmap.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmap.Attach(hBitmap);
delete pBitmap;
if (nSelected != 0) { // get the SELECTED bitmap and plug it in
pBitmap = FetchResourceBitmap(pDC, nullptr, nSelected);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapSel.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapSel.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the FOCUS bitmap and plug it in
(nFocus != 0)) {
pBitmap = FetchResourceBitmap(pDC, nullptr, nFocus);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapFocus.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapFocus.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the DISABLED bitmap and plug it in
(nDisabled != 0)) {
pBitmap = FetchResourceBitmap(pDC, nullptr, nDisabled);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapDisabled.DeleteObject();// release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapDisabled.Attach(hBitmap);
delete pBitmap;
}
}
} else
bSuccess = false;
}
if (pDC != nullptr)
ReleaseDC(pDC);
if (bSuccess)
ensureSize();
return bSuccess;
}
/*************************************************************************
*
* LoadBitmaps()
*
* Parameters:
* const char *lpszBase pointer to resource name string for UP state
* const char *lpszSelected pointer to resource name string for SELECTED state
* const char *lpszFocus pointer to resource name string for FOCUS state
* const char *lpszDisabled pointer to resource name string for DISABLED state
*
* Return Value:
* bool success / failure condition
*
* Description: Read in the DDB bitmaps for the four button states of a CBmpButton.
*
************************************************************************/
bool CBmpButton::LoadBitmaps(const char *lpszBase, const char *lpszSelected, const char *lpszFocus, const char *lpszDisabled) {
CDC *pDC = nullptr;
CBitmap *pBitmap = nullptr;
HBITMAP hBitmap = nullptr;
bool bSuccess = true;
if (m_pPalette != nullptr) { // release any existing palette resource
(*m_pPalette).DeleteObject();
delete m_pPalette;
m_pPalette = nullptr;
}
pDC = GetDC(); // fetch a device context we can use
if (pDC == nullptr)
bSuccess = false;
if (bSuccess) { // get a CBitmap for the UP button
pBitmap = FetchResourceBitmap(pDC, &m_pPalette, lpszBase);
if (pBitmap != nullptr) { // ... and plug it into our instance
m_bitmap.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmap.Attach(hBitmap);
delete pBitmap;
if (lpszSelected != nullptr) { // get the SELECTED bitmap and plug it in
pBitmap = FetchResourceBitmap(pDC, nullptr, lpszSelected);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapSel.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapSel.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the FOCUS bitmap and plug it in
(lpszFocus != nullptr)) {
pBitmap = FetchResourceBitmap(pDC, nullptr, lpszFocus);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapFocus.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapFocus.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the DISABLED bitmap and plug it in
(lpszDisabled != nullptr)) {
pBitmap = FetchResourceBitmap(pDC, nullptr, lpszDisabled);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapDisabled.DeleteObject();// release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapDisabled.Attach(hBitmap);
delete pBitmap;
}
}
} else
bSuccess = false;
}
if (pDC != nullptr)
ReleaseDC(pDC);
if (bSuccess)
ensureSize();
return bSuccess;
}
/*************************************************************************
*
* LoadBmpBitmaps()
*
* Parameters:
* const char *lpszBase pointer to .BMP path string for UP state
* const char *lpszSelected pointer to .BMP path string for SELECTED state
* const char *lpszFocus pointer to .BMP path string for FOCUS state
* const char *lpszDisabled pointer to .BMP path string for DISABLED state
*
* Return Value:
* bool success / failure condition
*
* Description: Read in the .BMP files for the four button states of a CBmpButton.
*
************************************************************************/
bool CBmpButton::LoadBmpBitmaps(const char *lpszBase, const char *lpszSelected, const char *lpszFocus, const char *lpszDisabled) {
CDC *pDC = nullptr;
CBitmap *pBitmap = nullptr;
HBITMAP hBitmap = nullptr;
bool bSuccess = true;
if (m_pPalette != nullptr) { // release any existing palette resource
(*m_pPalette).DeleteObject();
delete m_pPalette;
m_pPalette = nullptr;
}
pDC = GetDC(); // fetch a device context we can use
if (pDC == nullptr)
bSuccess = false;
if (bSuccess) { // get a CBitmap for the UP button
pBitmap = FetchBitmap(pDC, &m_pPalette, lpszBase);
if (pBitmap != nullptr) { // ... and plug it into our instance
m_bitmap.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmap.Attach(hBitmap);
delete pBitmap;
if (lpszSelected != nullptr) { // get the SELECTED bitmap and plug it in
pBitmap = FetchBitmap(pDC, nullptr, lpszSelected);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapSel.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapSel.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the FOCUS bitmap and plug it in
(lpszFocus != nullptr)) {
pBitmap = FetchBitmap(pDC, nullptr, lpszFocus);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapFocus.DeleteObject(); // release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapFocus.Attach(hBitmap);
delete pBitmap;
}
}
if (bSuccess && // get the DISABLED bitmap and plug it in
(lpszDisabled != nullptr)) {
pBitmap = FetchBitmap(pDC, nullptr, lpszDisabled);
if (pBitmap == nullptr)
bSuccess = false;
else {
m_bitmapDisabled.DeleteObject();// release what ever was already there
hBitmap = (HBITMAP)(*pBitmap).Detach();
m_bitmapDisabled.Attach(hBitmap);
delete pBitmap;
}
}
} else
bSuccess = false;
}
if (pDC != nullptr)
ReleaseDC(pDC);
if (bSuccess)
ensureSize();
return bSuccess;
}
void CBmpButton::ensureSize() {
CRect clientRect;
GetClientRect(&clientRect);
BITMAP bmpInfo;
m_bitmap.GetBitmap(&bmpInfo);
if (clientRect.right < bmpInfo.bmWidth ||
clientRect.bottom < bmpInfo.bmHeight) {
clientRect.right = MAX(clientRect.right, bmpInfo.bmWidth);
clientRect.bottom = MAX(clientRect.bottom, bmpInfo.bmHeight);
ClientToScreen(&clientRect);
m_pParentWnd->ScreenToClient(&clientRect);
MoveWindow(&clientRect);
}
// Flag for the control to redraw itself
Invalidate();
}
// CBmpButton message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CBmpButton, CBitmapButton)
//{{AFX_MSG_MAP( CBmpButton )
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CMaskedButton, CBmpButton)
/*************************************************************************
*
* CMaskedButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Constructor for button class. Initialize all fields
* to logical nullptr. Calls should then be made to other
* button routines to load palettes and bitmaps.
*
************************************************************************/
CMaskedButton::CMaskedButton() {
m_pPalette = nullptr; // no initial palette
m_pBackground = nullptr; // no initial background
}
/*************************************************************************
*
* ~CMaskedButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Destructor for button class. It is important to tear
* things down in the order we built them; map out bitmap,
* map out the palette, then discard the device context -
* failure to release key resources will cause application
* or system crashes.
*
************************************************************************/
CMaskedButton::~CMaskedButton() {
if (m_pPalette != nullptr) { // release the palette resource
(*m_pPalette).DeleteObject();
delete m_pPalette;
m_pPalette = nullptr;
}
if (m_pBackground != nullptr) { // release the background resource
delete m_pBackground;
m_pBackground = nullptr;
}
}
/*************************************************************************
*
* OnEraseBkgnd()
*
* Parameters: none
*
* Return Value: none
*
* Description: Do not let Windows automatically erase our window
* to white.
*
************************************************************************/
bool CMaskedButton::OnEraseBkgnd(CDC *pDC) {
return true; // do not automatically erase background to white
}
/*************************************************************************
*
* DrawItem()
*
* Parameters: pointer to button structure information
*
* Return Value: none
*
* Description: Paint a button appropriately, based on its current state.
*
************************************************************************/
void CMaskedButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC *pDC;
CPalette *pPalOld = nullptr;
CBitmap *pBitmap;
CWnd *pParentWnd;
pParentWnd = GetParent();
if (!IsWindowVisible() || // punt if not visible
(pParentWnd == nullptr) ||
!(*pParentWnd).IsWindowVisible())
return;
pDC = new CDC; // setup the device context given to us
(*pDC).Attach((*lpDrawItemStruct).hDC); // ... as a pointer to a CDC object
if (m_pPalette != nullptr) { // map the palette into the context
pPalOld = (*pDC).SelectPalette(m_pPalette, true);
(*pDC).RealizePalette(); // ... and tell the system to use it
}
if (m_pBackground == nullptr)
m_pBackground = FetchScreenBitmap(pDC, m_pPalette,
(*lpDrawItemStruct).rcItem.left,
(*lpDrawItemStruct).rcItem.top,
(*lpDrawItemStruct).rcItem.right - (*lpDrawItemStruct).rcItem.left,
(*lpDrawItemStruct).rcItem.bottom - (*lpDrawItemStruct).rcItem.top);
else
PaintBitmap(pDC, m_pPalette, m_pBackground,
(*lpDrawItemStruct).rcItem.left,
(*lpDrawItemStruct).rcItem.top);
if (((*lpDrawItemStruct).itemState & ODS_GRAYED) || // display the correct bitmap based on state
((*lpDrawItemStruct).itemState & ODS_DISABLED))
pBitmap = &m_bitmapDisabled;
else if ((*lpDrawItemStruct).itemState & ODS_SELECTED)
pBitmap = &m_bitmapSel;
else if ((*lpDrawItemStruct).itemState & ODS_FOCUS)
pBitmap = &m_bitmapFocus;
else
pBitmap = &m_bitmap;
PaintMaskedBitmap(pDC, nullptr, pBitmap, (*lpDrawItemStruct).rcItem.left, (*lpDrawItemStruct).rcItem.top);
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
(*pDC).Detach(); // dismantle the temporary CDC we built
delete pDC;
}
// CMaskedButton message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CMaskedButton, CBmpButton)
//{{AFX_MSG_MAP( CMaskedButton )
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CColorButton, CButton)
/*************************************************************************
*
* CColorButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Constructor for button class. Initialize all fields
* to logical nullptr. Calls should then be made to other
* button routines to load palettes and bitmaps.
*
************************************************************************/
CColorButton::CColorButton() {
m_pPalette = nullptr; // no initial palette
m_cButtonFace = RGB_BUTTON_FACE;
m_cButtonHighlight = RGB_BUTTON_HIGHLIGHT;
m_cButtonShadow = RGB_BUTTON_SHADOW;
m_cButtonText = RGB_BUTTON_TEXT;
m_cButtonTextDisabled = RGB_BUTTON_TEXT_DISABLE;
m_cButtonOutline = RGB_BUTTON_OUTLINE;
}
/*************************************************************************
*
* ~CColorButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Destructor for button class. It is important to tear
* things down in the order we built them; map out bitmap,
* map out the palette, then discard the device context -
* failure to release key resources will cause application
* or system crashes.
*
************************************************************************/
CColorButton::~CColorButton() {
m_pPalette = nullptr;
}
/*************************************************************************
*
* OnEraseBkgnd()
*
* Parameters: none
*
* Return Value: none
*
* Description: Do not let Windows automatically erase our window
* to white.
*
************************************************************************/
bool CColorButton::OnEraseBkgnd(CDC *pDC) {
return true; // do not automatically erase background to white
}
/*************************************************************************
*
* SetPalette()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
*
* Return Value: none
*
* Description: registers the palette to be used when painting the button;
* it is assumed to be a shared resource and hence is NOT
* deleted when the button is destroyed.
*
************************************************************************/
void CColorButton::SetPalette(CPalette *pPalette) {
m_pPalette = pPalette; // save the palette pointer
}
/*************************************************************************
*
* SetColors()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
* COLORREF cFace PALETTERGB color value for the face of the button
* COLORREF cHighlight PALETTERGB color value for the upper highlighted edge
* COLORREF cShadow PALETTERGB color value for the lower shadowed edge
* COLORREF cText PALETTERGB color value for the text in the button
* COLORREF cTextDisabled PALETTERGB color value for the text when disabled
* COLORREF cOutline PALETTERGB color value for the bounding rectangle
*
* Return Value: none
*
* Description: establishes the colors to use when painting the button;
* note that cHighlight and CShadow are reversed when the
* button is selected (i.e. down).
*
************************************************************************/
void CColorButton::SetColors(CPalette *pPalette, COLORREF cFace, COLORREF cHighlight, COLORREF cShadow, COLORREF cText, COLORREF cTextDisabled, COLORREF cOutline) {
m_pPalette = pPalette;
m_cButtonFace = cFace;
m_cButtonHighlight = cHighlight;
m_cButtonShadow = cShadow;
m_cButtonText = cText;
m_cButtonTextDisabled = cTextDisabled;
m_cButtonOutline = cOutline;
}
/*************************************************************************
*
* SetControl()
*
* Parameters:
* unsigned int nID control identifier for the dialog button
* CWnd * pParent pointer to parent window owning the button
*
* Return Value:
* bool success / failure condition
*
* Description: associate this button with a dialog control.
*
************************************************************************/
bool CColorButton::SetControl(unsigned int nID, CWnd * pParent) {
if (!CColorButton::SubclassDlgItem(nID, pParent)) // attach the Button to the dialog control
return false;
return true;
}
/*************************************************************************
*
* DrawItem()
*
* Parameters: pointer to button structure information
*
* Return Value: none
*
* Description: Paint a button appropriately, based on its current state.
*
************************************************************************/
void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC *pDC;
CPalette *pPalOld = nullptr;
CPen myPen, myInversePen, *pOldPen;
CBrush myBrush, *pOldBrush, myQuill, myFrame;
COLORREF myTextColor, oldTextColor;
int nUnderscore = -1;
int nMyTextLength,
i, j, x, y, dx, dy;
char chMyText[128];
TEXTMETRIC fontMetrics;
CSize textInfo,
letterInfo,
underscoreInfo;
CRect focusRect;
CWnd *pParentWnd;
pParentWnd = GetParent();
if (!IsWindowVisible() || // punt if not visible
(pParentWnd == nullptr) ||
!(*pParentWnd).IsWindowVisible())
return;
nMyTextLength = GetWindowText((char *) &chMyText, 127);
chMyText[nMyTextLength] = '\0'; // fetch the button label and strip
for (i = 0, j = 0; i <= nMyTextLength; i++) { // ... out any apersand characters
if (chMyText[i] == '&') // ... which are used to force underscoring
nUnderscore = j; // ... of the next letter, which in turn
else { // ... indicates the keyboard key equivalent
chMyText[j] = chMyText[i];
j += 1;
}
}
nMyTextLength = j - 1;
x = 0;
y = 0;
pDC = new CDC; // setup the device context given to us
(*pDC).Attach((*lpDrawItemStruct).hDC); // ... as a pointer to a CDC object
if (m_pPalette != nullptr) { // map the palette into the context
pPalOld = (*pDC).SelectPalette(m_pPalette, true);
(*pDC).RealizePalette(); // ... and tell the system to use it
}
if (((*lpDrawItemStruct).itemState & ODS_GRAYED) ||
((*lpDrawItemStruct).itemState & ODS_DISABLED)) {
myPen.CreatePen(PS_INSIDEFRAME, BUTTON_EDGE_WIDTH, m_cButtonHighlight);
myInversePen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonShadow);
myBrush.CreateSolidBrush(m_cButtonFace);
myTextColor = m_cButtonTextDisabled;
} else if ((*lpDrawItemStruct).itemState & ODS_SELECTED) {
myPen.CreatePen(PS_INSIDEFRAME, BUTTON_EDGE_WIDTH, m_cButtonShadow);
myInversePen.CreatePen(PS_SOLID, 1, m_cButtonHighlight);
myBrush.CreateSolidBrush(m_cButtonFace);
myTextColor = m_cButtonText;
x = SELECTED_TEXT_DX;
y = SELECTED_TEXT_DY;
} else {
myPen.CreatePen(PS_INSIDEFRAME, BUTTON_EDGE_WIDTH, m_cButtonHighlight);
myInversePen.CreatePen(PS_SOLID, 1, m_cButtonShadow);
myBrush.CreateSolidBrush(m_cButtonFace);
myTextColor = m_cButtonText;
}
pOldPen = (*pDC).SelectObject(&myPen); // select in the pens and brushes
pOldBrush = (*pDC).SelectObject(&myBrush);
(*pDC).Rectangle(&(*lpDrawItemStruct).rcItem);
(*pDC).SelectObject(pOldPen);
pOldPen = (*pDC).SelectObject(&myInversePen);
for (i = 1; i <= BUTTON_EDGE_WIDTH; i++) { // draw the button edges
(*pDC).MoveTo((*lpDrawItemStruct).rcItem.left + i, (*lpDrawItemStruct).rcItem.bottom - i);
(*pDC).LineTo((*lpDrawItemStruct).rcItem.right - i, (*lpDrawItemStruct).rcItem.bottom - i);
(*pDC).LineTo((*lpDrawItemStruct).rcItem.right - i, (*lpDrawItemStruct).rcItem.top + i - 1);
}
(*pDC).SelectObject(pOldPen);
(*pDC).SelectObject(pOldBrush);
myFrame.CreateSolidBrush(m_cButtonOutline); // outline the button
(*pDC).FrameRect(&(*lpDrawItemStruct).rcItem, &myFrame);
(*pDC).GetTextMetrics(&fontMetrics); // get some info about the font
textInfo = (*pDC).GetTextExtent(chMyText, nMyTextLength); // get the area spanned by the text
dx = (*lpDrawItemStruct).rcItem.right - (*lpDrawItemStruct).rcItem.left;
dy = (*lpDrawItemStruct).rcItem.bottom - (*lpDrawItemStruct).rcItem.top;
x += (dx - textInfo.cx) >> 1;
y += (dy - textInfo.cy) >> 1;
(*pDC).SetBkMode(TRANSPARENT); // make the text overlay transparently
oldTextColor = (*pDC).SetTextColor(myTextColor); // set the color of the text
(*pDC).TextOut(x, y, (const char *) &chMyText, nMyTextLength);
if (nUnderscore >= 0) {
underscoreInfo = (*pDC).GetTextExtent(chMyText, nUnderscore);
dx = x + underscoreInfo.cx;
letterInfo = (*pDC).GetTextExtent(&chMyText[nUnderscore], 1);
underscoreInfo = (*pDC).GetTextExtent((const char *) "_", 1);
dx += (letterInfo.cx - underscoreInfo.cx) >> 1;
(*pDC).TextOut(dx, y, (const char *) "_", 1);
}
(*pDC).SetTextColor(oldTextColor); // set the color of the text
if ((*lpDrawItemStruct).itemState & ODS_FOCUS) {
focusRect.SetRect(x - FOCUS_RECT_DX,
y - FOCUS_RECT_DY,
x + textInfo.cx + FOCUS_RECT_DX,
y + textInfo.cy + FOCUS_RECT_DY + 1);
myQuill.CreateStockObject(DKGRAY_BRUSH);
(*pDC).FrameRect(&focusRect, &myQuill);
}
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
(*pDC).Detach(); // dismantle the temporary CDC we built
delete pDC;
}
// CColorButton message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CColorButton, CButton)
//{{AFX_MSG_MAP( CColorButton )
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CCheckButton, CButton)
/*************************************************************************
*
* CCheckButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Constructor for button class. Initialize all fields
* to logical nullptr. Calls should then be made to other
* button routines to load palettes and bitmaps.
*
************************************************************************/
CCheckButton::CCheckButton() {
m_bCheckState = false;
m_pPalette = nullptr;
m_cButtonFace = RGB_CHECK_FACE;
m_cButtonControl = RGB_CHECK_CONTROL;
m_cButtonText = RGB_CHECK_TEXT;
m_cButtonTextDisabled = RGB_CHECK_TEXT_DISABLE;
m_cButtonOutline = RGB_CHECK_OUTLINE;
}
/*************************************************************************
*
* ~CCheckButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Destructor for button class. It is important to tear
* things down in the order we built them; map out bitmap,
* map out the palette, then discard the device context -
* failure to release key resources will cause application
* or system crashes.
*
************************************************************************/
CCheckButton::~CCheckButton() {
m_pPalette = nullptr;
}
/*************************************************************************
*
* OnEraseBkgnd()
*
* Parameters: none
*
* Return Value: none
*
* Description: Do not let Windows automatically erase our window
* to white.
*
************************************************************************/
bool CCheckButton::OnEraseBkgnd(CDC *pDC) {
return true; // do not automatically erase background to white
}
/*************************************************************************
*
* SetPalette()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
*
* Return Value: none
*
* Description: registers the palette to be used when painting the button;
* it is assumed to be a shared resource and hence is NOT
* deleted when the button is destroyed.
*
************************************************************************/
void CCheckButton::SetPalette(CPalette *pPalette) {
m_pPalette = pPalette; // save the palette pointer
}
/*************************************************************************
*
* SetColors()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
* COLORREF cFace PALETTERGB color value for the face of the button
* COLORREF cControl PALETTERGB color value for the control box
* COLORREF cText PALETTERGB color value for the text in the button
* COLORREF cTextDisabled PALETTERGB color value for the text when disabled
* COLORREF cOutline PALETTERGB color value for the bounding rectangle
*
* Return Value: none
*
* Description: establishes the colors to use when painting the button;
* note that cHighlight and CShadow are reversed when the
* button is selected (i.e. down).
*
************************************************************************/
void CCheckButton::SetColors(CPalette *pPalette, COLORREF cFace, COLORREF cControl, COLORREF cText, COLORREF cTextDisabled, COLORREF cOutline) {
m_pPalette = pPalette;
m_cButtonFace = cFace;
m_cButtonControl = cControl;
m_cButtonText = cText;
m_cButtonTextDisabled = cTextDisabled;
m_cButtonOutline = cOutline;
}
/*************************************************************************
*
* SetControl()
*
* Parameters:
* unsigned int nID control identifier for the dialog button
* CWnd * pParent pointer to parent window owning the button
*
* Return Value:
* bool success / failure condition
*
* Description: associate this button with a dialog control.
*
************************************************************************/
bool CCheckButton::SetControl(unsigned int nID, CWnd * pParent) {
if (!CCheckButton::SubclassDlgItem(nID, pParent)) // attach the Button to the dialog control
return false;
return true;
}
/*************************************************************************
*
* DrawItem()
*
* Parameters: pointer to button structure information
*
* Return Value: none
*
* Description: Paint a button appropriately, based on its current state.
*
************************************************************************/
void CCheckButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC *pDC;
CPalette *pPalOld = nullptr;
CPen outlinePen, controlPen, *pOldPen;
CBrush faceBrush, *pOldBrush, myQuill, frameBrush;
COLORREF myTextColor, oldTextColor;
int nUnderscore = -1;
int nMyTextLength,
i, j, x, y, dx, dy;
char chMyText[128];
TEXTMETRIC fontMetrics;
CSize textInfo,
letterInfo,
underscoreInfo;
CRect controlRect, focusRect;
CWnd *pParentWnd;
pParentWnd = GetParent();
if (!IsWindowVisible() || // punt if not visible
(pParentWnd == nullptr) ||
!(*pParentWnd).IsWindowVisible())
return;
nMyTextLength = GetWindowText((char *) &chMyText, 127);
chMyText[nMyTextLength] = '\0'; // fetch the button label and strip
for (i = 0, j = 0; i <= nMyTextLength; i++) { // ... out any apersand characters
if (chMyText[i] == '&') // ... which are used to force underscoring
nUnderscore = j; // ... of the next letter, which in turn
else { // ... indicates the keyboard key equivalent
chMyText[j] = chMyText[i];
j += 1;
}
}
nMyTextLength = j - 1;
pDC = new CDC; // setup the device context given to us
(*pDC).Attach((*lpDrawItemStruct).hDC); // ... as a pointer to a CDC object
if (m_pPalette != nullptr) { // map the palette into the context
pPalOld = (*pDC).SelectPalette(m_pPalette, true);
(*pDC).RealizePalette(); // ... and tell the system to use it
}
if (((*lpDrawItemStruct).itemState & ODS_GRAYED) || // setup text color based on enable/disable state
((*lpDrawItemStruct).itemState & ODS_DISABLED))
myTextColor = m_cButtonTextDisabled;
else
myTextColor = m_cButtonText;
// calculate the button width and height
dx = (*lpDrawItemStruct).rcItem.right - (*lpDrawItemStruct).rcItem.left;
dy = (*lpDrawItemStruct).rcItem.bottom - (*lpDrawItemStruct).rcItem.top;
// create the bounding rectangle for the box
controlRect.SetRect((*lpDrawItemStruct).rcItem.left + CHECK_BOX_DX,
(*lpDrawItemStruct).rcItem.top + ((dy - CHECK_BOX_SIZE) >> 1),
(*lpDrawItemStruct).rcItem.left + CHECK_BOX_DX + CHECK_BOX_SIZE,
(*lpDrawItemStruct).rcItem.top + ((dy - CHECK_BOX_SIZE) >> 1) + CHECK_BOX_SIZE);
// create the pens and brushes we need
outlinePen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonOutline);
faceBrush.CreateSolidBrush(m_cButtonFace);
controlPen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonControl);
frameBrush.CreateSolidBrush(m_cButtonControl);
pOldBrush = (*pDC).SelectObject(&faceBrush);
if ((*lpDrawItemStruct).itemAction & ODA_DRAWENTIRE) {
pOldPen = (*pDC).SelectObject(&outlinePen); // fill in the whole control
(*pDC).Rectangle(&(*lpDrawItemStruct).rcItem);
} else {
pOldPen = (*pDC).SelectObject(&controlPen); // fill in just the box
(*pDC).Rectangle(&controlRect);
}
(*pDC).SelectObject(pOldPen);
(*pDC).SelectObject(pOldBrush);
(*pDC).FrameRect(&controlRect, &frameBrush); // paint the box and indicate selection
if (m_bCheckState) { // indicate that the box is checked
pOldPen = (*pDC).SelectObject(&controlPen);
(*pDC).MoveTo(controlRect.left, controlRect.top);
(*pDC).LineTo(controlRect.right - 1, controlRect.bottom - 1);
(*pDC).MoveTo(controlRect.left, controlRect.bottom - 1);
(*pDC).LineTo(controlRect.right - 1, controlRect.top);
(*pDC).SelectObject(pOldPen);
}
if ((*lpDrawItemStruct).itemState & ODS_SELECTED) {
controlRect.InflateRect(-1, -1);
(*pDC).FrameRect(&controlRect, &frameBrush);
}
(*pDC).GetTextMetrics(&fontMetrics); // get some info about the font
textInfo = (*pDC).GetTextExtent(chMyText, nMyTextLength); // get the area spanned by the text
x = (*lpDrawItemStruct).rcItem.left + CHECK_TEXT_DX;
y = (*lpDrawItemStruct).rcItem.top + ((dy - textInfo.cy) >> 1);
(*pDC).SetBkMode(TRANSPARENT); // make the text overlay transparently
oldTextColor = (*pDC).SetTextColor(myTextColor); // set the color of the text
(*pDC).TextOut(x, y, (const char *) &chMyText, nMyTextLength);
if (nUnderscore >= 0) { // put the underscore where it belongs
underscoreInfo = (*pDC).GetTextExtent(chMyText, nUnderscore);
dx = x + underscoreInfo.cx;
letterInfo = (*pDC).GetTextExtent(&chMyText[nUnderscore], 1);
underscoreInfo = (*pDC).GetTextExtent((const char *) "_", 1);
dx += (letterInfo.cx - underscoreInfo.cx) >> 1;
(*pDC).TextOut(dx, y, (const char *) "_", 1);
}
(*pDC).SetTextColor(oldTextColor);
focusRect.SetRect(x - FOCUS_RECT_DX, // set the focus rectangle
y - FOCUS_RECT_DY, // ... then paint it or clear it
x + textInfo.cx + FOCUS_RECT_DX,
y + textInfo.cy + FOCUS_RECT_DY + 1);
if ((*lpDrawItemStruct).itemState & ODS_FOCUS) {
myQuill.CreateStockObject(DKGRAY_BRUSH);
(*pDC).FrameRect(&focusRect, &myQuill);
} else
(*pDC).FrameRect(&focusRect, &faceBrush);
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
(*pDC).Detach(); // dismantle the temporary CDC we built
delete pDC;
}
/*************************************************************************
*
* OnSetCheck()
*
* Parameters:
* WPARAM wParam true / false for new check state
* LPARAM lParam 0
*
* Return Value: 0
*
* Description: set the new state of the check box.
*
************************************************************************/
LRESULT CCheckButton::OnSetCheck(WPARAM wParam, LPARAM lParam) {
CRect controlRect;
m_bCheckState = wParam; // set the new state value
GetWindowRect(&controlRect); // force a repaint of the check box
controlRect.left = CHECK_BOX_DX;
controlRect.top = ((controlRect.bottom - controlRect.top) - CHECK_BOX_SIZE) >> 1;
controlRect.right = CHECK_BOX_DX + CHECK_BOX_SIZE;
controlRect.bottom = controlRect.top + CHECK_BOX_SIZE;
InvalidateRect(&controlRect, false);
UpdateWindow();
return 0;
}
/*************************************************************************
*
* OnGetCheck()
*
* Parameters:
* WPARAM wParam 0
* LPARAM lParam 0
*
* Return Value: true / false for current check state
*
* Description: get the current state of the check box.
*
************************************************************************/
LRESULT CCheckButton::OnGetCheck(WPARAM wParam, LPARAM lParam) {
return m_bCheckState; // return the current state value
}
// CCheckButton message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CCheckButton, CButton)
//{{AFX_MSG_MAP( CCheckButton )
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
ON_MESSAGE(BM_SETCHECK, CCheckButton::OnSetCheck)
ON_MESSAGE(BM_GETCHECK, CCheckButton::OnGetCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CRadioButton, CButton)
/*************************************************************************
*
* CRadioButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Constructor for button class. Initialize all fields
* to logical nullptr. Calls should then be made to other
* button routines to load palettes and bitmaps.
*
************************************************************************/
CRadioButton::CRadioButton() {
m_bCheckState = false;
m_pPalette = nullptr;
m_cButtonFace = RGB_RADIO_FACE;
m_cButtonControl = RGB_RADIO_CONTROL;
m_cButtonText = RGB_RADIO_TEXT;
m_cButtonTextDisabled = RGB_RADIO_TEXT_DISABLE;
m_cButtonOutline = RGB_RADIO_OUTLINE;
}
/*************************************************************************
*
* ~CRadioButton()
*
* Parameters: none
*
* Return Value: none
*
* Description: Destructor for button class. It is important to tear
* things down in the order we built them; map out bitmap,
* map out the palette, then discard the device context -
* failure to release key resources will cause application
* or system crashes.
*
************************************************************************/
CRadioButton::~CRadioButton() {
m_pPalette = nullptr;
}
/*************************************************************************
*
* OnEraseBkgnd()
*
* Parameters: none
*
* Return Value: none
*
* Description: Do not let Windows automatically erase our window
* to white.
*
************************************************************************/
bool CRadioButton::OnEraseBkgnd(CDC *pDC) {
return true; // do not automatically erase background to white
}
/*************************************************************************
*
* SetPalette()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
*
* Return Value: none
*
* Description: registers the palette to be used when painting the button;
* it is assumed to be a shared resource and hence is NOT
* deleted when the button is destroyed.
*
************************************************************************/
void CRadioButton::SetPalette(CPalette *pPalette) {
m_pPalette = pPalette; // save the palette pointer
}
/*************************************************************************
*
* SetColors()
*
* Parameters:
* CPalette * pointer to palette to be used when painting the button
* COLORREF cFace PALETTERGB color value for the face of the button
* COLORREF cControl PALETTERGB color value for the control box
* COLORREF cText PALETTERGB color value for the text in the button
* COLORREF cTextDisabled PALETTERGB color value for the text when disabled
* COLORREF cOutline PALETTERGB color value for the bounding rectangle
*
* Return Value: none
*
* Description: establishes the colors to use when painting the button;
* note that cHighlight and CShadow are reversed when the
* button is selected (i.e. down).
*
************************************************************************/
void CRadioButton::SetColors(CPalette *pPalette, COLORREF cFace, COLORREF cControl, COLORREF cText, COLORREF cTextDisabled, COLORREF cOutline) {
m_pPalette = pPalette;
m_cButtonFace = cFace;
m_cButtonControl = cControl;
m_cButtonText = cText;
m_cButtonTextDisabled = cTextDisabled;
m_cButtonOutline = cOutline;
}
/*************************************************************************
*
* SetControl()
*
* Parameters:
* unsigned int nID control identifier for the dialog button
* CWnd * pParent pointer to parent window owning the button
*
* Return Value:
* bool success / failure condition
*
* Description: associate this button with a dialog control.
*
************************************************************************/
bool CRadioButton::SetControl(unsigned int nID, CWnd * pParent) {
if (!CRadioButton::SubclassDlgItem(nID, pParent)) // attach the Button to the dialog control
return false;
SetButtonStyle(BS_OWNERDRAW, false);
return true;
}
/*************************************************************************
*
* DrawItem()
*
* Parameters: pointer to button structure information
*
* Return Value: none
*
* Description: Paint a button appropriately, based on its current state.
*
************************************************************************/
void CRadioButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC *pDC;
CPalette *pPalOld = nullptr;
CPen outlinePen, controlPen, framePen, *pOldPen;
CBrush faceBrush, *pOldBrush, myQuill, controlBrush;
COLORREF myTextColor, oldTextColor;
int nUnderscore = -1;
int nMyTextLength,
i, j, x, y, dx, dy;
char chMyText[128];
TEXTMETRIC fontMetrics;
CSize textInfo,
letterInfo,
underscoreInfo;
CRect controlRect, focusRect, selectRect;
CWnd *pParentWnd;
pParentWnd = GetParent();
if (!IsWindowVisible() || // punt if not visible
(pParentWnd == nullptr) ||
!(*pParentWnd).IsWindowVisible())
return;
nMyTextLength = GetWindowText((char *) &chMyText, 127);
chMyText[nMyTextLength] = '\0'; // fetch the button label and strip
for (i = 0, j = 0; i <= nMyTextLength; i++) { // ... out any apersand characters
if (chMyText[i] == '&') // ... which are used to force underscoring
nUnderscore = j; // ... of the next letter, which in turn
else { // ... indicates the keyboard key equivalent
chMyText[j] = chMyText[i];
j += 1;
}
}
nMyTextLength = j - 1;
pDC = new CDC; // setup the device context given to us
(*pDC).Attach((*lpDrawItemStruct).hDC); // ... as a pointer to a CDC object
if (m_pPalette != nullptr) { // map the palette into the context
pPalOld = (*pDC).SelectPalette(m_pPalette, true);
(*pDC).RealizePalette(); // ... and tell the system to use it
}
if (((*lpDrawItemStruct).itemState & ODS_GRAYED) || // setup text color based on enable/disable state
((*lpDrawItemStruct).itemState & ODS_DISABLED))
myTextColor = m_cButtonTextDisabled;
else
myTextColor = m_cButtonText;
// calculate the button width and height
dx = (*lpDrawItemStruct).rcItem.right - (*lpDrawItemStruct).rcItem.left;
dy = (*lpDrawItemStruct).rcItem.bottom - (*lpDrawItemStruct).rcItem.top;
// create the bounding rectangle for the box
controlRect.SetRect((*lpDrawItemStruct).rcItem.left + RADIO_BOX_DX,
(*lpDrawItemStruct).rcItem.top + ((dy - RADIO_BOX_SIZE) >> 1),
(*lpDrawItemStruct).rcItem.left + RADIO_BOX_DX + RADIO_BOX_SIZE,
(*lpDrawItemStruct).rcItem.top + ((dy - RADIO_BOX_SIZE) >> 1) + RADIO_BOX_SIZE);
selectRect = controlRect;
// create the pens and brushes we need
outlinePen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonOutline);
faceBrush.CreateSolidBrush(m_cButtonFace);
controlPen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonControl);
controlBrush.CreateSolidBrush(m_cButtonControl);
framePen.CreatePen(PS_INSIDEFRAME, 1, m_cButtonControl);
pOldBrush = (*pDC).SelectObject(&faceBrush);
if ((*lpDrawItemStruct).itemAction & ODA_DRAWENTIRE) {
pOldPen = (*pDC).SelectObject(&outlinePen); // fill in the whole control
(*pDC).Rectangle(&(*lpDrawItemStruct).rcItem);
} else {
pOldPen = (*pDC).SelectObject(&controlPen); // fill in just the box
(*pDC).Ellipse(&controlRect);
}
(*pDC).SelectObject(pOldPen);
pOldPen = (*pDC).SelectObject(&framePen);
(*pDC).Ellipse(&controlRect); // paint the box and indicate selection
if ((*lpDrawItemStruct).itemState & ODS_SELECTED) {
controlRect.InflateRect(-1, -1);
(*pDC).Ellipse(&controlRect);
}
(*pDC).SelectObject(pOldPen);
(*pDC).SelectObject(pOldBrush);
if (m_bCheckState) { // indicate that the box is checked
selectRect.InflateRect(-2, -2);
pOldPen = (*pDC).SelectObject(&controlPen);
pOldBrush = (*pDC).SelectObject(&controlBrush);
(*pDC).Ellipse(&selectRect);
(*pDC).SelectObject(pOldBrush);
(*pDC).SelectObject(pOldPen);
}
(*pDC).GetTextMetrics(&fontMetrics); // get some info about the font
textInfo = (*pDC).GetTextExtent(chMyText, nMyTextLength); // get the area spanned by the text
x = (*lpDrawItemStruct).rcItem.left + RADIO_TEXT_DX;
y = (*lpDrawItemStruct).rcItem.top + ((dy - textInfo.cy) >> 1);
(*pDC).SetBkMode(TRANSPARENT); // make the text overlay transparently
oldTextColor = (*pDC).SetTextColor(myTextColor); // set the color of the text
(*pDC).TextOut(x, y, (const char *) &chMyText, nMyTextLength);
if (nUnderscore >= 0) { // put the underscore where it belongs
underscoreInfo = (*pDC).GetTextExtent(chMyText, nUnderscore);
dx = x + underscoreInfo.cx;
letterInfo = (*pDC).GetTextExtent(&chMyText[nUnderscore], 1);
underscoreInfo = (*pDC).GetTextExtent((const char *) "_", 1);
dx += (letterInfo.cx - underscoreInfo.cx) >> 1;
(*pDC).TextOut(dx, y, (const char *) "_", 1);
}
(*pDC).SetTextColor(oldTextColor);
focusRect.SetRect(x - FOCUS_RECT_DX, // set the focus rectangle
y - FOCUS_RECT_DY, // ... then paint it or clear it
x + textInfo.cx + FOCUS_RECT_DX - 1,
y + textInfo.cy + FOCUS_RECT_DY + 1);
if ((*lpDrawItemStruct).itemState & ODS_FOCUS) {
myQuill.CreateStockObject(DKGRAY_BRUSH);
(*pDC).FrameRect(&focusRect, &myQuill);
} else {
// (*pDC).FrameRect(&focusRect, &faceBrush);
}
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
(*pDC).Detach(); // dismantle the temporary CDC we built
delete pDC;
}
/*************************************************************************
*
* OnSetRadio()
*
* Parameters:
* WPARAM wParam true / false for new check state
* LPARAM lParam 0
*
* Return Value: 0
*
* Description: set the new state of the radio button box, and update
* other members of the group as needed.
*
************************************************************************/
LRESULT CRadioButton::OnSetCheck(WPARAM wParam, LPARAM lParam) {
CRect controlRect;
CWnd *pBase, *pWnd, *pParent;
m_bCheckState = wParam; // set the new state value
GetWindowRect(&controlRect); // force a repaint of the check box
controlRect.left = RADIO_BOX_DX;
controlRect.top = ((controlRect.bottom - controlRect.top) - RADIO_BOX_SIZE) >> 1;
controlRect.right = RADIO_BOX_DX + RADIO_BOX_SIZE;
controlRect.bottom = controlRect.top + RADIO_BOX_SIZE;
InvalidateRect(&controlRect, false);
UpdateWindow();
if (m_bCheckState == true) { // if we are the control in the
pBase = pWnd = FromHandlePermanent(m_hWnd); // ... group being set, then we
pParent = (*pWnd).GetParent(); // ... need to clear all of the others
while (true) { // so fetch the next control
pWnd = (*pParent).GetNextDlgGroupItem(pWnd, true);
if (pWnd == pBase) // ... and clear it if its not us
break;
(*pWnd).SendMessage(BM_SETCHECK, false, 0);
}
}
return 0;
}
/*************************************************************************
*
* OnGetRadio()
*
* Parameters:
* WPARAM wParam 0
* LPARAM lParam 0
*
* Return Value: true / false for current check state
*
* Description: get the current state of the check box.
*
************************************************************************/
LRESULT CRadioButton::OnGetCheck(WPARAM wParam, LPARAM lParam) {
return m_bCheckState; // return the current state value
}
// CRadioButton message map:
// Associate messages with member functions.
//
BEGIN_MESSAGE_MAP(CRadioButton, CButton)
//{{AFX_MSG_MAP( CRadioButton )
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM()
ON_MESSAGE(BM_SETCHECK, CRadioButton::OnSetCheck)
ON_MESSAGE(BM_GETCHECK, CRadioButton::OnGetCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
} // namespace HodjNPodj
} // namespace Bagel