Tweak wxSpinCtrl appearance in dark mode
Previously wxSpinButton using a buddy control had borders which were much too bright in the dark mode. Now the entire border is perhaps a bit too dark, but it's still better than before.
This commit is contained in:
parent
68666d929d
commit
595e2f9326
1 changed files with 85 additions and 1 deletions
|
|
@ -24,12 +24,14 @@
|
|||
#include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
|
||||
#include "wx/app.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/dcmemory.h"
|
||||
#endif
|
||||
|
||||
#if wxUSE_SPINBTN
|
||||
|
||||
#include "wx/spinbutt.h"
|
||||
|
||||
#include "wx/msw/dc.h"
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/msw/private/darkmode.h"
|
||||
|
||||
|
|
@ -175,7 +177,89 @@ wxSize wxSpinButton::DoGetBestSize() const
|
|||
|
||||
void wxSpinButton::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
if ( !wxMSWDarkMode::PaintIfNecessary(GetHwnd(), m_oldWndProc) )
|
||||
if ( wxMSWDarkMode::IsActive() )
|
||||
{
|
||||
// Unfortunately PaintIfNecessary() can't be used here as we need to
|
||||
// handle the extra border below, so duplicate what it does here.
|
||||
const RECT rc = wxGetClientRect(GetHwnd());
|
||||
const wxSize size{rc.right - rc.left, rc.bottom - rc.top};
|
||||
|
||||
if ( size == wxSize() )
|
||||
return;
|
||||
|
||||
wxBitmap bmp(size);
|
||||
{
|
||||
wxMemoryDC mdc(bmp);
|
||||
|
||||
::CallWindowProc(m_oldWndProc,
|
||||
GetHwnd(), WM_PAINT, (WPARAM)GetHdcOf(mdc), 0);
|
||||
}
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
// When using a buddy control, the spin button tries to mimic being a
|
||||
// part of it by adding an extra border, not used for standalone
|
||||
// controls. This doesn't work very well even in light mode in modern
|
||||
// Windows (it was apparently done for the classic 3D appearance and
|
||||
// never updated since then), but looks completely horrible in dark
|
||||
// mode, so we must get rid of this border by overdrawing it.
|
||||
const bool drawBorder = ::SendMessage(GetHwnd(), UDM_GETBUDDY, 0, 0);
|
||||
wxImage::RGBValue border;
|
||||
if ( drawBorder )
|
||||
{
|
||||
const auto col = wxMSWDarkMode::GetBorderPen().GetColour();
|
||||
border.red = col.GetRed();
|
||||
border.green = col.GetGreen();
|
||||
border.blue = col.GetBlue();
|
||||
}
|
||||
|
||||
wxImage image = bmp.ConvertToImage();
|
||||
|
||||
const int width = image.GetWidth();
|
||||
const int height = image.GetHeight();
|
||||
unsigned char *data = image.GetData();
|
||||
unsigned char *alpha = image.GetAlpha();
|
||||
for ( int y = 0; y < height; ++y )
|
||||
{
|
||||
for ( int x = 0; x < width; ++x )
|
||||
{
|
||||
wxImage::RGBValue rgb(data[0], data[1], data[2]);
|
||||
|
||||
if ( drawBorder &&
|
||||
(y == 0 || y == height - 1 || x == width - 1) )
|
||||
{
|
||||
rgb = border;
|
||||
if ( alpha )
|
||||
*alpha = wxALPHA_OPAQUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This uses a slightly different formula than the one in
|
||||
// InvertBitmapPixel() because the one there results in the
|
||||
// lines being too bright.
|
||||
auto hsv = wxImage::RGBtoHSV(rgb);
|
||||
hsv.value = 1.0 - hsv.value;
|
||||
rgb = wxImage::HSVtoRGB(hsv);
|
||||
}
|
||||
|
||||
data[0] = rgb.red;
|
||||
data[1] = rgb.green;
|
||||
data[2] = rgb.blue;
|
||||
data += 3;
|
||||
|
||||
if ( alpha )
|
||||
alpha++;
|
||||
}
|
||||
}
|
||||
|
||||
bmp = wxBitmap(image);
|
||||
#endif // wxUSE_IMAGE
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
wxDCTemp dc(::BeginPaint(GetHwnd(), &ps), size);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
::EndPaint(GetHwnd(), &ps);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to always paint this control explicitly instead of letting
|
||||
// DefWndProc() do it, as this avoids whichever optimization the latter
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue