X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/164db177a227c71a91fc998ab38f6eefd4f2606a..404b319a85dadd7decf7a5a5331020520031a41c:/src/msw/nonownedwnd.cpp diff --git a/src/msw/nonownedwnd.cpp b/src/msw/nonownedwnd.cpp index 48dd03e24d..09f5ec0f8e 100644 --- a/src/msw/nonownedwnd.cpp +++ b/src/msw/nonownedwnd.cpp @@ -27,6 +27,7 @@ #ifndef __WXWINCE__ #ifndef WX_PRECOMP + #include "wx/dcclient.h" #include "wx/frame.h" // Only for wxFRAME_SHAPED. #include "wx/region.h" #include "wx/msw/private.h" @@ -34,27 +35,30 @@ #include "wx/nonownedwnd.h" +#if wxUSE_GRAPHICS_CONTEXT + #include "wx/msw/wrapgdip.h" + #include "wx/graphics.h" +#endif // wxUSE_GRAPHICS_CONTEXT + +#include "wx/scopedptr.h" + // ============================================================================ // wxNonOwnedWindow implementation // ============================================================================ -bool wxNonOwnedWindow::SetShape(const wxRegion& region) +bool wxNonOwnedWindow::DoClearShape() { - wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false, - wxT("Shaped windows must be created with the wxFRAME_SHAPED style.")); - - // The empty region signifies that the shape should be removed from the - // window. - if ( region.IsEmpty() ) + if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0) { - if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0) - { - wxLogLastError(wxT("SetWindowRgn")); - return false; - } - return true; + wxLogLastError(wxT("SetWindowRgn")); + return false; } + return true; +} + +bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region) +{ // Windows takes ownership of the region, so // we'll have to make a copy of the region to give to it. DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL); @@ -64,14 +68,9 @@ bool wxNonOwnedWindow::SetShape(const wxRegion& region) delete[] (char*) rgnData; // SetWindowRgn expects the region to be in coordinates - // relative to the window, not the client area. Figure - // out the offset, if any. - RECT rect; - DWORD dwStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE); - DWORD dwExStyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE); - ::GetClientRect(GetHwnd(), &rect); - ::AdjustWindowRectEx(&rect, dwStyle, ::GetMenu(GetHwnd()) != NULL, dwExStyle); - ::OffsetRgn(hrgn, -rect.left, -rect.top); + // relative to the window, not the client area. + const wxPoint clientOrigin = GetClientAreaOrigin(); + ::OffsetRgn(hrgn, -clientOrigin.x, -clientOrigin.y); // Now call the shape API with the new region. if (::SetWindowRgn(GetHwnd(), hrgn, TRUE) == 0) @@ -82,4 +81,104 @@ bool wxNonOwnedWindow::SetShape(const wxRegion& region) return true; } +#if wxUSE_GRAPHICS_CONTEXT + +#include "wx/msw/wrapgdip.h" + +// This class contains data used only when SetPath(wxGraphicsPath) is called. +// +// Notice that it derives from wxEvtHandler solely to allow Connect()-ing its +// OnPaint() method to the window, we could get rid of this inheritance once +// Bind() can be used in wx sources. +class wxNonOwnedWindowShapeImpl : public wxEvtHandler +{ +public: + wxNonOwnedWindowShapeImpl(wxNonOwnedWindow* win, const wxGraphicsPath& path) : + m_win(win), + m_path(path) + { + // Create the region corresponding to this path and set it as windows + // shape. + wxScopedPtr context(wxGraphicsContext::Create(win)); + Region gr(static_cast(m_path.GetNativePath())); + win->SetShape( + wxRegion( + gr.GetHRGN(static_cast(context->GetNativeContext())) + ) + ); + + + // Connect to the paint event to draw the border. + // + // TODO: Do this only optionally? + m_win->Connect + ( + wxEVT_PAINT, + wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint), + NULL, + this + ); + } + + virtual ~wxNonOwnedWindowShapeImpl() + { + m_win->Disconnect + ( + wxEVT_PAINT, + wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint), + NULL, + this + ); + } + +private: + void OnPaint(wxPaintEvent& event) + { + event.Skip(); + + wxPaintDC dc(m_win); + wxScopedPtr context(wxGraphicsContext::Create(dc)); + context->SetPen(wxPen(*wxLIGHT_GREY, 2)); + context->StrokePath(m_path); + } + + wxNonOwnedWindow* const m_win; + wxGraphicsPath m_path; + + wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl); +}; + +wxNonOwnedWindow::wxNonOwnedWindow() +{ + m_shapeImpl = NULL; +} + +wxNonOwnedWindow::~wxNonOwnedWindow() +{ + delete m_shapeImpl; +} + +bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path) +{ + delete m_shapeImpl; + m_shapeImpl = new wxNonOwnedWindowShapeImpl(this, path); + + return true; +} + +#else // !wxUSE_GRAPHICS_CONTEXT + +// Trivial ctor and dtor as we don't have anything to do when wxGraphicsContext +// is not used but still define them here to avoid adding even more #if checks +// to the header, it it doesn't do any harm even though it's not needed. +wxNonOwnedWindow::wxNonOwnedWindow() +{ +} + +wxNonOwnedWindow::~wxNonOwnedWindow() +{ +} + +#endif // wxUSE_GRAPHICS_CONTEXT/!wxUSE_GRAPHICS_CONTEXT + #endif // !__WXWINCE__