Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
Toolbar.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6DISABLE_COMPILER_MSC_WARNING_START (5054)
7#include <afxctl.h>
8DISABLE_COMPILER_MSC_WARNING_END (5054)
9
10#include <atlbase.h>
11
12#include "DispIDs.h"
13
14#include "Toolbar.h"
15
17
18namespace {
19 template <class EnumType, class CollType>
20 HRESULT CreateSTLEnumerator (IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection)
21 {
22 if (ppUnk == NULL)
23 return E_POINTER;
24 *ppUnk = NULL;
25
26 CComObject<EnumType>* pEnum = NULL;
27 HRESULT hr = CComObject<EnumType>::CreateInstance (&pEnum);
28
29 if (FAILED (hr))
30 return hr;
31
32 hr = pEnum->Init (pUnkForRelease, collection);
33
34 if (SUCCEEDED (hr))
35 hr = pEnum->QueryInterface (ppUnk);
36
37 if (FAILED (hr))
38 delete pEnum;
39
40 return hr;
41 }
42}
43
44namespace {
45 size_t DoFindIndex (vector<CComPtr<IDispatch>>* list, VARIANT eltIntNameOrObj)
46 {
47 CComVariant e2r (eltIntNameOrObj);
48 if (SUCCEEDED (e2r.ChangeType (VT_UI4))) {
49 size_t idx = e2r.ulVal;
50 if (idx >= list->size ()) {
51 ThrowIfErrorHRESULT (DISP_E_MEMBERNOTFOUND);
52 }
53 return idx;
54 }
55 else if (SUCCEEDED (e2r.ChangeType (VT_DISPATCH))) {
56 for (vector<CComPtr<IDispatch>>::iterator i = list->begin (); i != list->end (); ++i) {
57 if ((*i).p == e2r.pdispVal) {
58 return i - list->begin ();
59 }
60 }
61 }
62 return kBadIndex;
63 }
64}
65
66namespace {
67 // Used as an implemenation detail for CComEnumOnSTL<> invocation
68 struct STL_ATL_COPY_VARIANT_IDISPATCH {
69 static HRESULT copy (VARIANT* p1, const ATL::CComPtr<IDispatch>* p2)
70 {
71 if (p2 != NULL and *p2 != NULL) {
72 p1->vt = VT_DISPATCH;
73 p1->pdispVal = *p2;
74 IDispatch* pp2 = *p2;
75 pp2->AddRef ();
76 return S_OK;
77 }
78 else {
79 p1->vt = VT_EMPTY;
80 return E_FAIL;
81 }
82 }
83 static void init (VARIANT* p)
84 {
85 p->vt = VT_EMPTY;
86 }
87 static void destroy (VARIANT* p)
88 {
89 ::VariantClear (p);
90 }
91 };
92}
93
94namespace {
95 void DoEnableDisableChecksEtcsOnMenu (CComPtr<IDispatch> al, HMENU menu)
96 {
97 UINT itemCount = ::GetMenuItemCount (menu);
98 for (UINT i = 0; i < itemCount; ++i) {
99 UINT itemID = ::GetMenuItemID (menu, i);
100 if (itemID == -1) {
101 // see if a popup menu - and recurse
102 MENUITEMINFO menuItemInfo;
103 memset (&menuItemInfo, 0, sizeof (menuItemInfo));
104 menuItemInfo.cbSize = sizeof (menuItemInfo);
105 Verify (::GetMenuItemInfo (menu, i, true, &menuItemInfo));
106 if (menuItemInfo.hSubMenu != NULL) {
107 DoEnableDisableChecksEtcsOnMenu (al, menuItemInfo.hSubMenu);
108 }
109 }
110 else {
111 wstring cmdName = CmdNum2Name (itemID);
112 CComVariant result;
113 CComVariant cmdNameCCV = cmdName.c_str ();
114 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandEnabled, &cmdNameCCV, &result));
115 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
116 ::EnableMenuItem (menu, i, MF_BYPOSITION | (result.boolVal ? MF_ENABLED : MF_GRAYED));
117
118 cmdNameCCV = cmdName.c_str ();
119 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandChecked, &cmdNameCCV, &result));
120 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
121 ::CheckMenuItem (menu, i, MF_BYPOSITION | (result.boolVal ? MF_CHECKED : MF_UNCHECKED));
122 }
123 }
124 }
125}
126
127/*
128 ********************************************************************************
129 ******************* ActiveLedIt_IconButtonToolbarElement ***********************
130 ********************************************************************************
131 */
132ActiveLedIt_IconButtonToolbarElement::ActiveLedIt_IconButtonToolbarElement ()
133 : fHWnd (NULL)
134 , fButtonImage ()
135 , fPressedOnClick (false)
136 , fCommand ()
137 , fIconButtonStyle (eIconButton_PushButton)
138 , fOwningToolbar (NULL)
139 , fOwningActiveLedIt (NULL)
140 , fBounds ()
141{
142}
143
144ActiveLedIt_IconButtonToolbarElement::~ActiveLedIt_IconButtonToolbarElement ()
145{
146}
147
148HRESULT ActiveLedIt_IconButtonToolbarElement::FinalConstruct ()
149{
150 return S_OK;
151}
152
153void ActiveLedIt_IconButtonToolbarElement::FinalRelease ()
154{
155}
156
157LRESULT ActiveLedIt_IconButtonToolbarElement::OnLButtonDown ([[maybe_unused]] UINT uMsg, [[maybe_unused]] WPARAM wParam,
158 [[maybe_unused]] LPARAM lParam, BOOL& bHandled)
159{
160 bHandled = true;
161 try {
162 switch (fIconButtonStyle) {
163 case eIconButton_Sticky:
164 case eIconButton_Toggle: {
165 if (IsWindowEnabled ()) {
166 bool wasPushed = !!(SendMessage (BM_GETSTATE) & BST_PUSHED);
167 fPressedOnClick = wasPushed;
168 if (fIconButtonStyle == eIconButton_Sticky) {
169 SendMessage (BM_SETSTATE, BST_PUSHED);
170 }
171 else {
172 SendMessage (BM_SETSTATE, wasPushed ? 0 : BST_PUSHED);
173 }
174 SendMessage (GetParent (), WM_COMMAND, MAKEWPARAM (GetWindowLong (GWL_ID), BN_CLICKED), reinterpret_cast<LPARAM> (m_hWnd));
175 }
176 return true;
177 }
178
179 case eIconButton_Popup: {
180 CComPtr<IDispatch> oal = fOwningActiveLedIt;
181 CComPtr<IALAcceleratorTable> accelerators;
182 {
183 CComVariant accel;
184 ThrowIfErrorHRESULT (oal.GetProperty (DISPID_AcceleratorTable, &accel));
185 if (SUCCEEDED (accel.ChangeType (VT_DISPATCH))) {
186 accelerators = CComQIPtr<IALAcceleratorTable> (accel.pdispVal);
187 }
188 }
189 if (SUCCEEDED (fCommand.ChangeType (VT_DISPATCH))) {
190 CComQIPtr<IALCommandList> cm = fCommand.pdispVal;
191 if (cm != NULL) {
192 HMENU mH = NULL;
193 if (SUCCEEDED (cm->GeneratePopupMenu (accelerators, &mH))) {
194 try {
195 RECT wr;
196 GetWindowRect (&wr);
197 DoEnableDisableChecksEtcsOnMenu (oal, mH);
198 int cmdNum =
199 ::TrackPopupMenu (mH, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, wr.left, wr.bottom, 0, m_hWnd, NULL);
200 if (cmdNum != 0) {
201 wstring cmdName = CmdNum2Name (cmdNum);
202 if (cmdName.length () != 0) {
203 CComVariant cmdNameCCV = cmdName.c_str ();
204 ThrowIfErrorHRESULT (oal.Invoke1 (DISPID_InvokeCommand, &cmdNameCCV));
205 }
206 }
207 ::DestroyMenu (mH);
208 }
209 catch (...) {
210 ::DestroyMenu (mH);
211 throw;
212 }
213 }
214 }
215 }
216 return true;
217 }
218
219 default: {
220 return DefWindowProc ();
221 }
222 }
223 }
224 catch (...) {
225 // ignore exceptions doing mousedown processing
226 return true;
227 }
228}
229
230LRESULT ActiveLedIt_IconButtonToolbarElement::OnLButtonUp ([[maybe_unused]] UINT uMsg, [[maybe_unused]] WPARAM wParam,
231 [[maybe_unused]] LPARAM lParam, BOOL& bHandled)
232{
233 /*
234 * Pushing on a button causes it to grab the focus (cannot figure out how to stop this - but its not SO bad).
235 * Instead - just reset the focus back to the OCX when the click is finihsed.
236 */
237 LRESULT lr = DefWindowProc ();
238 try {
239 CComPtr<IDispatch> oal = fOwningActiveLedIt;
240 CComVariant res;
241 ThrowIfErrorHRESULT (oal.GetProperty (DISPID_HWND, &res));
242 ThrowIfErrorHRESULT (res.ChangeType (VT_UINT));
243 HWND controlHWND = reinterpret_cast<HWND> (res.iVal);
244 ::SetFocus (controlHWND);
245 }
246 catch (...) {
247 // ignore any errors here.
248 }
249 bHandled = true;
250 return lr;
251}
252
253LRESULT ActiveLedIt_IconButtonToolbarElement::OnMouseMove ([[maybe_unused]] UINT uMsg, [[maybe_unused]] WPARAM wParam, LPARAM lParam, BOOL& bHandled)
254{
255 if (GetCapture () == m_hWnd and fIconButtonStyle == eIconButton_PushButton) {
256#define MY_GET_X_LPARAM(lp) ((int)(short)LOWORD (lp))
257#define MY_GET_Y_LPARAM(lp) ((int)(short)HIWORD (lp))
258 RECT cr;
259 GetClientRect (&cr);
260 bool clickedInside = (AsLedRect (cr).Contains (Led_Point (MY_GET_Y_LPARAM (lParam), MY_GET_X_LPARAM (lParam))));
261 bool newPressed = clickedInside ? not fPressedOnClick : fPressedOnClick;
262 SendMessage (BM_SETSTATE, newPressed ? BST_PUSHED : 0);
263 bHandled = true;
264 return DefWindowProc ();
265#undef MY_GET_X_LPARAM
266#undef MY_GET_Y_LPARAM
267 }
268 return 0;
269}
270
271STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_PreferredHeight (UINT* pVal)
272{
273 const DistanceType kBorderSize = 3;
274 try {
275 if (pVal == NULL) {
276 return E_INVALIDARG;
277 }
278 if (fButtonImage.p == NULL) {
279 *pVal = kBorderSize * 2;
280 return S_OK;
281 }
282 OLE_XSIZE_HIMETRIC height = 0;
283 ThrowIfErrorHRESULT (fButtonImage->get_Height (&height));
284 SIZEL hmSize;
285 hmSize.cx = 0;
286 hmSize.cy = height;
287 SIZEL pixSize;
288 ::memset (&pixSize, 0, sizeof (pixSize));
289 AtlHiMetricToPixel (&hmSize, &pixSize);
290 *pVal = pixSize.cy + 2 * kBorderSize;
291 return S_OK;
292 }
293 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
294}
295
296STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_PreferredWidth (UINT* pVal)
297{
298 const DistanceType kBorderSize = 3;
299 try {
300 if (pVal == NULL) {
301 return E_INVALIDARG;
302 }
303 if (fButtonImage.p == NULL) {
304 *pVal = kBorderSize * 2;
305 return S_OK;
306 }
307 OLE_XSIZE_HIMETRIC width = 0;
308 ThrowIfErrorHRESULT (fButtonImage->get_Width (&width));
309 SIZEL hmSize;
310 hmSize.cx = width;
311 hmSize.cy = 0;
312 SIZEL pixSize;
313 ::memset (&pixSize, 0, sizeof (pixSize));
314 AtlHiMetricToPixel (&hmSize, &pixSize);
315 *pVal = pixSize.cx + kBorderSize * 2;
316 return S_OK;
317 }
318 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
319}
320
321STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_X (INT* pVal)
322{
323 try {
324 if (pVal == NULL) {
325 return E_INVALIDARG;
326 }
327 *pVal = fBounds.left;
328 return S_OK;
329 }
330 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
331}
332
333STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_Y (INT* pVal)
334{
335 try {
336 if (pVal == NULL) {
337 return E_INVALIDARG;
338 }
339 *pVal = fBounds.top;
340 return S_OK;
341 }
342 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
343}
344
345STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_Width (UINT* pVal)
346{
347 try {
348 if (pVal == NULL) {
349 return E_INVALIDARG;
350 }
351 *pVal = fBounds.GetWidth ();
352 return S_OK;
353 }
354 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
355}
356
357STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_Height (UINT* pVal)
358{
359 try {
360 if (pVal == NULL) {
361 return E_INVALIDARG;
362 }
363 *pVal = fBounds.GetHeight ();
364 return S_OK;
365 }
366 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
367}
368
369STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::SetRectangle (int X, int Y, UINT width, UINT height)
370{
371 try {
372 if (m_hWnd != NULL) {
373 fBounds = Led_Rect (Y, X, height, width);
374 MoveWindow (X, Y, width, height);
375 }
376 return S_OK;
377 }
378 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
379}
380
381STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::NotifyOfOwningToolbar (IDispatch* owningToolbar, IDispatch* owningActiveLedIt)
382{
383 try {
384 if (fOwningToolbar != owningToolbar or fOwningActiveLedIt != owningActiveLedIt) {
385 if (m_hWnd != NULL) { // maybe already destroyed by parent window destruction
386 DestroyWindow ();
387 }
388
389 fOwningToolbar = owningToolbar;
390 fOwningActiveLedIt = owningActiveLedIt;
391
392 if (fOwningToolbar != NULL) {
393 RECT r = AsRECT (fBounds);
394 HWND parentHWND = 0;
395 {
396 CComQIPtr<IALToolbar> otb = fOwningToolbar;
397 ThrowIfErrorHRESULT (otb->get_hWnd (&parentHWND));
398 }
399
400 int itemID = 0;
401 Create (parentHWND, &r, NULL, WS_CHILD | WS_VISIBLE, 0, itemID);
402 UpdateButtonObj ();
403 }
404 }
405 }
406 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
407 return S_OK;
408}
409
410STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::UpdateEnableState ()
411{
412 try {
413 if (m_hWnd != NULL) {
414 bool enabled = false;
415 if (fOwningActiveLedIt != NULL) {
416 CComPtr<IDispatch> al = fOwningActiveLedIt;
417 if (fIconButtonStyle == eIconButton_Popup) {
418 enabled = true; // even if no items enabled - still allow show of menus (kind of like in a menu bar)
419 }
420 else {
421 CComVariant result;
422 CComVariant cmdCCV = fCommand;
423 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandEnabled, &cmdCCV, &result));
424 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
425 enabled = !!result.boolVal;
426 }
427 }
428 EnableWindow (enabled);
429 if (fIconButtonStyle == eIconButton_Toggle or fIconButtonStyle == eIconButton_Sticky) {
430 bool checked = false;
431 if (fOwningActiveLedIt != NULL) {
432 CComPtr<IDispatch> al = fOwningActiveLedIt;
433 CComVariant result;
434 CComVariant commandCCV = fCommand;
435 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandChecked, &commandCCV, &result));
436 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
437 checked = !!result.boolVal;
438 }
439 SendMessage (BM_SETSTATE, checked ? BST_PUSHED : 0);
440 }
441 }
442 return S_OK;
443 }
444 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
445}
446
447STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_ButtonImage (IDispatch** pVal)
448{
449 try {
450 if (pVal == NULL) {
451 return E_INVALIDARG;
452 }
453 *pVal = CComQIPtr<IDispatch> (fButtonImage);
454 if (*pVal != NULL) {
455 (*pVal)->AddRef ();
456 }
457 return S_OK;
458 }
459 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
460}
461
462STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::put_ButtonImage (IDispatch* val)
463{
464 try {
465 fButtonImage = val;
467 if (fButtonImage.p == NULL and val != NULL) {
468 DumpSupportedInterfaces (val, "SUP INTERFACES FOR JSCRIPT IMAGE");
469 }
470 }
471 UpdateButtonObj ();
472 return S_OK;
473 }
474 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
475}
476
477STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_Command (VARIANT* pVal)
478{
479 try {
480 if (pVal == NULL) {
481 return E_INVALIDARG;
482 }
483 CComVariant{fCommand}.Detach (pVal);
484 return S_OK;
485 }
486 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
487}
488
489STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::put_Command (VARIANT val)
490{
491 try {
492 fCommand = CComVariant{val};
493 CheckFixButtonStyle ();
494 UpdateButtonObj ();
495 return S_OK;
496 }
497 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
498}
499
500STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::get_ButtonStyle (IconButtonStyle* pVal)
501{
502 try {
503 if (pVal == NULL) {
504 return E_INVALIDARG;
505 }
506 *pVal = fIconButtonStyle;
507 return S_OK;
508 }
509 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
510}
511
512STDMETHODIMP ActiveLedIt_IconButtonToolbarElement::put_ButtonStyle (IconButtonStyle val)
513{
514 try {
515 fIconButtonStyle = val;
516 CheckFixButtonStyle ();
517 UpdateButtonObj ();
518 return S_OK;
519 }
520 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
521}
522
523void ActiveLedIt_IconButtonToolbarElement::UpdateButtonObj ()
524{
525 if (m_hWnd != NULL) {
526 if (fButtonImage.p == NULL) {
527 (void)SendMessage (BM_SETIMAGE, IMAGE_ICON, NULL);
528 (void)SendMessage (BM_SETIMAGE, IMAGE_BITMAP, NULL);
529 }
530 else {
531 short pictType = 0;
532 ThrowIfErrorHRESULT (fButtonImage->get_Type (&pictType));
533 OLE_HANDLE pictHandle = NULL;
534 ThrowIfErrorHRESULT (fButtonImage->get_Handle (&pictHandle));
535 switch (pictType) {
536 case PICTYPE_BITMAP: {
537 SetWindowLong (GWL_STYLE, (GetWindowLong (GWL_STYLE) & ~BS_ICON) | BS_BITMAP);
538 (void)SendMessage (BM_SETIMAGE, IMAGE_BITMAP, pictHandle);
539 } break;
540 case PICTYPE_ICON: {
541 SetWindowLong (GWL_STYLE, (GetWindowLong (GWL_STYLE) & ~BS_BITMAP) | BS_ICON);
542 (void)SendMessage (BM_SETIMAGE, IMAGE_ICON, pictHandle);
543 } break;
544 default: {
545 (void)SendMessage (BM_SETIMAGE, IMAGE_ICON, NULL);
546 } break;
547 }
548 }
549
550 SetWindowLong (GWL_ID, CmdObjOrName2Num (fCommand));
551 }
552}
553
554void ActiveLedIt_IconButtonToolbarElement::CheckFixButtonStyle ()
555{
556 CComVariant c = fCommand;
557 if (SUCCEEDED (c.ChangeType (VT_DISPATCH))) {
558 CComQIPtr<IALCommandList> alc = c.pdispVal;
559 if (alc.p == NULL) {
560 if (fIconButtonStyle == eIconButton_Popup) {
561 fIconButtonStyle = eIconButton_PushButton;
562 }
563 }
564 else {
565 fIconButtonStyle = eIconButton_Popup;
566 }
567 }
568 else {
569 if (fIconButtonStyle == eIconButton_Popup) {
570 fIconButtonStyle = eIconButton_PushButton;
571 }
572 }
573}
574
575/*
576 ********************************************************************************
577 ********************* ActiveLedIt_ComboBoxToolbarElement ***********************
578 ********************************************************************************
579 */
580ActiveLedIt_ComboBoxToolbarElement::ActiveLedIt_ComboBoxToolbarElement ()
581 : fDropDownActive (false)
582 , fHWnd (NULL)
583 , fComboBox ()
584 , fPreferredWidth (100)
585 , fPressedOnClick (false)
586 , fCommandList ()
587 , fCommandListCache ()
588 , fOwningToolbar (NULL)
589 , fOwningActiveLedIt (NULL)
590 , fBounds ()
591{
592}
593
594ActiveLedIt_ComboBoxToolbarElement::~ActiveLedIt_ComboBoxToolbarElement ()
595{
596}
597
598HRESULT ActiveLedIt_ComboBoxToolbarElement::FinalConstruct ()
599{
600 return S_OK;
601}
602
603void ActiveLedIt_ComboBoxToolbarElement::FinalRelease ()
604{
605}
606
607LRESULT ActiveLedIt_ComboBoxToolbarElement::OnCBDropDown ([[maybe_unused]] USHORT uMsg, [[maybe_unused]] USHORT wParam,
608 [[maybe_unused]] HWND ctlHandle, BOOL& bHandled)
609{
610 fDropDownActive = true;
611 LRESULT lr = DefWindowProc ();
612 bHandled = true;
613 return lr;
614}
615
616LRESULT ActiveLedIt_ComboBoxToolbarElement::OnCBCloseUp ([[maybe_unused]] USHORT uMsg, [[maybe_unused]] USHORT wParam,
617 [[maybe_unused]] HWND ctlHandle, BOOL& bHandled)
618{
619 fDropDownActive = false;
620 /*
621 * Using the combobox grabs the focus. Reset the focus back to the OCX when the click is finihsed.
622 */
623 LRESULT lr = DefWindowProc ();
624 try {
625 CComPtr<IDispatch> oal = fOwningActiveLedIt;
626 CComVariant res;
627 ThrowIfErrorHRESULT (oal.GetProperty (DISPID_HWND, &res));
628 ThrowIfErrorHRESULT (res.ChangeType (VT_UINT));
629 HWND controlHWND = reinterpret_cast<HWND> (res.iVal);
630 ::SetFocus (controlHWND);
631 }
632 catch (...) {
633 // ignore any errors here.
634 }
635 bHandled = true;
636 return lr;
637}
638
639LRESULT ActiveLedIt_ComboBoxToolbarElement::OnCBSelChange ([[maybe_unused]] USHORT uMsg, [[maybe_unused]] USHORT wParam,
640 [[maybe_unused]] HWND ctlHandle, BOOL& bHandled)
641{
642 bHandled = true;
643 LRESULT lr = DefWindowProc ();
644 int r = static_cast<int> (fComboBox.SendMessage (CB_GETCURSEL, 0, 0));
645 try {
646 if (r >= 0 and static_cast<size_t> (r) < fCommandListCache.size ()) {
647#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
648 CComQIPtr<IALCommand> alc = (IDispatch*)fCommandListCache[r];
649#else
650 CComQIPtr<IALCommand> alc = fCommandListCache[r];
651#endif
652 CComBSTR internalName;
653 ThrowIfErrorHRESULT (alc->get_InternalName (&internalName));
654 CComPtr<IDispatch> al = fOwningActiveLedIt;
655 CComVariant internalNameCCV = internalName;
656 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_InvokeCommand, &internalNameCCV));
657 }
658 }
659 catch (...) {
660 }
661 return lr;
662}
663
664STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_PreferredHeight (UINT* pVal)
665{
666 try {
667 if (pVal == NULL) {
668 return E_INVALIDARG;
669 }
670 const DistanceType kWhiteSluff = 4;
671 *pVal = ::GetSystemMetrics (SM_CYVSCROLL) + kWhiteSluff;
672 return S_OK;
673 }
674 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
675}
676
677STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_PreferredWidth (UINT* pVal)
678{
679 try {
680 if (pVal == NULL) {
681 return E_INVALIDARG;
682 }
683 *pVal = fPreferredWidth;
684 return S_OK;
685 }
686 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
687}
688
689STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_X (INT* pVal)
690{
691 try {
692 if (pVal == NULL) {
693 return E_INVALIDARG;
694 }
695 *pVal = fBounds.left;
696 return S_OK;
697 }
698 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
699}
700
701STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_Y (INT* pVal)
702{
703 try {
704 if (pVal == NULL) {
705 return E_INVALIDARG;
706 }
707 *pVal = fBounds.top;
708 return S_OK;
709 }
710 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
711}
712
713STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_Width (UINT* pVal)
714{
715 try {
716 if (pVal == NULL) {
717 return E_INVALIDARG;
718 }
719 *pVal = fBounds.GetWidth ();
720 return S_OK;
721 }
722 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
723}
724
725STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_Height (UINT* pVal)
726{
727 try {
728 if (pVal == NULL) {
729 return E_INVALIDARG;
730 }
731 *pVal = fBounds.GetHeight ();
732 return S_OK;
733 }
734 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
735}
736
737STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::SetRectangle (int X, int Y, UINT width, UINT height)
738{
739 try {
740 if (m_hWnd != NULL) {
741 fBounds = Led_Rect (Y, X, height, width);
742 MoveWindow (X, Y, width, height);
743 RECT cr;
744 GetClientRect (&cr);
745 cr.bottom += 200; // fix SPR#1659- comboboxes don't popup on Win2k
746 fComboBox.MoveWindow (&cr);
747 }
748 return S_OK;
749 }
750 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
751}
752
753STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::NotifyOfOwningToolbar (IDispatch* owningToolbar, IDispatch* owningActiveLedIt)
754{
755 try {
756 if (fOwningToolbar != owningToolbar or fOwningActiveLedIt != owningActiveLedIt) {
757 if (m_hWnd != NULL) { // maybe already destroyed by parent window destruction
758 DestroyWindow ();
759 }
760
761 fOwningToolbar = owningToolbar;
762 fOwningActiveLedIt = owningActiveLedIt;
763
764 if (fOwningToolbar != NULL) {
765 RECT r = AsRECT (fBounds);
766 HWND parentHWND = 0;
767 {
768 CComQIPtr<IALToolbar> otb = fOwningToolbar;
769 ThrowIfErrorHRESULT (otb->get_hWnd (&parentHWND));
770 }
771
772 Create (parentHWND, &r, NULL, WS_CHILD | WS_VISIBLE);
773 fComboBox.Create (_T("ComboBox"), m_hWnd, &r, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST);
774 {
775 HFONT f = reinterpret_cast<HFONT> (::GetStockObject (DEFAULT_GUI_FONT));
776 fComboBox.SendMessage (WM_SETFONT, reinterpret_cast<LPARAM> (f), true);
777 }
778
779 UpdatePopupObj ();
780 }
781 }
782 }
783 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
784 return S_OK;
785}
786
787STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::UpdateEnableState ()
788{
789 try {
790 if (m_hWnd != NULL and not fDropDownActive) {
791 // Walk list of all subcommands - and if ANY enabled - then we are, and otherwise we are disabled
792 bool enabled = false;
793 size_t idxSelected = kBadIndex;
794 if (fOwningActiveLedIt != NULL) {
795 CComPtr<IDispatch> al = fOwningActiveLedIt;
796 for (vector<CComPtr<IALCommand>>::iterator i = fCommandListCache.begin (); i != fCommandListCache.end (); ++i) {
797 {
798 CComVariant result;
799#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
800 CComVariant alcmdCCV = (IDispatch*)*i;
801#else
802 CComVariant alcmdCCV = *i;
803#endif
804 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandEnabled, &alcmdCCV, &result));
805 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
806 if (result.boolVal) {
807 enabled = true;
808 }
809 }
810 {
811 CComVariant result;
812#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
813 CComVariant alcmdCCV = (IDispatch*)*i;
814#else
815 CComVariant alcmdCCV = *i;
816#endif
817 ThrowIfErrorHRESULT (al.Invoke1 (DISPID_CommandChecked, &alcmdCCV, &result));
818 ThrowIfErrorHRESULT (result.ChangeType (VT_BOOL));
819 if (result.boolVal) {
820 idxSelected = i - fCommandListCache.begin ();
821 }
822 }
823 }
824 }
825 fComboBox.EnableWindow (enabled);
826 if (idxSelected == kBadIndex) {
827 (void)fComboBox.SendMessage (CB_SETCURSEL, static_cast<WPARAM> (-1), 0);
828 }
829 else {
830 Verify (fComboBox.SendMessage (CB_SETCURSEL, static_cast<int> (idxSelected), 0) != CB_ERR);
831 }
832 }
833 return S_OK;
834 }
835 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
836}
837
838STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::get_CommandList (IDispatch** pVal)
839{
840 try {
841 if (pVal == NULL) {
842 return E_INVALIDARG;
843 }
844 *pVal = fCommandList;
845 if (*pVal != NULL) {
846 (*pVal)->AddRef ();
847 }
848 return S_OK;
849 }
850 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
851}
852
853STDMETHODIMP ActiveLedIt_ComboBoxToolbarElement::put_CommandList (IDispatch* val)
854{
855 try {
856 fCommandList = val;
857 UpdatePopupObj ();
858 CallInvalidateLayout ();
859 return S_OK;
860 }
861 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
862}
863
864void ActiveLedIt_ComboBoxToolbarElement::UpdatePopupObj ()
865{
866 if (m_hWnd != NULL) {
867 // resetcoennt in combobox, and then walk list of commands and add items...
868 // Need to keep SIDE-vector of CComPtr<> guys for each elt - since the IALcommandList chould get
869 // changed behind our backs... (need some way to keep them in sync?)
870 (void)fComboBox.SendMessage (CB_RESETCONTENT, 0, 0);
871 fCommandListCache.clear ();
872#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
873 CComQIPtr<IALCommandList> cmdList = (IDispatch*)fCommandList;
874#else
875 CComQIPtr<IALCommandList> cmdList = fCommandList;
876#endif
877 if (cmdList.p != NULL) {
878 long cmdCount = 0;
879 ThrowIfErrorHRESULT (cmdList->get_Count (&cmdCount));
880 HDC hdc = GetWindowDC ();
881 HGDIOBJ oldFont = ::SelectObject (hdc, ::GetStockObject (DEFAULT_GUI_FONT));
882 try {
883 DistanceType maxItemWidth = 0;
884 for (long i = 0; i < cmdCount; ++i) {
885 CComPtr<IDispatch> e;
886 ThrowIfErrorHRESULT (cmdList->get_Item (i, &e));
887#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
888 CComQIPtr<IALCommand> alc = (IDispatch*)e;
889#else
890 CComQIPtr<IALCommand> alc = e;
891#endif
892 CComBSTR name;
893 ThrowIfErrorHRESULT (alc->get_Name (&name));
894 fCommandListCache.push_back (alc);
895 SDKString itemPrintName = String{wstring{name}}.AsSDKString ();
896 Verify (fComboBox.SendMessage (CB_ADDSTRING, 0, reinterpret_cast<LPARAM> (itemPrintName.c_str ())) != CB_ERR);
897 SIZE sz;
898 memset (&sz, 0, sizeof (sz));
899 ::GetTextExtentPoint32 (hdc, itemPrintName.c_str (), static_cast<int> (itemPrintName.length ()), &sz);
900 maxItemWidth = max (maxItemWidth, static_cast<DistanceType> (sz.cx));
901 }
902 ::SelectObject (hdc, oldFont);
903 ReleaseDC (hdc);
904 const DistanceType kMaxMax = 200; // don't make any wider than this - even if really long text...
905 maxItemWidth = min (maxItemWidth, kMaxMax);
906 const DistanceType kWhiteSluff = 6;
907 fPreferredWidth = 2 * ::GetSystemMetrics (SM_CXEDGE) + ::GetSystemMetrics (SM_CXVSCROLL) + maxItemWidth + kWhiteSluff;
908 }
909 catch (...) {
910 ::SelectObject (hdc, oldFont);
911 ReleaseDC (hdc);
912 throw;
913 }
914 }
915 }
916}
917
918void ActiveLedIt_ComboBoxToolbarElement::CallInvalidateLayout ()
919{
920 if (fOwningActiveLedIt != NULL) {
921 CComPtr<IDispatch> oal = fOwningActiveLedIt;
922 ThrowIfErrorHRESULT (oal.Invoke0 (DISPID_InvalidateLayout));
923 }
924}
925
926/*
927 ********************************************************************************
928 ******************* ActiveLedIt_SeparatorToolbarElement ************************
929 ********************************************************************************
930 */
931ActiveLedIt_SeparatorToolbarElement::ActiveLedIt_SeparatorToolbarElement ()
932 : fBounds ()
933{
934}
935
936ActiveLedIt_SeparatorToolbarElement::~ActiveLedIt_SeparatorToolbarElement ()
937{
938}
939
940HRESULT ActiveLedIt_SeparatorToolbarElement::FinalConstruct ()
941{
942 return S_OK;
943}
944
945void ActiveLedIt_SeparatorToolbarElement::FinalRelease ()
946{
947}
948
949STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_PreferredHeight (UINT* pVal)
950{
951 try {
952 if (pVal == NULL) {
953 return E_INVALIDARG;
954 }
955 *pVal = 1;
956 return S_OK;
957 }
958 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
959}
960
961STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_PreferredWidth (UINT* pVal)
962{
963 try {
964 if (pVal == NULL) {
965 return E_INVALIDARG;
966 }
967 *pVal = 6;
968 return S_OK;
969 }
970 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
971}
972
973STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_X (INT* pVal)
974{
975 try {
976 if (pVal == NULL) {
977 return E_INVALIDARG;
978 }
979 *pVal = fBounds.left;
980 return S_OK;
981 }
982 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
983}
984
985STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_Y (INT* pVal)
986{
987 try {
988 if (pVal == NULL) {
989 return E_INVALIDARG;
990 }
991 *pVal = fBounds.top;
992 return S_OK;
993 }
994 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
995}
996
997STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_Width (UINT* pVal)
998{
999 try {
1000 if (pVal == NULL) {
1001 return E_INVALIDARG;
1002 }
1003 *pVal = fBounds.GetWidth ();
1004 return S_OK;
1005 }
1006 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1007}
1008
1009STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::get_Height (UINT* pVal)
1010{
1011 try {
1012 if (pVal == NULL) {
1013 return E_INVALIDARG;
1014 }
1015 *pVal = fBounds.GetHeight ();
1016 return S_OK;
1017 }
1018 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1019}
1020
1021STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::SetRectangle (int X, int Y, UINT width, UINT height)
1022{
1023 try {
1024 fBounds = Led_Rect (Y, X, height, width);
1025 return S_OK;
1026 }
1027 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1028}
1029
1030STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::NotifyOfOwningToolbar (IDispatch* /*owningToolbar*/, IDispatch* /*owningActiveLedIt*/)
1031{
1032 try {
1033 return S_OK;
1034 }
1035 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1036}
1037
1038STDMETHODIMP ActiveLedIt_SeparatorToolbarElement::UpdateEnableState ()
1039{
1040 try {
1041 return S_OK;
1042 }
1043 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1044}
1045
1046/*
1047 ********************************************************************************
1048 ****************************** ActiveLedIt_Toolbar *****************************
1049 ********************************************************************************
1050 */
1051ActiveLedIt_Toolbar::ActiveLedIt_Toolbar ()
1052 : fToolbarItems ()
1053 , fOwningActiveLedIt (NULL)
1054 , fOwningALToolbar (NULL)
1055 , fBounds ()
1056{
1057}
1058
1059ActiveLedIt_Toolbar::~ActiveLedIt_Toolbar ()
1060{
1061}
1062
1063LRESULT ActiveLedIt_Toolbar::OnCommand ([[maybe_unused]] UINT uMsg, WPARAM wParam, [[maybe_unused]] LPARAM lParam, BOOL& bHandled)
1064{
1065 if (!HIWORD (wParam)) {
1066 if (fOwningActiveLedIt != NULL) {
1067 CComPtr<IDispatch> oal = fOwningActiveLedIt;
1068 wstring cmdName = CmdNum2Name (LOWORD (wParam));
1069 CComVariant cmdNameCCV = cmdName.c_str ();
1070 oal.Invoke1 (DISPID_InvokeCommand, &cmdNameCCV);
1071 bHandled = true;
1072 }
1073 }
1074 return -1;
1075}
1076#if 0
1077 LRESULT ActiveLedIt_Toolbar::OnPaint (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1078 {
1079 PAINTSTRUCT ps;
1080 HDC hdc = ::BeginPaint (m_hWnd, &ps);
1081 if (hdc != NULL) {
1082 try {
1083 Tablet tablet (hdc, Tablet::eDoesntOwnDC);
1084 Pen usePen (PS_SOLID, 1, Color::kBlack.GetOSRep ());
1085 GDI_Obj_Selector penSelector (&tablet, usePen);
1086 Led_Rect drawRect = Led_Rect (0, 0, fBounds.GetHeight (), fBounds.GetWidth ());
1087 if (m_hWnd != NULL) { // probbaly not really needed anymore - now that I subtract out the SM_CXYEDGE - but what the heck... Just in case...
1088 RECT cr;
1089 ::GetClientRect (m_hWnd, &cr);
1090 drawRect = AsLedRect (cr);
1091 }
1092 tablet.MoveTo (Led_Point (drawRect.GetBottom () - 1, drawRect.GetLeft ()));
1093 tablet.LineTo (Led_Point (drawRect.GetBottom () - 1, drawRect.GetRight ()));
1094 }
1095 catch (...) {
1096 ::EndPaint (m_hWnd, &ps);
1097 throw;
1098 }
1099 ::EndPaint (m_hWnd, &ps);
1100 }
1101 return 0;
1102 }
1103#endif
1104void ActiveLedIt_Toolbar::CallInvalidateLayout ()
1105{
1106 if (fOwningActiveLedIt != NULL) {
1107 CComPtr<IDispatch> oal = fOwningActiveLedIt;
1108 ThrowIfErrorHRESULT (oal.Invoke0 (DISPID_InvalidateLayout));
1109 }
1110}
1111
1112void ActiveLedIt_Toolbar::DoLayout ()
1113{
1114#if 1
1115 Led_Rect clientBounds = Led_Rect (0, 0, fBounds.GetHeight (), fBounds.GetWidth ());
1116#else
1117 Led_Rect clientBounds = Led_Rect (0, 0, max (static_cast<CoordinateType> (fBounds.GetHeight ()) - 2 * ::GetSystemMetrics (SM_CYEDGE), 0),
1118 max (static_cast<CoordinateType> (fBounds.GetHeight ()) - 2 * ::GetSystemMetrics (SM_CXEDGE), 0));
1119#endif
1120
1121 // MAYBE NOT NEEDED ANYMORE???
1122 if (m_hWnd != NULL) { // probbaly not really needed anymore - now that I subtract out the SM_CXYEDGE - but what the heck... Just in case...
1123 RECT cr;
1124 ::GetClientRect (m_hWnd, &cr);
1125 clientBounds.bottom = max (clientBounds.bottom, cr.bottom);
1126 }
1127
1128 Led_Rect itemBoundsCursor = Led_Rect (clientBounds.GetTop (), clientBounds.GetLeft () + kHTBEdge, clientBounds.GetHeight (), 0);
1129
1130 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1131#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1132 CComQIPtr<IALToolbarElement> tbi = (IDispatch*)*i;
1133#else
1134 CComQIPtr<IALToolbarElement> tbi = *i;
1135#endif
1136 UINT preferredWidth = 0;
1137 ThrowIfErrorHRESULT (tbi->get_PreferredWidth (&preferredWidth));
1138 UINT preferredHeight = 0;
1139 ThrowIfErrorHRESULT (tbi->get_PreferredHeight (&preferredHeight));
1140
1141 DistanceType useHeight = min (DistanceType (preferredHeight), itemBoundsCursor.GetHeight ());
1142 Led_Rect itemBounds = itemBoundsCursor;
1143 itemBounds.right = itemBounds.left + preferredWidth;
1144 itemBoundsCursor.right = itemBounds.right;
1145 itemBounds.bottom = itemBounds.top + useHeight;
1146 itemBounds = CenterRectInRect (itemBounds, itemBoundsCursor);
1147 tbi->SetRectangle (itemBounds.GetLeft (), itemBounds.GetTop (), itemBounds.GetWidth (), itemBounds.GetHeight ());
1148
1149 itemBoundsCursor.left = itemBoundsCursor.right + kHSluff;
1150 itemBoundsCursor.right = itemBoundsCursor.left;
1151 }
1152}
1153
1154HRESULT ActiveLedIt_Toolbar::FinalConstruct ()
1155{
1156 IdleManager::Get ().AddEnterIdler (this);
1157 return S_OK;
1158}
1159
1160void ActiveLedIt_Toolbar::FinalRelease ()
1161{
1162 IdleManager::Get ().RemoveEnterIdler (this);
1163}
1164
1165void ActiveLedIt_Toolbar::OnEnterIdle ()
1166{
1167 try {
1168 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1169#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1170 CComQIPtr<IALToolbarElement> tbi = (IDispatch*)*i;
1171#else
1172 CComQIPtr<IALToolbarElement> tbi = *i;
1173#endif
1174 ThrowIfErrorHRESULT (tbi->UpdateEnableState ());
1175 }
1176 }
1177 catch (...) {
1178 }
1179}
1180
1181STDMETHODIMP ActiveLedIt_Toolbar::get__NewEnum (IUnknown** ppUnk)
1182{
1183 using VarVarEnum = CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, STL_ATL_COPY_VARIANT_IDISPATCH, std::vector<CComPtr<IDispatch>>>;
1184 try {
1185 if (ppUnk == NULL) {
1186 return E_INVALIDARG;
1187 }
1188 return CreateSTLEnumerator<VarVarEnum> (ppUnk, this, fToolbarItems);
1189 }
1190 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1191}
1192
1193STDMETHODIMP ActiveLedIt_Toolbar::get_Item (long Index, IDispatch** pVal)
1194{
1195 try {
1196 if (pVal == NULL) {
1197 return E_INVALIDARG;
1198 }
1199 if (Index < 0 or static_cast<size_t> (Index) >= fToolbarItems.size ()) {
1200 return E_INVALIDARG;
1201 }
1202 *pVal = fToolbarItems[Index];
1203 (*pVal)->AddRef ();
1204 }
1205 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1206 return S_OK;
1207}
1208
1209STDMETHODIMP ActiveLedIt_Toolbar::get_Count (long* pVal)
1210{
1211 try {
1212 if (pVal == NULL) {
1213 return E_INVALIDARG;
1214 }
1215 *pVal = static_cast<long> (fToolbarItems.size ());
1216 }
1217 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1218 return S_OK;
1219}
1220
1221STDMETHODIMP ActiveLedIt_Toolbar::Add (IDispatch* newElt, UINT atIndex)
1222{
1223 try {
1224 if (newElt == NULL) {
1225 return E_INVALIDARG;
1226 }
1227 size_t idx = min (static_cast<size_t> (atIndex), fToolbarItems.size ());
1228 fToolbarItems.insert (fToolbarItems.begin () + idx, newElt);
1229 if (fOwningActiveLedIt != NULL) {
1230 CComQIPtr<IALToolbarElement> tbe = newElt;
1231 ThrowIfErrorHRESULT (tbe->NotifyOfOwningToolbar (this, fOwningActiveLedIt));
1232 }
1233 CallInvalidateLayout ();
1234 }
1235 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1236 return S_OK;
1237}
1238
1239STDMETHODIMP ActiveLedIt_Toolbar::MergeAdd (IDispatch* newElts, UINT afterElt)
1240{
1241 try {
1242 if (newElts == NULL) {
1243 return E_INVALIDARG;
1244 }
1245 size_t idx = min (static_cast<size_t> (afterElt), fToolbarItems.size ());
1246 CComQIPtr<IALToolbar> alt = newElts;
1247 long nElts2Add = 0;
1248 ThrowIfErrorHRESULT (alt->get_Count (&nElts2Add));
1249 for (long i = 0; i < nElts2Add; ++i) {
1250 CComPtr<IDispatch> e;
1251 ThrowIfErrorHRESULT (alt->get_Item (i, &e));
1252 fToolbarItems.insert (fToolbarItems.begin () + idx, e);
1253 if (fOwningActiveLedIt != NULL) {
1254#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1255 CComQIPtr<IALToolbarElement> tbe = (IDispatch*)e;
1256#else
1257 CComQIPtr<IALToolbarElement> tbe = e;
1258#endif
1259 tbe->NotifyOfOwningToolbar (this, fOwningActiveLedIt);
1260 }
1261 ++idx;
1262 }
1263 CallInvalidateLayout ();
1264 }
1265 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1266 return S_OK;
1267}
1268
1269STDMETHODIMP ActiveLedIt_Toolbar::Remove (VARIANT eltIntNameOrIndex)
1270{
1271 try {
1272 size_t idx = DoFindIndex (&fToolbarItems, eltIntNameOrIndex);
1273 if (idx != kBadIndex) {
1274 return E_INVALIDARG;
1275 }
1276 if (fOwningActiveLedIt != NULL) {
1277#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1278 CComQIPtr<IALToolbarElement> tbe = (IDispatch*)fToolbarItems[idx];
1279#else
1280 CComQIPtr<IALToolbarElement> tbe = fToolbarItems[idx];
1281#endif
1282 ThrowIfErrorHRESULT (tbe->NotifyOfOwningToolbar (NULL, NULL));
1283 }
1284 fToolbarItems.erase (fToolbarItems.begin () + idx, fToolbarItems.begin () + idx + 1);
1285 CallInvalidateLayout ();
1286 return S_OK;
1287 }
1288 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1289}
1290
1291STDMETHODIMP ActiveLedIt_Toolbar::Clear ()
1292{
1293 try {
1294 if (fOwningActiveLedIt != NULL) {
1295 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1296#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1297 CComQIPtr<IALToolbarElement> tbe = (IDispatch*)*i;
1298#else
1299 CComQIPtr<IALToolbarElement> tbe = *i;
1300#endif
1301 ThrowIfErrorHRESULT (tbe->NotifyOfOwningToolbar (NULL, NULL));
1302 }
1303 }
1304 fToolbarItems.clear ();
1305 CallInvalidateLayout ();
1306 }
1307 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1308 return S_OK;
1309}
1310
1311STDMETHODIMP ActiveLedIt_Toolbar::get_hWnd (HWND* pVal)
1312{
1313 try {
1314 *pVal = m_hWnd;
1315 }
1316 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1317 return S_OK;
1318}
1319
1320STDMETHODIMP ActiveLedIt_Toolbar::get_PreferredHeight (UINT* pVal)
1321{
1322 try {
1323 if (pVal == NULL) {
1324 return E_INVALIDARG;
1325 }
1326
1327 UINT maxHeight = 0;
1328 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1329#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1330 CComQIPtr<IALToolbarElement> tbi = (IDispatch*)*i;
1331#else
1332 CComQIPtr<IALToolbarElement> tbi = *i;
1333#endif
1334 UINT preferredHeight = 0;
1335 ThrowIfErrorHRESULT (tbi->get_PreferredHeight (&preferredHeight));
1336 maxHeight = max (maxHeight, preferredHeight);
1337 }
1338
1339 // Use MAX preferred height of all buttons, plus room for bottom line, plus room for edges of toolbar itself
1340 // *pVal = maxHeight + 2*kVInset + kRoomForBotLine + 2 * ::GetSystemMetrics (SM_CYEDGE);
1341 // Use MAX preferred height of all buttons, plus room for above/below vinset
1342 *pVal = maxHeight + 2 * kVInset;
1343
1344 return S_OK;
1345 }
1346 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1347}
1348
1349STDMETHODIMP ActiveLedIt_Toolbar::get_PreferredWidth (UINT* pVal)
1350{
1351 try {
1352 if (pVal == NULL) {
1353 return E_INVALIDARG;
1354 }
1355 UINT totalPrefWidth = 0;
1356 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1357#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1358 CComQIPtr<IALToolbarElement> tbi = (IDispatch*)*i;
1359#else
1360 CComQIPtr<IALToolbarElement> tbi = *i;
1361#endif
1362 UINT preferredWidth = 0;
1363 ThrowIfErrorHRESULT (tbi->get_PreferredWidth (&preferredWidth));
1364 totalPrefWidth += preferredWidth;
1365 }
1366
1367 // Use total preferred width of all buttons, plus room for bottom line, plus room for edges of toolbar itself
1368 *pVal = static_cast<UINT> (totalPrefWidth + 2 * kHTBEdge + kHSluff * (fToolbarItems.size ()) + 2 * ::GetSystemMetrics (SM_CYEDGE));
1369
1370 return S_OK;
1371 }
1372 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1373}
1374
1375STDMETHODIMP ActiveLedIt_Toolbar::NotifyOfOwningActiveLedIt (IDispatch* owningActiveLedIt, IDispatch* owningALToolbar)
1376{
1377 try {
1378 if (fOwningActiveLedIt != owningActiveLedIt or fOwningALToolbar != owningALToolbar) {
1379 if (m_hWnd != NULL) {
1380 DestroyWindow ();
1381 }
1382
1383 fOwningActiveLedIt = owningActiveLedIt;
1384 fOwningALToolbar = owningALToolbar;
1385
1386 if (fOwningActiveLedIt != NULL) {
1387 HWND parentHWND = 0;
1388 CComQIPtr<IALToolbarList> altbl = fOwningALToolbar;
1389 if (altbl.p != NULL) {
1390 ThrowIfErrorHRESULT (altbl->get_hWnd (&parentHWND));
1391 }
1392 RECT r = AsRECT (fBounds);
1393 Create (parentHWND, &r);
1394 }
1395
1396 for (vector<CComPtr<IDispatch>>::iterator i = fToolbarItems.begin (); i != fToolbarItems.end (); ++i) {
1397#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1398 CComQIPtr<IALToolbarElement> tbi = (IDispatch*)*i;
1399#else
1400 CComQIPtr<IALToolbarElement> tbi = *i;
1401#endif
1402 tbi->NotifyOfOwningToolbar (owningActiveLedIt == NULL ? NULL : this, owningActiveLedIt);
1403 }
1404
1405 CallInvalidateLayout ();
1406 }
1407 }
1408 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1409 return S_OK;
1410}
1411
1412STDMETHODIMP ActiveLedIt_Toolbar::SetRectangle (int X, int Y, UINT width, UINT height)
1413{
1414 try {
1415 fBounds = Led_Rect (Y, X, height, width);
1416 MoveWindow (X, Y, width, height);
1417 DoLayout ();
1418 return S_OK;
1419 }
1420 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1421}
1422
1423/*
1424 ********************************************************************************
1425 **************************** ActiveLedIt_ToolbarList ***************************
1426 ********************************************************************************
1427 */
1428ActiveLedIt_ToolbarList::ActiveLedIt_ToolbarList ()
1429 : fToolbars ()
1430 , fOwningActiveLedIt (NULL)
1431 , fBounds ()
1432{
1433}
1434
1435ActiveLedIt_ToolbarList::~ActiveLedIt_ToolbarList ()
1436{
1437 if (m_hWnd != NULL) {
1438 DestroyWindow ();
1439 }
1440}
1441
1442HRESULT ActiveLedIt_ToolbarList::FinalConstruct ()
1443{
1444 return S_OK;
1445}
1446
1447void ActiveLedIt_ToolbarList::FinalRelease ()
1448{
1449}
1450
1451LRESULT ActiveLedIt_ToolbarList::OnPaint ([[maybe_unused]] UINT uMsg, [[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam,
1452 [[maybe_unused]] BOOL& bHandled)
1453{
1454 PAINTSTRUCT ps;
1455 HDC hdc = ::BeginPaint (m_hWnd, &ps);
1456 if (hdc != NULL) {
1457 try {
1458 Tablet tablet (hdc, Tablet::eDoesntOwnDC);
1459 Pen usePen (PS_SOLID, 1, Color::kBlack.GetOSRep ());
1460 GDI_Obj_Selector penSelector (&tablet, usePen);
1461 Led_Rect drawRect = Led_Rect (0, 0, fBounds.GetHeight (), fBounds.GetWidth ());
1462 if (m_hWnd != NULL) { // probbaly not really needed anymore - now that I subtract out the SM_CXYEDGE - but what the heck... Just in case...
1463 RECT cr;
1464 ::GetClientRect (m_hWnd, &cr);
1465 drawRect = AsLedRect (cr);
1466 }
1467 tablet.MoveTo (Led_Point (drawRect.GetBottom () - 1, drawRect.GetLeft ()));
1468 tablet.LineTo (Led_Point (drawRect.GetBottom () - 1, drawRect.GetRight ()));
1469 }
1470 catch (...) {
1471 ::EndPaint (m_hWnd, &ps);
1472 throw;
1473 }
1474 ::EndPaint (m_hWnd, &ps);
1475 }
1476 return 0;
1477}
1478
1479STDMETHODIMP ActiveLedIt_ToolbarList::get__NewEnum (IUnknown** ppUnk)
1480{
1481 using VarVarEnum = CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, STL_ATL_COPY_VARIANT_IDISPATCH, std::vector<CComPtr<IDispatch>>>;
1482 if (ppUnk == NULL) {
1483 return E_INVALIDARG;
1484 }
1485 try {
1486 return CreateSTLEnumerator<VarVarEnum> (ppUnk, this, fToolbars);
1487 }
1488 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1489}
1490
1491STDMETHODIMP ActiveLedIt_ToolbarList::get_Item (long Index, IDispatch** pVal)
1492{
1493 if (pVal == NULL) {
1494 return E_INVALIDARG;
1495 }
1496 if (Index < 0 or static_cast<size_t> (Index) >= fToolbars.size ()) {
1497 return E_INVALIDARG;
1498 }
1499 try {
1500 *pVal = fToolbars[Index];
1501 (*pVal)->AddRef ();
1502 }
1503 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1504 return S_OK;
1505}
1506
1507STDMETHODIMP ActiveLedIt_ToolbarList::get_Count (UINT* pVal)
1508{
1509 if (pVal == NULL) {
1510 return E_INVALIDARG;
1511 }
1512 try {
1513 *pVal = static_cast<UINT> (fToolbars.size ());
1514 }
1515 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1516 return S_OK;
1517}
1518
1519STDMETHODIMP ActiveLedIt_ToolbarList::Add (IDispatch* newElt, UINT atIndex)
1520{
1521 if (newElt == NULL) {
1522 return E_INVALIDARG;
1523 }
1524 try {
1525 CComQIPtr<IALToolbar> tb = newElt;
1526 ThrowIfErrorHRESULT (tb->NotifyOfOwningActiveLedIt (fOwningActiveLedIt, fOwningActiveLedIt == NULL ? NULL : this));
1527 size_t idx = min (static_cast<size_t> (atIndex), fToolbars.size ());
1528 fToolbars.insert (fToolbars.begin () + idx, newElt);
1529 CallInvalidateLayout ();
1530 }
1531 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1532 return S_OK;
1533}
1534
1535STDMETHODIMP ActiveLedIt_ToolbarList::Remove (VARIANT eltIntNameOrIndex)
1536{
1537 try {
1538 size_t idx = DoFindIndex (&fToolbars, eltIntNameOrIndex);
1539 if (idx != kBadIndex) {
1540 return E_INVALIDARG;
1541 }
1542#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1543 CComQIPtr<IALToolbar> tb = (IDispatch*)fToolbars[idx];
1544#else
1545 CComQIPtr<IALToolbar> tb = fToolbars[idx];
1546#endif
1547 ThrowIfErrorHRESULT (tb->NotifyOfOwningActiveLedIt (NULL, NULL));
1548 fToolbars.erase (fToolbars.begin () + idx, fToolbars.begin () + idx + 1);
1549 CallInvalidateLayout ();
1550 return S_OK;
1551 }
1552 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1553}
1554
1555STDMETHODIMP ActiveLedIt_ToolbarList::Clear ()
1556{
1557 try {
1558 for (vector<CComPtr<IDispatch>>::iterator i = fToolbars.begin (); i != fToolbars.end (); ++i) {
1559#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1560 CComQIPtr<IALToolbar> tb = (IDispatch*)*i;
1561#else
1562 CComQIPtr<IALToolbar> tb = *i;
1563#endif
1564 ThrowIfErrorHRESULT (tb->NotifyOfOwningActiveLedIt (NULL, NULL));
1565 }
1566 fToolbars.clear ();
1567 CallInvalidateLayout ();
1568 }
1569 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1570 return S_OK;
1571}
1572
1573void ActiveLedIt_ToolbarList::CallInvalidateLayout ()
1574{
1575 if (fOwningActiveLedIt != NULL) {
1576 CComPtr<IDispatch> oal = fOwningActiveLedIt;
1577 ThrowIfErrorHRESULT (oal.Invoke0 (DISPID_InvalidateLayout));
1578 }
1579}
1580
1581STDMETHODIMP ActiveLedIt_ToolbarList::NotifyOfOwningActiveLedIt (IDispatch* owningActiveLedIt, HWND owningHWND)
1582{
1583 try {
1584 if (fOwningActiveLedIt != owningActiveLedIt) {
1585 if (m_hWnd != NULL) {
1586 DestroyWindow ();
1587 }
1588
1589 fOwningActiveLedIt = owningActiveLedIt;
1590
1591 if (fOwningActiveLedIt != NULL) {
1592 RECT r = AsRECT (fBounds);
1593 Create (owningHWND, &r, NULL, 0, WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
1594 }
1595
1596 for (vector<CComPtr<IDispatch>>::iterator i = fToolbars.begin (); i != fToolbars.end (); ++i) {
1597#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1598 CComQIPtr<IALToolbar> tb = (IDispatch*)*i;
1599#else
1600 CComQIPtr<IALToolbar> tb = *i;
1601#endif
1602 ThrowIfErrorHRESULT (tb->NotifyOfOwningActiveLedIt (owningActiveLedIt, owningActiveLedIt == NULL ? NULL : this));
1603 }
1604 CallInvalidateLayout ();
1605 }
1606 }
1607 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1608 return S_OK;
1609}
1610
1611STDMETHODIMP ActiveLedIt_ToolbarList::get_hWnd (HWND* pVal)
1612{
1613 try {
1614 *pVal = m_hWnd;
1615 }
1616 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1617 return S_OK;
1618}
1619
1620STDMETHODIMP ActiveLedIt_ToolbarList::get_PreferredHeight (UINT* pVal)
1621{
1622 try {
1623 if (pVal == NULL) {
1624 return E_INVALIDARG;
1625 }
1626
1627 UINT totalHeight = 0;
1628 for (vector<CComPtr<IDispatch>>::iterator i = fToolbars.begin (); i != fToolbars.end (); ++i) {
1629#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1630 CComQIPtr<IALToolbar> tb = (IDispatch*)*i;
1631#else
1632 CComQIPtr<IALToolbar> tb = *i;
1633#endif
1634 UINT preferredHeight = 0;
1635 ThrowIfErrorHRESULT (tb->get_PreferredHeight (&preferredHeight));
1636 totalHeight += preferredHeight;
1637 }
1638
1639 // Use total preferred height of all toolbars, plus room for bottom line, plus room for edges of toolbar itself
1640 if (fToolbars.size () > 0) {
1641 *pVal = totalHeight + kRoomForBotLine + 2 * ::GetSystemMetrics (SM_CYEDGE);
1642 }
1643 else {
1644 // if no toolbars - no edge/bottom line either...
1645 *pVal = 0;
1646 }
1647
1648 return S_OK;
1649 }
1650 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1651}
1652
1653STDMETHODIMP ActiveLedIt_ToolbarList::get_PreferredWidth (UINT* pVal)
1654{
1655 try {
1656 if (pVal == NULL) {
1657 return E_INVALIDARG;
1658 }
1659 UINT maxWidth = 0;
1660 for (vector<CComPtr<IDispatch>>::iterator i = fToolbars.begin (); i != fToolbars.end (); ++i) {
1661#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1662 CComQIPtr<IALToolbar> tb = (IDispatch*)*i;
1663#else
1664 CComQIPtr<IALToolbar> tb = *i;
1665#endif
1666 UINT preferredWidth = 0;
1667 ThrowIfErrorHRESULT (tb->get_PreferredWidth (&preferredWidth));
1668 maxWidth = max (maxWidth, preferredWidth);
1669 }
1670
1671 // Use total preferred width of all buttons, plus room for bottom line, plus room for edges of toolbar itself
1672 *pVal = maxWidth + 2 * ::GetSystemMetrics (SM_CYEDGE);
1673
1674 return S_OK;
1675 }
1676 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1677}
1678
1679STDMETHODIMP ActiveLedIt_ToolbarList::SetRectangle (int X, int Y, UINT width, UINT height)
1680{
1681 try {
1682 fBounds = Led_Rect (Y, X, height, width);
1683 MoveWindow (X, Y, width, height);
1684 DoLayout ();
1685 return S_OK;
1686 }
1687 CATCH_AND_HANDLE_EXCEPTIONS_IN_HRESULT_FUNCTION ()
1688}
1689
1690void ActiveLedIt_ToolbarList::DoLayout ()
1691{
1692 Led_Rect clientBounds =
1693 Led_Rect (0, 0, max (static_cast<CoordinateType> (fBounds.GetHeight ()) - 2 * ::GetSystemMetrics (SM_CYEDGE), CoordinateType (0)),
1694 max (static_cast<CoordinateType> (fBounds.GetWidth ()) - 2 * ::GetSystemMetrics (SM_CXEDGE), CoordinateType (0)));
1695 if (m_hWnd != NULL) { // probbaly not really needed anymore - now that I subtract out the SM_CXYEDGE - but what the heck... Just in case...
1696 RECT cr;
1697 ::GetClientRect (m_hWnd, &cr);
1698 clientBounds.bottom = max (clientBounds.bottom, cr.bottom);
1699 }
1700
1701 Led_Rect itemBoundsCursor = clientBounds;
1702 for (vector<CComPtr<IDispatch>>::iterator i = fToolbars.begin (); i != fToolbars.end (); ++i) {
1703#if qCompilerAndStdLib_altComPtrCvt2ComQIPtrRequiresExtraCast_Buggy
1704 CComQIPtr<IALToolbar> tb = (IDispatch*)*i;
1705#else
1706 CComQIPtr<IALToolbar> tb = *i;
1707#endif
1708 if (tb.p != NULL) {
1709 UINT height = 0;
1710 ThrowIfErrorHRESULT (tb->get_PreferredHeight (&height));
1711 itemBoundsCursor.bottom = itemBoundsCursor.top + height;
1713 tb->SetRectangle (itemBoundsCursor.left, itemBoundsCursor.top, itemBoundsCursor.GetWidth (), itemBoundsCursor.GetHeight ()));
1714 itemBoundsCursor.top = itemBoundsCursor.bottom;
1715 }
1716 }
1717}
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:48
#define Verify(c)
Definition Assertions.h:419
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual SDKString AsSDKString() const
Definition String.inl:806
basic_string< SDKChar > SDKString
Definition SDKString.h:38