Inline wxStaticBitmap::MSWReplaceImageHandle() There doesn't seem to be any good reason to have this as a separate function any more as it is called only once and always takes m_currentHandle as parameter, which made things confusing as it used it both directly and via formal parameter name. No real changes.
Reduce GDI handles use in wxStaticBitmap Don't keep the GDI handle passed to the native control if it had made a copy of it: this is unnecessary and may result in resource exhaustion if many bitmaps are used. Closes #25698. Co-authored-by: Vadim Zeitlin <va...@wxwidgets.org>
Fix MSVS debug visualizer of wxStrings Fix the visualizer to display full Unicode string. Previously, only the first character was shown in recent versions of Visual Studio. This was due to the use of "sb" format specifier meaning an ANSI string. Use condition expressions to cover both wchar_t and UTF-8 builds. Correct the specifier for UTF-8 case to be "s8b" so that it interprets and displays UTF-8 correctly. Closes #25684.
Add tests preset to CMake Sets `wxBUILD_TESTS` to `ALL`. Closes #25690.
Fix wxOSX wxOwnerDrawnComboBox button rendering in dark mode Emulate native combobox button as close as possible. Closes #25681. Closes #25696.
Minor formatting/comment fixes in wxMSW wxIDataObject code This was supposed to be part of cf38ba8077 (Allow handling drag and drop of CFSTR_FILECONTENTS with wxMSW, 2025-08-12) but was forgotten there. See #25694.
Minor formatting improvement to wxMSW wxStaticBitmap code Try to be more consistent when comparing handles with the current one. No real changes.
Merge branch 'msw-statbmp-handle' Free unused bitmaps in wxMSW wxStaticBitmap to reduce GDI resource usage in this class. See #25698, #25699.
... | ... | @@ -18,6 +18,13 @@ |
18 | 18 | "wxBUILD_SAMPLES": "ALL"
|
19 | 19 | }
|
20 | 20 | },
|
21 | + {
|
|
22 | + "name": "with_tests",
|
|
23 | + "hidden": true,
|
|
24 | + "cacheVariables": {
|
|
25 | + "wxBUILD_TESTS": "ALL"
|
|
26 | + }
|
|
27 | + },
|
|
21 | 28 | {
|
22 | 29 | "name": "msw_base",
|
23 | 30 | "description": "Base configuration for MSW",
|
... | ... | @@ -38,6 +45,15 @@ |
38 | 45 | "displayName": "MSW Visual Studio 2022 (with Samples)",
|
39 | 46 | "generator": "Visual Studio 17 2022"
|
40 | 47 | },
|
48 | + {
|
|
49 | + "name": "msw_vc17_tests",
|
|
50 | + "inherits": [
|
|
51 | + "with_tests",
|
|
52 | + "msw_base"
|
|
53 | + ],
|
|
54 | + "displayName": "MSW Visual Studio 2022 (with Tests)",
|
|
55 | + "generator": "Visual Studio 17 2022"
|
|
56 | + },
|
|
41 | 57 | {
|
42 | 58 | "name": "msw_vc17",
|
43 | 59 | "inherits": "msw_base",
|
... | ... | @@ -63,6 +79,15 @@ |
63 | 79 | "displayName": "macOS Xcode (with Samples)",
|
64 | 80 | "generator": "Xcode"
|
65 | 81 | },
|
82 | + {
|
|
83 | + "name": "osx_xcode_tests",
|
|
84 | + "inherits": [
|
|
85 | + "with_tests",
|
|
86 | + "osx_base"
|
|
87 | + ],
|
|
88 | + "displayName": "macOS Xcode (with Tests)",
|
|
89 | + "generator": "Xcode"
|
|
90 | + },
|
|
66 | 91 | {
|
67 | 92 | "name": "osx_xcode",
|
68 | 93 | "inherits": "osx_base",
|
... | ... | @@ -78,6 +103,15 @@ |
78 | 103 | "displayName": "macOS Make (with Samples)",
|
79 | 104 | "generator": "Unix Makefiles"
|
80 | 105 | },
|
106 | + {
|
|
107 | + "name": "osx_make_tests",
|
|
108 | + "inherits": [
|
|
109 | + "with_tests",
|
|
110 | + "osx_base"
|
|
111 | + ],
|
|
112 | + "displayName": "macOS Make (with Tests)",
|
|
113 | + "generator": "Unix Makefiles"
|
|
114 | + },
|
|
81 | 115 | {
|
82 | 116 | "name": "osx_make",
|
83 | 117 | "inherits": "osx_base",
|
... | ... | @@ -132,10 +132,6 @@ private: |
132 | 132 | // Flag indicating whether we own m_currentHandle, i.e. should delete it.
|
133 | 133 | bool m_ownsCurrentHandle;
|
134 | 134 | |
135 | - // Replace the image at the native control level with the given HBITMAP or
|
|
136 | - // HICON (which can be 0) and destroy the previous image if necessary.
|
|
137 | - void MSWReplaceImageHandle(WXHANDLE handle);
|
|
138 | - |
|
139 | 135 | |
140 | 136 | wxDECLARE_DYNAMIC_CLASS(wxStaticBitmap);
|
141 | 137 | wxDECLARE_EVENT_TABLE();
|
... | ... | @@ -12,11 +12,12 @@ More information can be found at https://learn.microsoft.com/en-us/visualstudio/ |
12 | 12 | <!-- We want to avoid showing 'L' before the string, this is useless and
|
13 | 13 | makes the display less readable. But we still do want to put quotes
|
14 | 14 | around the string to show that it is, in fact, a string. So we use
|
15 | - "sb" qualifier to get rid of L"..." around the string and then add
|
|
16 | - the quotes back. This also has a (nice) side effect of not doubling
|
|
17 | - the backslashes inside the string. -->
|
|
15 | + "sub" or "s8b" qualifier to get rid of L"..." around the string and
|
|
16 | + then add the quotes back. This also has a (nice) side effect of not
|
|
17 | + doubling the backslashes inside the string. -->
|
|
18 | 18 | <Type Name="wxString">
|
19 | - <DisplayString>"{m_impl,sb}"</DisplayString>
|
|
19 | + <DisplayString Condition="sizeof(m_impl[0])==2">"{m_impl,sub}"</DisplayString> <!-- wxUSE_UNICODE_WCHAR -->
|
|
20 | + <DisplayString Condition="sizeof(m_impl[0])==1">"{m_impl,s8b}"</DisplayString> <!-- wxUSE_UNICODE_UTF8 -->
|
|
20 | 21 | <StringView>m_impl</StringView>
|
21 | 22 | </Type>
|
22 | 23 |
... | ... | @@ -609,14 +609,17 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) |
609 | 609 | return hr;
|
610 | 610 | }
|
611 | 611 | |
612 | - if ((pformatetcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM)) == TYMED_ISTREAM) {
|
|
612 | + if ( (pformatetcIn->tymed & (TYMED_HGLOBAL | TYMED_ISTREAM)) == TYMED_ISTREAM ) {
|
|
613 | 613 | IStream* stream = nullptr;
|
614 | - hr = CreateStreamOnHGlobal(pmedium->hGlobal, TRUE, &stream);
|
|
614 | + hr = ::CreateStreamOnHGlobal(pmedium->hGlobal,
|
|
615 | + TRUE, // delete on release
|
|
616 | + &stream);
|
|
615 | 617 | if ( FAILED(hr) ) {
|
616 | 618 | GlobalFree(pmedium->hGlobal);
|
617 | 619 | return hr;
|
618 | 620 | }
|
619 | - ZeroMemory(pmedium, sizeof(STGMEDIUM));
|
|
621 | + |
|
622 | + wxZeroMemory(*pmedium);
|
|
620 | 623 | pmedium->tymed = TYMED_ISTREAM;
|
621 | 624 | pmedium->pstm = stream;
|
622 | 625 | }
|
... | ... | @@ -816,8 +819,10 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc) |
816 | 819 | return E_INVALIDARG;
|
817 | 820 | }
|
818 | 821 | |
819 | - // the only ones allowed by current COM implementation
|
|
820 | - if (pformatetc->lindex != -1 && pformatetc->lindex != 0) {
|
|
822 | + // the only ones allowed by current COM implementation (0 is used for e.g.
|
|
823 | + // CFSTR_FILECONTENTS which is not handled by wx itself, but could be by
|
|
824 | + // the application)
|
|
825 | + if ( pformatetc->lindex != -1 && pformatetc->lindex != 0 ) {
|
|
821 | 826 | wxLogTrace(wxTRACE_OleCalls,
|
822 | 827 | wxT("wxIDataObject::QueryGetData: bad lindex %ld"),
|
823 | 828 | pformatetc->lindex);
|
... | ... | @@ -223,19 +223,6 @@ void wxStaticBitmap::DoPaintManually(wxPaintEvent& WXUNUSED(event)) |
223 | 223 | true /* use mask */);
|
224 | 224 | }
|
225 | 225 | |
226 | -void wxStaticBitmap::MSWReplaceImageHandle(WXHANDLE handle)
|
|
227 | -{
|
|
228 | - HGDIOBJ oldHandle = (HGDIOBJ)::SendMessage(GetHwnd(), STM_SETIMAGE,
|
|
229 | - m_icon.IsOk() ? IMAGE_ICON : IMAGE_BITMAP, (LPARAM)handle);
|
|
230 | - // detect if this is still the handle we passed before or
|
|
231 | - // if the static-control made a copy of the bitmap!
|
|
232 | - if (oldHandle != 0 && oldHandle != (HGDIOBJ) m_currentHandle)
|
|
233 | - {
|
|
234 | - // the static control made a copy and we are responsible for deleting it
|
|
235 | - ::DeleteObject((HGDIOBJ) oldHandle);
|
|
236 | - }
|
|
237 | -}
|
|
238 | - |
|
239 | 226 | void wxStaticBitmap::DoUpdateImage(const wxSize& sizeOld, bool wasIcon)
|
240 | 227 | {
|
241 | 228 | const wxSize sizeNew = GetImageSize();
|
... | ... | @@ -296,7 +283,31 @@ void wxStaticBitmap::DoUpdateImage(const wxSize& sizeOld, bool wasIcon) |
296 | 283 | .TurnOn(isIcon ? SS_ICON : SS_BITMAP);
|
297 | 284 | }
|
298 | 285 | |
299 | - MSWReplaceImageHandle(m_currentHandle);
|
|
286 | + |
|
287 | + // Update the handle used by the native control.
|
|
288 | + const WPARAM imageType = m_icon.IsOk() ? IMAGE_ICON : IMAGE_BITMAP;
|
|
289 | + |
|
290 | + const HGDIOBJ currentHandle = (HGDIOBJ)m_currentHandle;
|
|
291 | + const HGDIOBJ oldHandle = (HGDIOBJ)
|
|
292 | + ::SendMessage(GetHwnd(), STM_SETIMAGE, imageType, (LPARAM)currentHandle);
|
|
293 | + |
|
294 | + // detect if this is still the handle we passed before or
|
|
295 | + // if the static-control made a copy of the bitmap!
|
|
296 | + if ( oldHandle != 0 && oldHandle != currentHandle )
|
|
297 | + {
|
|
298 | + // the static control made a copy and we are responsible for deleting it
|
|
299 | + ::DeleteObject(oldHandle);
|
|
300 | + }
|
|
301 | + |
|
302 | + // Also check if we need to keep our current handle, it may be unnecessary
|
|
303 | + // if the native control doesn't actually use it.
|
|
304 | + const HGDIOBJ newHandle = (HGDIOBJ)
|
|
305 | + ::SendMessage(GetHwnd(), STM_GETIMAGE, imageType, 0);
|
|
306 | + if ( newHandle != currentHandle )
|
|
307 | + {
|
|
308 | + // The control made a copy of the image and we don't need to keep it.
|
|
309 | + Free();
|
|
310 | + }
|
|
300 | 311 | |
301 | 312 | if ( sizeNew != sizeOld )
|
302 | 313 | {
|
... | ... | @@ -184,6 +184,19 @@ private: |
184 | 184 | return m_nsPushButtonCell;
|
185 | 185 | }
|
186 | 186 | |
187 | + NSButtonCell* GetPopDownArrowCell()
|
|
188 | + {
|
|
189 | + if ( !m_nsPopDownArrowCell )
|
|
190 | + {
|
|
191 | + m_nsPopDownArrowCell = [[NSButtonCell alloc] initImageCell:[NSImage imageNamed: @"NSTokenPopDownArrow"]];
|
|
192 | + m_nsPopDownArrowCell.buttonType = NSButtonTypeMomentaryPushIn;
|
|
193 | + m_nsPopDownArrowCell.highlightsBy = NSPushInCellMask;
|
|
194 | + m_nsPopDownArrowCell.bezelStyle = NSBezelStyleRoundedDisclosure;
|
|
195 | + }
|
|
196 | + |
|
197 | + return m_nsPopDownArrowCell;
|
|
198 | + }
|
|
199 | + |
|
187 | 200 | NSButtonCell* GetCheckBoxCell()
|
188 | 201 | {
|
189 | 202 | if ( !m_nsCheckBoxCell )
|
... | ... | @@ -260,6 +273,7 @@ private: |
260 | 273 | NSButtonCell* m_nsCheckBoxCell = nil;
|
261 | 274 | NSButtonCell* m_nsRadioButtonCell = nil;
|
262 | 275 | NSButtonCell* m_nsDisclosureButtonCell = nil;
|
276 | + NSButtonCell* m_nsPopDownArrowCell = nil;
|
|
263 | 277 | NSPopUpButtonCell* m_nsPopupbuttonCell = nil;
|
264 | 278 | NSComboBoxCell* m_nsComboBoxCell = nil;
|
265 | 279 | NSTableHeaderCell* m_nsTableHeaderCell = nil;
|
... | ... | @@ -285,6 +299,7 @@ wxRendererMac::~wxRendererMac() |
285 | 299 | [m_nsCheckBoxCell release];
|
286 | 300 | [m_nsRadioButtonCell release];
|
287 | 301 | [m_nsDisclosureButtonCell release];
|
302 | + [m_nsPopDownArrowCell release];
|
|
288 | 303 | [m_nsPopupbuttonCell release];
|
289 | 304 | [m_nsComboBoxCell release];
|
290 | 305 | [m_nsTableHeaderCell release];
|
... | ... | @@ -830,6 +845,10 @@ wxRendererMac::DrawComboBoxDropButton(wxWindow *win, |
830 | 845 | const wxRect& rect,
|
831 | 846 | int flags)
|
832 | 847 | {
|
848 | +#if wxOSX_USE_NSCELL_RENDERER
|
|
849 | + NSControlStateValue stateValue = (flags & wxCONTROL_PRESSED) ? NSControlStateValueOn : NSControlStateValueOff;
|
|
850 | + DrawMacCell(win, dc, GetPopDownArrowCell(), rect, flags, stateValue);
|
|
851 | +#else
|
|
833 | 852 | int kind;
|
834 | 853 | if (win->GetWindowVariant() == wxWINDOW_VARIANT_SMALL || (win->GetParent() && win->GetParent()->GetWindowVariant() == wxWINDOW_VARIANT_SMALL))
|
835 | 854 | kind = kThemeArrowButtonSmall;
|
... | ... | @@ -840,6 +859,7 @@ wxRendererMac::DrawComboBoxDropButton(wxWindow *win, |
840 | 859 | |
841 | 860 | DrawMacThemeButton(win, dc, rect, flags,
|
842 | 861 | kind, kThemeAdornmentArrowDownArrow);
|
862 | +#endif
|
|
843 | 863 | }
|
844 | 864 | |
845 | 865 | void
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help