Mercurial > foo_out_sdl
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include <functional> | |
| 4 #include <vsstyle.h> | |
| 5 #include "wtl-pp.h" | |
| 6 #include "win32_op.h" | |
| 7 #include "DarkMode.h" | |
| 8 | |
| 9 typedef CWinTraits<WS_CHILD|WS_TABSTOP,0> CButtonLiteTraits; | |
| 10 | |
| 11 class CButtonLite : public CWindowImpl<CButtonLite, CWindow, CButtonLiteTraits > { | |
| 12 public: | |
| 13 BEGIN_MSG_MAP_EX(CButtonLite) | |
| 14 MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, MousePassThru) | |
| 15 MSG_WM_MOUSELEAVE(OnMouseLeave) | |
| 16 MSG_WM_SETTEXT(OnSetText) | |
| 17 MSG_WM_PAINT( OnPaint ) | |
| 18 MSG_WM_MOUSEMOVE(OnMouseMove) | |
| 19 MSG_WM_LBUTTONDOWN(OnLButtonDown) | |
| 20 MSG_WM_SETFOCUS(OnSetFocus) | |
| 21 MSG_WM_KILLFOCUS(OnKillFocus) | |
| 22 MSG_WM_KEYDOWN(OnKeyDown) | |
| 23 MSG_WM_KEYUP(OnKeyUp) | |
| 24 MSG_WM_CHAR(OnChar) | |
| 25 MSG_WM_ENABLE(OnEnable) | |
| 26 MESSAGE_HANDLER_EX(WM_GETDLGCODE, OnGetDlgCode) | |
| 27 MSG_WM_SETFONT(OnSetFont) | |
| 28 MSG_WM_GETFONT(OnGetFont) | |
| 29 MSG_WM_CREATE(OnCreate) | |
| 30 END_MSG_MAP() | |
| 31 std::function<void () > ClickHandler; | |
| 32 | |
| 33 unsigned Measure() const { | |
| 34 auto font = myGetFont(); | |
| 35 LOGFONT lf; | |
| 36 WIN32_OP_D(font.GetLogFont(lf)); | |
| 37 MakeBoldFont( lf ); | |
| 38 CFont bold; | |
| 39 WIN32_OP_D(bold.CreateFontIndirect(&lf)); | |
| 40 CWindowDC dc(*this); | |
| 41 auto oldFont = dc.SelectFont( bold ); | |
| 42 CSize size (0,0); | |
| 43 | |
| 44 { | |
| 45 CString measure; | |
| 46 measure = L"#"; | |
| 47 measure += m_textDrawMe; | |
| 48 WIN32_OP_D(dc.GetTextExtent(measure, measure.GetLength(), &size)); | |
| 49 } | |
| 50 | |
| 51 dc.SelectFont( oldFont ); | |
| 52 | |
| 53 return size.cx; | |
| 54 } | |
| 55 std::function< void (HWND) > TabCycleHandler; | |
| 56 std::function< HBRUSH (CDCHandle) > CtlColorHandler; | |
| 57 std::function< bool (HWND) > WantTabCheck; | |
| 58 CWindow WndCtlColorTarget; | |
| 59 | |
| 60 // Rationale: sometimes you want a different text to be presented to accessibility APIs than actually drawn | |
| 61 // For an example, a clear button looks best with a multiplication sign, but the narrator should say "clear" or so when focused | |
| 62 void DrawAlternateText( const wchar_t * textDrawMe ) { | |
| 63 m_textDrawMe = textDrawMe; | |
| 64 } | |
| 65 | |
| 66 protected: | |
| 67 LRESULT MousePassThru(UINT cMsg, WPARAM cFlags, LPARAM lParam) { | |
| 68 SetMsgHandled(FALSE); | |
| 69 CPoint cPoint(lParam); | |
| 70 const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; | |
| 71 if (cMsg == WM_MOUSEWHEEL || cMsg == WM_MOUSEHWHEEL || (cFlags & maskButtons) != 0) { | |
| 72 ToggleHot(false); | |
| 73 } | |
| 74 if (cMsg == WM_MOUSEWHEEL || cMsg == WM_MOUSEHWHEEL) { | |
| 75 TogglePressed(false); | |
| 76 } | |
| 77 if (cMsg == WM_LBUTTONUP) { | |
| 78 bool wasPressed = m_pressed; | |
| 79 TogglePressed(false); | |
| 80 if (wasPressed) OnClicked(); | |
| 81 SetMsgHandled(TRUE); | |
| 82 } | |
| 83 return 0; | |
| 84 } | |
| 85 CFontHandle m_font; | |
| 86 void OnSetFont(HFONT font, BOOL bRedraw) { | |
| 87 m_font = font; if (bRedraw) Invalidate(); | |
| 88 } | |
| 89 HFONT OnGetFont() { | |
| 90 return m_font; | |
| 91 } | |
| 92 LRESULT OnGetDlgCode(UINT, WPARAM wp, LPARAM) { | |
| 93 if ( wp == VK_TAB && TabCycleHandler != NULL) { | |
| 94 if ( WantTabCheck == NULL || WantTabCheck(m_hWnd) ) { | |
| 95 TabCycleHandler( m_hWnd ); | |
| 96 return DLGC_WANTTAB; | |
| 97 } | |
| 98 } | |
| 99 SetMsgHandled(FALSE); return 0; | |
| 100 } | |
| 101 void OnChar(UINT, UINT, UINT) { | |
| 102 } | |
| 103 void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { | |
| 104 (void)nRepCnt; (void)nFlags; | |
| 105 switch(nChar) { | |
| 106 case VK_SPACE: | |
| 107 case VK_RETURN: | |
| 108 TogglePressed(true); break; | |
| 109 } | |
| 110 } | |
| 111 void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { | |
| 112 (void)nRepCnt; (void)nFlags; | |
| 113 switch(nChar) { | |
| 114 case VK_SPACE: | |
| 115 case VK_RETURN: | |
| 116 TogglePressed(false); | |
| 117 OnClicked(); | |
| 118 break; | |
| 119 } | |
| 120 } | |
| 121 void OnSetFocus(CWindow) { | |
| 122 m_focused = true; Invalidate(); | |
| 123 } | |
| 124 void OnKillFocus(CWindow) { | |
| 125 m_focused = false; Invalidate(); | |
| 126 } | |
| 127 CFontHandle myGetFont() const { | |
| 128 auto f = GetFont(); | |
| 129 if ( f == NULL ) f = (HFONT) GetStockObject(DEFAULT_GUI_FONT); | |
| 130 return f; | |
| 131 } | |
| 132 static void MakeBoldFont(LOGFONT & lf ) { | |
| 133 lf.lfWeight += 300; | |
| 134 if (lf.lfWeight > 1000 ) lf.lfWeight = 1000; | |
| 135 } | |
| 136 | |
| 137 CWindow GetCtlColorTarget() { | |
| 138 CWindow target = WndCtlColorTarget; | |
| 139 if (target == NULL) target = GetParent(); | |
| 140 return target; | |
| 141 } | |
| 142 virtual void DrawBackground( CDCHandle dc, CRect rcClient ) { | |
| 143 { | |
| 144 HBRUSH brush = NULL; | |
| 145 if (CtlColorHandler) { | |
| 146 brush = CtlColorHandler(dc); | |
| 147 } else { | |
| 148 brush = (HBRUSH)GetCtlColorTarget().SendMessage(WM_CTLCOLORBTN, (WPARAM)dc.m_hDC, (LPARAM)this->m_hWnd); | |
| 149 } | |
| 150 if (brush != NULL) { | |
| 151 dc.FillRect(rcClient, brush); | |
| 152 dc.SetBkMode(TRANSPARENT); | |
| 153 } | |
| 154 } | |
| 155 if ( IsPressed() ) { | |
| 156 CTheme theme; | |
| 157 if (theme.OpenThemeData(*this, L"BUTTON" )) { | |
| 158 DrawThemeBackground(theme, dc, BP_PUSHBUTTON, PBS_PRESSED, rcClient, rcClient ); | |
| 159 } else { | |
| 160 DrawFrameControl( dc, rcClient, DFC_BUTTON, DFCS_PUSHED ); | |
| 161 } | |
| 162 } else if (m_hot) { | |
| 163 CTheme theme; | |
| 164 if (theme.OpenThemeData(*this, L"BUTTON")) { | |
| 165 DrawThemeBackground(theme, dc, BP_PUSHBUTTON, PBS_HOT, rcClient, rcClient); | |
| 166 } else { | |
| 167 DrawFrameControl(dc, rcClient, DFC_BUTTON, DFCS_HOT); | |
| 168 } | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 virtual void OnPaint(CDCHandle) { | |
| 173 CPaintDC pdc(*this); | |
| 174 | |
| 175 CRect rcClient; | |
| 176 if (! GetClientRect( &rcClient ) ) return; | |
| 177 | |
| 178 auto font = myGetFont(); | |
| 179 /* | |
| 180 CFont fontOverride; | |
| 181 if ( IsPressed() ) { | |
| 182 LOGFONT lf; | |
| 183 font.GetLogFont( lf ); | |
| 184 MakeBoldFont( lf ); | |
| 185 fontOverride.CreateFontIndirect( & lf ); | |
| 186 font = fontOverride; | |
| 187 } | |
| 188 */ | |
| 189 HFONT oldFont = pdc.SelectFont( font ); | |
| 190 | |
| 191 DrawBackground( pdc.m_hDC, rcClient ); | |
| 192 | |
| 193 pdc.SetBkMode( TRANSPARENT ); | |
| 194 if ( !IsWindowEnabled() ) { | |
| 195 pdc.SetTextColor( DarkMode::GetSysColor(COLOR_GRAYTEXT) ); | |
| 196 } else if ( m_focused ) { | |
| 197 pdc.SetTextColor( DarkMode::GetSysColor(COLOR_HIGHLIGHT) ); | |
| 198 } | |
| 199 pdc.DrawText( m_textDrawMe, m_textDrawMe.GetLength(), &rcClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_NOPREFIX ); | |
| 200 | |
| 201 pdc.SelectFont( oldFont ); | |
| 202 } | |
| 203 virtual void OnClicked() { | |
| 204 if ( ClickHandler ) { | |
| 205 ClickHandler(); | |
| 206 } else { | |
| 207 GetParent().PostMessage( WM_COMMAND, MAKEWPARAM( this->GetDlgCtrlID(), BN_CLICKED ), (LPARAM) m_hWnd ); | |
| 208 } | |
| 209 } | |
| 210 bool IsPressed() {return m_pressed; } | |
| 211 private: | |
| 212 int OnCreate(LPCREATESTRUCT lpCreateStruct) { | |
| 213 DarkMode::ApplyDarkThemeCtrl(*this, DarkMode::IsDialogDark(GetCtlColorTarget(), WM_CTLCOLORBTN)); | |
| 214 if ( lpCreateStruct->lpszName != nullptr ) this->m_textDrawMe = lpCreateStruct->lpszName; | |
| 215 SetMsgHandled(FALSE); return 0; | |
| 216 } | |
| 217 void OnEnable(BOOL) { | |
| 218 Invalidate(); SetMsgHandled(FALSE); | |
| 219 } | |
| 220 void ToggleHot( bool bHot ) { | |
| 221 if ( bHot != m_hot ) { | |
| 222 m_hot = bHot; Invalidate(); | |
| 223 } | |
| 224 } | |
| 225 void OnMouseMove(UINT nFlags, CPoint) { | |
| 226 const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; | |
| 227 if ((nFlags & maskButtons) != 0) return; | |
| 228 ToggleHot(true); | |
| 229 TrackMouseLeave(); | |
| 230 } | |
| 231 void OnLButtonDown(UINT nFlags, CPoint) { | |
| 232 const DWORD maskButtons = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2; | |
| 233 if ( ( nFlags & maskButtons ) != MK_LBUTTON ) return; | |
| 234 TogglePressed( true ); | |
| 235 TrackMouseLeave(); | |
| 236 } | |
| 237 void TogglePressed( bool bPressed ) { | |
| 238 if ( bPressed != m_pressed ) { | |
| 239 m_pressed = bPressed; Invalidate(); | |
| 240 } | |
| 241 } | |
| 242 int OnSetText(LPCTSTR lpstrText) { | |
| 243 m_textDrawMe = lpstrText; | |
| 244 Invalidate(); SetMsgHandled(FALSE); | |
| 245 return 0; | |
| 246 } | |
| 247 void TrackMouseLeave() { | |
| 248 TRACKMOUSEEVENT tme = { sizeof(tme) }; | |
| 249 tme.dwFlags = TME_LEAVE; | |
| 250 tme.hwndTrack = m_hWnd; | |
| 251 TrackMouseEvent(&tme); | |
| 252 } | |
| 253 void OnMouseLeave() { | |
| 254 ToggleHot(false); TogglePressed(false); | |
| 255 } | |
| 256 | |
| 257 bool m_pressed = false, m_focused = false, m_hot = false; | |
| 258 CString m_textDrawMe; | |
| 259 }; |
