| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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/>.
- */
- //////////////////////////////////////////////////////////////////////
- //
- // Toolbar.CPP
- //
- // Implementation of a 'fancy' toolbar using hi-color buttons
- //
- #include "stdafx.h"
- #include "Toolbar.H"
- BEGIN_MESSAGE_MAP(CFancyToolbar, CControlBar)
- //{{AFX_MSG_MAP(CFancyToolbar)
- ON_WM_PAINT()
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- //////////////////////////////////////////////////////////////
- //
- // Local Constants
- //
- const TCHAR * const TOOLBAR_CLASS_NAME = TEXT ("FANCYTOOLBAR");
- //////////////////////////////////////////////////////////////
- //
- // CFancyToolbar
- //
- CFancyToolbar::CFancyToolbar (void)
- : m_iButtons (0),
- m_iCurrentButton (-1)
- {
- // Ensure that the toolbar window class is registered
- RegisterFancyToolbarClass ();
- ::memset (m_pButtonArray, 0, sizeof (m_pButtonArray));
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // ~CFancyToolbar
- //
- CFancyToolbar::~CFancyToolbar (void)
- {
- for (int iButton = 0; iButton < m_iButtons; iButton ++)
- {
- if (m_pButtonArray[iButton].hBMPUp)
- {
- // Free the BMP for this button
- ::DeleteObject (m_pButtonArray[iButton].hBMPUp);
- m_pButtonArray[iButton].hBMPUp = NULL;
- }
-
- if (m_pButtonArray[iButton].hBMPDn)
- {
- // Free the BMP for this button
- ::DeleteObject (m_pButtonArray[iButton].hBMPDn);
- m_pButtonArray[iButton].hBMPDn = NULL;
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // RegisterFancyToolbarClass
- //
- void
- CFancyToolbar::RegisterFancyToolbarClass (void)
- {
- // Is this class already registered?
- WNDCLASS classInfo = { 0 };
- if (::GetClassInfo (::AfxGetInstanceHandle (),
- TOOLBAR_CLASS_NAME,
- &classInfo) != TRUE)
- {
- classInfo.style = CS_PARENTDC;
- classInfo.lpfnWndProc = ::DefWindowProc;
- classInfo.hInstance = ::AfxGetInstanceHandle ();
- classInfo.hCursor = ::LoadCursor (NULL, IDC_ARROW);
- classInfo.hbrBackground = (HBRUSH)COLOR_BTNFACE;
- classInfo.lpszClassName = TOOLBAR_CLASS_NAME;
- // Register the class with windows
- ::RegisterClass (&classInfo);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Create
- //
- void
- CFancyToolbar::OnPaint ()
- {
- Paint ();
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Create
- //
- BOOL
- CFancyToolbar::Create
- (
- LPCTSTR pszWindowName,
- CWnd *pCParentWnd,
- UINT uiID
- )
- {
- // Create the toolbar window using our own special window class
- RECT rect = { 0 };
- BOOL bReturn = CWnd::Create (TOOLBAR_CLASS_NAME, pszWindowName, WS_CHILD | WS_VISIBLE, rect, pCParentWnd, uiID);
- // Were we successful?
- ASSERT (bReturn);
- if (bReturn)
- {
- // Set the bar style, but don't allow docking
- SetBarStyle (GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
- EnableDocking (CBRS_ALIGN_ANY);
- }
- // Return the TRUE/FALSE result code
- return bReturn;
- }
- //////////////////////////////////////////////////////////////
- //
- // DrawButton
- //
- void
- CFancyToolbar::DrawButton
- (
- HDC hDC,
- int iXPos,
- int iYPos,
- HBITMAP hBMP
- )
- {
- // Create a screen-compatible DC
- HDC hMemDC = ::CreateCompatibleDC (hDC);
- if (hMemDC)
- {
- // Select the BMP to paint into the DC
- HBITMAP hOldBMP = (HBITMAP)::SelectObject (hMemDC, hBMP);
- // Paint the BMP in its slot
- ::BitBlt (hDC, iXPos, iYPos, BUTTON_WIDTH, BUTTON_HEIGHT, hMemDC, 0, 0, SRCCOPY);
- // Select the old BMP back into the DC and free the DC
- ::SelectObject (hMemDC, hOldBMP);
- DeleteDC (hMemDC);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // AddButton
- //
- void
- CFancyToolbar::AddButton
- (
- UINT iBMPUp,
- UINT iBMPDn,
- int iCommandID,
- BUTTON_TYPE buttonType
- )
- {
- // Increment the button count
- int iButton = m_iButtons ++;
- // Fill in the internal button structure for this entry
- m_pButtonArray[iButton].hBMPUp = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (iBMPUp));
- m_pButtonArray[iButton].hBMPDn = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (iBMPDn));
- m_pButtonArray[iButton].iCommandID = iCommandID;
- m_pButtonArray[iButton].buttonType = buttonType;
- m_pButtonArray[iButton].currentState = StateUp;
- m_pButtonArray[iButton].bVisible = TRUE;
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // Paint
- //
- void
- CFancyToolbar::Paint (void)
- {
- // Get the window's DC
- HDC hDC = ::GetDC (m_hWnd);
- if (hDC)
- {
- // Get the bounding rectangle of the window
- RECT rect;
- ::GetClientRect (m_hWnd, &rect);
- // Paint the background light gray
- HBRUSH hBrush = ::CreateSolidBrush (RGB (192, 192, 192));
- ::FillRect (hDC, &rect, hBrush);
- ::DeleteObject (hBrush);
- // Loop through each button and paint it
- int iXPos = BORDER_LEFT;
- for (int iButton = 0; iButton < m_iButtons; iButton ++)
- {
- // Is this button visible?
- if (m_pButtonArray[iButton].bVisible)
- {
- // Determine which BMP to use
- HBITMAP hBMP = m_pButtonArray[iButton].hBMPUp;
- if (m_pButtonArray[iButton].currentState == StateDn)
- {
- hBMP = m_pButtonArray[iButton].hBMPDn;
- }
- // Draw this button
- DrawButton (hDC,
- iXPos,
- ((rect.bottom-rect.top) >> 1) - BUTTON_MIDDLE,
- hBMP);
- // Increment the current x position
- iXPos += BUTTON_WIDTH;
- }
- }
-
- // Free the windows DC
- ::ReleaseDC (m_hWnd, hDC);
- }
- // Let the window know its done painting
- ::ValidateRect (m_hWnd, NULL);
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // ButtonFromPoint
- //
- int
- CFancyToolbar::ButtonFromPoint (const CPoint &point)
- {
- int iIndex = -1;
- // Loop through all the buttons until we've found the
- // one we're looking for
- int iXPos = BORDER_LEFT;
- for (int iButton = 0; (iButton < m_iButtons) && (iIndex == -1); iButton ++)
- {
- // Is this the button we're looking for?
- if (m_pButtonArray[iButton].bVisible &&
- (point.x >= iXPos) && (point.x <= iXPos + BUTTON_WIDTH) &&
- (point.y >= BORDER_TOP) && (point.y <= BORDER_TOP+BUTTON_HEIGHT))
- {
- // Yup, this is the button we're looking for
- iIndex = iButton;
- }
- // Increment the current position
- iXPos += BUTTON_WIDTH;
- }
-
- // Return the zero based index of the button we're looking for
- return iIndex;
- }
- //////////////////////////////////////////////////////////////
- //
- // HandleLButtonUp
- //
- void
- CFancyToolbar::OnLButtonDown
- (
- UINT nFlags,
- CPoint point
- )
- {
- // Determine which button was clicked
- int iButton = ButtonFromPoint (point);
- if (iButton >= 0)
- {
- // Flip the button state
- m_pButtonArray[iButton].currentState = (STATE_INFO)!m_pButtonArray[iButton].currentState;
- // Determine which BMP to paint
- HBITMAP hBMP = m_pButtonArray[iButton].hBMPUp;
- if (m_pButtonArray[iButton].currentState == StateDn)
- {
- hBMP = m_pButtonArray[iButton].hBMPDn;
- }
- // Get the DC for the window
- HDC hDC = ::GetDC (m_hWnd);
- if (hDC)
- {
- // Get the bounding rectangle for the window
- RECT rect;
- ::GetClientRect (m_hWnd, &rect);
- // Draw the selected button
- DrawButton (hDC,
- BORDER_LEFT + iButton*BUTTON_WIDTH,
- ((rect.bottom-rect.top) >> 1) - BUTTON_MIDDLE,
- hBMP);
- // Release the window's DC
- ::ReleaseDC (m_hWnd, hDC);
- }
-
- // Is this a 'normal' or 2 state button?
- if (m_pButtonArray[iButton].buttonType == TypeNormal)
- {
- // Normal button, so trap all mouse message so if the user
- // lets up the mouse button outside the button rectangle we don't do anything
- m_iCurrentButton = iButton;
- ::SetCapture (m_hWnd);
- }
- else
- {
- // 2 state button
- m_iCurrentButton = -1;
- // Send the message to the window's parent to let them know a command has occured
- ::AfxGetMainWnd ()->PostMessage (WM_COMMAND,
- MAKELONG (m_pButtonArray[iButton].iCommandID, BN_CLICKED),
- (LPARAM)m_hWnd);
- }
- }
- else
- {
- CControlBar::OnLButtonDown (nFlags, point);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // HandleLButtonUp
- //
- void
- CFancyToolbar::OnLButtonUp
- (
- UINT nFlags,
- CPoint point
- )
- {
- // Were we currently processing a button?
- if (m_iCurrentButton >= 0)
- {
- // Which button were we processing?
- int iButton = ButtonFromPoint (point);
- if (iButton == m_iCurrentButton)
- {
- // Fire a command to the parent
- ::AfxGetMainWnd ()->PostMessage (WM_COMMAND,
- MAKELONG (m_pButtonArray[iButton].iCommandID, BN_CLICKED),
- (LPARAM)m_hWnd);
- }
- // Reset the button state
- m_pButtonArray[m_iCurrentButton].currentState = StateUp;
- // Get the window's DC
- HDC hDC = ::GetDC (m_hWnd);
- if (hDC)
- {
- // Get the bounding rectangle of the window
- RECT rect;
- ::GetClientRect (m_hWnd, &rect);
- // Paint the button
- DrawButton (hDC,
- BORDER_LEFT + m_iCurrentButton*BUTTON_WIDTH,
- ((rect.bottom-rect.top) >> 1) - BUTTON_MIDDLE,
- m_pButtonArray[m_iCurrentButton].hBMPUp);
- // Free the window's DC
- ::ReleaseDC (m_hWnd, hDC);
- }
- // Let go of the mouse capture
- ::ReleaseCapture ();
- }
- else
- {
- CControlBar::OnLButtonUp (nFlags, point);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // OnDraw
- //
- void
- CFancyToolbar::OnDraw (CDC* pDC)
- {
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // PreCreateWindow
- //
- BOOL
- CFancyToolbar::PreCreateWindow (CREATESTRUCT& cs)
- {
- // Allow the base class to process this message
- return CControlBar::PreCreateWindow (cs);
- }
- //////////////////////////////////////////////////////////////
- //
- // SetButtonState
- //
- void
- CFancyToolbar::SetButtonState
- (
- int iCommandID,
- STATE_INFO newState,
- BOOL bRepaint
- )
- {
- BOOL bFound = FALSE;
- // Loop through all the buttons until we've found the one we're looking for
- for (int iButton = 0;
- (iButton < m_iButtons) && (bFound == FALSE);
- iButton ++)
- {
- if (m_pButtonArray[iButton].iCommandID == iCommandID)
- {
- // Set the new state
- m_pButtonArray[iButton].currentState = newState;
- if (bRepaint)
- {
- // Repaint the toolbar
- //Paint ();
- InvalidateRect (NULL);
- UpdateWindow ();
- }
- // Found it!
- bFound = TRUE;
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////////
- //
- // GetButtonState
- //
- CFancyToolbar::STATE_INFO
- CFancyToolbar::GetButtonState (int iCommandID) const
- {
- STATE_INFO stateInfo = StateUp;
- // Loop through all the buttons until we've found the one we're looking for
- BOOL bFound = FALSE;
- for (int iButton = 0;
- (iButton < m_iButtons) && (bFound == FALSE);
- iButton ++)
- {
- if (m_pButtonArray[iButton].iCommandID == iCommandID)
- {
- // Return the current state to the caller
- stateInfo = m_pButtonArray[iButton].currentState;
- // Found it!
- bFound = TRUE;
- }
- }
- // Return the state of the requested button
- return stateInfo;
- }
|