wxwidgets/src/msw/overlay.cpp
AliKet c0140d12c9 Remove unnecessary override from wxOverlayImpl under wxMSW
The base class version already returns true by default.
2024-02-09 22:47:42 +01:00

164 lines
4.4 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/msw/overlay.cpp
// Author: Ali Kettab
// Copyright: (c) 2022 Ali Kettab
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/private/overlay.h"
#include "wx/dcclient.h"
#include "wx/dcmemory.h"
#include "wx/msw/dc.h"
#include "wx/msw/private.h"
namespace // anonymous
{
wxWindow* wxCreateOverlayWindow(const wxRect& rect)
{
auto overlayWin = new wxWindow();
overlayWin->MSWCreate
(
overlayWin->GetMSWClassName(0),
nullptr, // No title
rect.GetPosition(),
rect.GetSize(),
WS_POPUP,
WS_EX_LAYERED |
WS_EX_TRANSPARENT |
WS_EX_NOACTIVATE
);
overlayWin->SetBackgroundStyle(wxBG_STYLE_PAINT);
if ( !::SetLayeredWindowAttributes(GetHwndOf(overlayWin), 0, 128,
LWA_COLORKEY | LWA_ALPHA) )
{
wxLogLastError(wxS("SetLayeredWindowAttributes()"));
}
// We intentionally don't use WS_VISIBLE when creating this window to avoid
// stealing activation from the parent, so show it using SWP_NOACTIVATE now.
::SetWindowPos(GetHwndOf(overlayWin), nullptr, 0, 0, 0, 0,
SWP_NOSIZE |
SWP_NOMOVE |
SWP_NOREDRAW |
SWP_NOOWNERZORDER |
SWP_NOACTIVATE |
SWP_SHOWWINDOW);
return overlayWin;
}
} // anonymous namespace
class wxOverlayImpl : public wxOverlay::Impl
{
public:
wxOverlayImpl() = default;
~wxOverlayImpl() = default;
virtual void Reset() override;
virtual bool IsOk() override;
virtual void Init(wxDC* dc, int x , int y , int width , int height) override;
virtual void BeginDrawing(wxDC* dc) override;
virtual void EndDrawing(wxDC* dc) override;
virtual void Clear(wxDC* dc) override;
public:
// window the overlay is associated with
wxWindow* m_window = nullptr;
// the overlay window itself. doesn't have to be child of any window
// and is totally managed by this class
wxWindow* m_overlayWindow = nullptr;
wxRect m_rect;
// Drawing on the overlay window is achieved by hijacking the existing wxDC.
// i.e. any drawing done through wxDC should go to the offscreen bitmap m_bitmap
// which will eventually be drawn on the overlay window.
wxBitmap m_bitmap;
wxMemoryDC m_memDC; // for memory dc construction only.
WXHDC m_hdc = 0; // the original HDC
wxDECLARE_NO_COPY_CLASS(wxOverlayImpl);
};
bool wxOverlayImpl::IsOk()
{
return m_overlayWindow != nullptr;
}
void wxOverlayImpl::Init(wxDC* dc, int , int , int , int )
{
if ( IsOk() )
return;
m_window = dc->GetWindow();
m_rect.SetSize(m_window->GetClientSize());
m_rect.SetPosition(m_window->GetScreenPosition());
m_bitmap.CreateWithLogicalSize(m_rect.GetSize(), m_window->GetDPIScaleFactor());
m_overlayWindow = wxCreateOverlayWindow(m_rect);
}
void wxOverlayImpl::BeginDrawing(wxDC* dc)
{
wxCHECK_RET( IsOk(), wxS("overlay not initialized") );
m_memDC.SelectObject(m_bitmap);
auto impl = dc->GetImpl();
auto msw_impl = static_cast<wxMSWDCImpl*>(impl);
m_hdc = GetHdcOf(*msw_impl); // save the original hdc
msw_impl->SetHDC(GetHdcOf(m_memDC));
msw_impl->UpdateClipBox();
}
void wxOverlayImpl::EndDrawing(wxDC* dc)
{
wxCHECK_RET( IsOk(), wxS("overlay not initialized") );
m_memDC.SelectObject(wxNullBitmap);
auto impl = dc->GetImpl();
auto msw_impl = static_cast<wxMSWDCImpl*>(impl);
msw_impl->SetHDC(m_hdc); // restore the original hdc
msw_impl->UpdateClipBox();
wxWindowDC winDC(m_overlayWindow);
winDC.DrawBitmap(m_bitmap, wxPoint(0, 0));
}
void wxOverlayImpl::Clear(wxDC* WXUNUSED(dc))
{
wxCHECK_RET( IsOk(), wxS("overlay not initialized") );
// Note that the colour used here is the same one that we specify as
// LWA_COLORKEY when creating the layered window, so it is actually
// transparent.
m_memDC.SetBackground(*wxBLACK);
m_memDC.Clear();
}
void wxOverlayImpl::Reset()
{
if ( IsOk() )
{
m_overlayWindow->Destroy();
m_overlayWindow = nullptr;
}
}
wxOverlay::Impl* wxOverlay::Create()
{
return new wxOverlayImpl;
}