Mercurial > foo_out_sdl
view foosdk/sdk/libPPUI/CButtonLite.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line source
#pragma once #include <functional> #include <vsstyle.h> #include "wtl-pp.h" #include "win32_op.h" #include "DarkMode.h" typedef CWinTraits<WS_CHILD|WS_TABSTOP,0> CButtonLiteTraits; class CButtonLite : public CWindowImpl<CButtonLite, CWindow, CButtonLiteTraits > { public: BEGIN_MSG_MAP_EX(CButtonLite) MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, MousePassThru) MSG_WM_MOUSELEAVE(OnMouseLeave) MSG_WM_SETTEXT(OnSetText) MSG_WM_PAINT( OnPaint ) MSG_WM_MOUSEMOVE(OnMouseMove) MSG_WM_LBUTTONDOWN(OnLButtonDown) MSG_WM_SETFOCUS(OnSetFocus) MSG_WM_KILLFOCUS(OnKillFocus) MSG_WM_KEYDOWN(OnKeyDown) MSG_WM_KEYUP(OnKeyUp) MSG_WM_CHAR(OnChar) MSG_WM_ENABLE(OnEnable) MESSAGE_HANDLER_EX(WM_GETDLGCODE, OnGetDlgCode) MSG_WM_SETFONT(OnSetFont) MSG_WM_GETFONT(OnGetFont) MSG_WM_CREATE(OnCreate) END_MSG_MAP() std::function<void () > ClickHandler; unsigned Measure() const { auto font = myGetFont(); LOGFONT lf; WIN32_OP_D(font.GetLogFont(lf)); MakeBoldFont( lf ); CFont bold; WIN32_OP_D(bold.CreateFontIndirect(&lf)); CWindowDC dc(*this); auto oldFont = dc.SelectFont( bold ); CSize size (0,0); { CString measure; measure = L"#"; measure += m_textDrawMe; WIN32_OP_D(dc.GetTextExtent(measure, measure.GetLength(), &size)); } dc.SelectFont( oldFont ); return size.cx; } std::function< void (HWND) > TabCycleHandler; std::function< HBRUSH (CDCHandle) > CtlColorHandler; std::function< bool (HWND) > WantTabCheck; CWindow WndCtlColorTarget; // Rationale: sometimes you want a different text to be presented to accessibility APIs than actually drawn // For an example, a clear button looks best with a multiplication sign, but the narrator should say "clear" or so when focused void DrawAlternateText( const wchar_t * textDrawMe ) { m_textDrawMe = textDrawMe; } protected: LRESULT MousePassThru(UINT cMsg, WPARAM cFlags, LPARAM lParam) { SetMsgHandled(FALSE); CPoint cPoint(lParam); const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; if (cMsg == WM_MOUSEWHEEL || cMsg == WM_MOUSEHWHEEL || (cFlags & maskButtons) != 0) { ToggleHot(false); } if (cMsg == WM_MOUSEWHEEL || cMsg == WM_MOUSEHWHEEL) { TogglePressed(false); } if (cMsg == WM_LBUTTONUP) { bool wasPressed = m_pressed; TogglePressed(false); if (wasPressed) OnClicked(); SetMsgHandled(TRUE); } return 0; } CFontHandle m_font; void OnSetFont(HFONT font, BOOL bRedraw) { m_font = font; if (bRedraw) Invalidate(); } HFONT OnGetFont() { return m_font; } LRESULT OnGetDlgCode(UINT, WPARAM wp, LPARAM) { if ( wp == VK_TAB && TabCycleHandler != NULL) { if ( WantTabCheck == NULL || WantTabCheck(m_hWnd) ) { TabCycleHandler( m_hWnd ); return DLGC_WANTTAB; } } SetMsgHandled(FALSE); return 0; } void OnChar(UINT, UINT, UINT) { } void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { (void)nRepCnt; (void)nFlags; switch(nChar) { case VK_SPACE: case VK_RETURN: TogglePressed(true); break; } } void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { (void)nRepCnt; (void)nFlags; switch(nChar) { case VK_SPACE: case VK_RETURN: TogglePressed(false); OnClicked(); break; } } void OnSetFocus(CWindow) { m_focused = true; Invalidate(); } void OnKillFocus(CWindow) { m_focused = false; Invalidate(); } CFontHandle myGetFont() const { auto f = GetFont(); if ( f == NULL ) f = (HFONT) GetStockObject(DEFAULT_GUI_FONT); return f; } static void MakeBoldFont(LOGFONT & lf ) { lf.lfWeight += 300; if (lf.lfWeight > 1000 ) lf.lfWeight = 1000; } CWindow GetCtlColorTarget() { CWindow target = WndCtlColorTarget; if (target == NULL) target = GetParent(); return target; } virtual void DrawBackground( CDCHandle dc, CRect rcClient ) { { HBRUSH brush = NULL; if (CtlColorHandler) { brush = CtlColorHandler(dc); } else { brush = (HBRUSH)GetCtlColorTarget().SendMessage(WM_CTLCOLORBTN, (WPARAM)dc.m_hDC, (LPARAM)this->m_hWnd); } if (brush != NULL) { dc.FillRect(rcClient, brush); dc.SetBkMode(TRANSPARENT); } } if ( IsPressed() ) { CTheme theme; if (theme.OpenThemeData(*this, L"BUTTON" )) { DrawThemeBackground(theme, dc, BP_PUSHBUTTON, PBS_PRESSED, rcClient, rcClient ); } else { DrawFrameControl( dc, rcClient, DFC_BUTTON, DFCS_PUSHED ); } } else if (m_hot) { CTheme theme; if (theme.OpenThemeData(*this, L"BUTTON")) { DrawThemeBackground(theme, dc, BP_PUSHBUTTON, PBS_HOT, rcClient, rcClient); } else { DrawFrameControl(dc, rcClient, DFC_BUTTON, DFCS_HOT); } } } virtual void OnPaint(CDCHandle) { CPaintDC pdc(*this); CRect rcClient; if (! GetClientRect( &rcClient ) ) return; auto font = myGetFont(); /* CFont fontOverride; if ( IsPressed() ) { LOGFONT lf; font.GetLogFont( lf ); MakeBoldFont( lf ); fontOverride.CreateFontIndirect( & lf ); font = fontOverride; } */ HFONT oldFont = pdc.SelectFont( font ); DrawBackground( pdc.m_hDC, rcClient ); pdc.SetBkMode( TRANSPARENT ); if ( !IsWindowEnabled() ) { pdc.SetTextColor( DarkMode::GetSysColor(COLOR_GRAYTEXT) ); } else if ( m_focused ) { pdc.SetTextColor( DarkMode::GetSysColor(COLOR_HIGHLIGHT) ); } pdc.DrawText( m_textDrawMe, m_textDrawMe.GetLength(), &rcClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_NOPREFIX ); pdc.SelectFont( oldFont ); } virtual void OnClicked() { if ( ClickHandler ) { ClickHandler(); } else { GetParent().PostMessage( WM_COMMAND, MAKEWPARAM( this->GetDlgCtrlID(), BN_CLICKED ), (LPARAM) m_hWnd ); } } bool IsPressed() {return m_pressed; } private: int OnCreate(LPCREATESTRUCT lpCreateStruct) { DarkMode::ApplyDarkThemeCtrl(*this, DarkMode::IsDialogDark(GetCtlColorTarget(), WM_CTLCOLORBTN)); if ( lpCreateStruct->lpszName != nullptr ) this->m_textDrawMe = lpCreateStruct->lpszName; SetMsgHandled(FALSE); return 0; } void OnEnable(BOOL) { Invalidate(); SetMsgHandled(FALSE); } void ToggleHot( bool bHot ) { if ( bHot != m_hot ) { m_hot = bHot; Invalidate(); } } void OnMouseMove(UINT nFlags, CPoint) { const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; if ((nFlags & maskButtons) != 0) return; ToggleHot(true); TrackMouseLeave(); } void OnLButtonDown(UINT nFlags, CPoint) { const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; if ( ( nFlags & maskButtons ) != MK_LBUTTON ) return; TogglePressed( true ); TrackMouseLeave(); } void TogglePressed( bool bPressed ) { if ( bPressed != m_pressed ) { m_pressed = bPressed; Invalidate(); } } int OnSetText(LPCTSTR lpstrText) { m_textDrawMe = lpstrText; Invalidate(); SetMsgHandled(FALSE); return 0; } void TrackMouseLeave() { TRACKMOUSEEVENT tme = { sizeof(tme) }; tme.dwFlags = TME_LEAVE; tme.hwndTrack = m_hWnd; TrackMouseEvent(&tme); } void OnMouseLeave() { ToggleHot(false); TogglePressed(false); } bool m_pressed = false, m_focused = false, m_hot = false; CString m_textDrawMe; };
