[Git][wxwidgets/wxwidgets][master] 8 commits: Inline wxStaticBitmap::MSWReplaceImageHandle()

0 views
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Aug 17, 2025, 5:55:52 PMAug 17
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • 6c53312e
    by Vadim Zeitlin at 2025-08-15T14:14:38+02:00
    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.
    
  • 2a2eca16
    by Alex Shvartzkop at 2025-08-15T14:25:01+02:00
    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>
    
  • 77dd42f3
    by Václav Slavík at 2025-08-17T23:43:42+02:00
    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.
    
  • 54f61689
    by Blake-Madden at 2025-08-17T23:45:16+02:00
    Add tests preset to CMake
    
    Sets `wxBUILD_TESTS` to `ALL`.
    
    Closes #25690.
    
  • 5c0e7e33
    by Stefan Csomor at 2025-08-17T23:46:14+02:00
    Fix wxOSX wxOwnerDrawnComboBox button rendering in dark mode
    
    Emulate native combobox button as close as possible.
    
    Closes #25681.
    
    Closes #25696.
    
  • abee10f8
    by Vadim Zeitlin at 2025-08-17T23:47:58+02:00
    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.
    
  • 119ed10a
    by Vadim Zeitlin at 2025-08-17T23:50:42+02:00
    Minor formatting improvement to wxMSW wxStaticBitmap code
    
    Try to be more consistent when comparing handles with the current one.
    
    No real changes.
    
  • a3983214
    by Vadim Zeitlin at 2025-08-17T23:51:32+02:00
    Merge branch 'msw-statbmp-handle'
    
    Free unused bitmaps in wxMSW wxStaticBitmap to reduce GDI resource usage
    in this class.
    
    See #25698, #25699.
    

6 changed files:

Changes:

  • CMakePresets.json
    ... ... @@ -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",
    

  • include/wx/msw/statbmp.h
    ... ... @@ -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();
    

  • misc/msvc/wxWidgets.natvis
    ... ... @@ -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
     
    

  • src/msw/ole/dataobj.cpp
    ... ... @@ -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);
    

  • src/msw/statbmp.cpp
    ... ... @@ -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
         {
    

  • src/osx/cocoa/renderer.mm
    ... ... @@ -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
    

Reply all
Reply to author
Forward
0 new messages