]> git.saurik.com Git - wxWidgets.git/commitdiff
added wxBG_STYLE_TRANSPARENT and implemented it for wxMac; documented various transpa...
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 22 Oct 2007 21:15:04 +0000 (21:15 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 22 Oct 2007 21:15:04 +0000 (21:15 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49341 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
docs/latex/wx/window.tex
include/wx/defs.h
include/wx/mac/carbon/toplevel.h
samples/shaped/shaped.cpp
src/mac/carbon/toplevel.cpp
src/mac/carbon/window.cpp

index 18ae1e73d0542eb75c79cc44d862ac6af484eadd..7eabf9bc39fdef057c4e909080c2350acba73960 100644 (file)
@@ -181,6 +181,7 @@ All (GUI):
 - Added support for drop down toolbar buttons (Tim Kosse).
 - Added support for labels for toolbar controls (Vince Harron).
 - Added wxMessageDialog::SetMessage() and SetExtendedMessage().
+- Added wxBG_STYLE_TRANSPARENT background style (Julian Scheid)
 - Added XRCSIZERITEM() macro for obtaining sizers from XRC (Brian Vanderburg II)
 - New and improved wxFileCtrl (Diaa Sami and Marcin Wojdyr)
 - Added wxEventBlocker class (Francesco Montorsi).
index d19f545197cbd40dd1ac9aef24a0131fcdf7cd2f..ef908b33d00f69433fd6c7899fbe61e6a2a645a1 100644 (file)
@@ -226,6 +226,16 @@ called by the user code.
 Sets the cached best size value.
 
 
+\membersection{wxWindow::CanSetTransparent}\label{wxwindowcansettransparent}
+
+\func{bool}{CanSetTransparent}{\void}
+
+Returns \true if the system supports transparent windows and calling 
+\helpref{SetTransparent}{wxwindowsettransparent} may succeed. If this function
+returns \false, transparent windows are definitely not supported by the current
+system.
+
+
 \membersection{wxWindow::CaptureMouse}\label{wxwindowcapturemouse}
 
 \func{virtual void}{CaptureMouse}{\void}
@@ -775,19 +785,32 @@ Returns the background colour of the window.
 
 \constfunc{virtual wxBackgroundStyle}{GetBackgroundStyle}{\void}
 
-Returns the background style of the window. The background style indicates
-whether background colour should be determined by the system (wxBG\_STYLE\_SYSTEM),
-be set to a specific colour (wxBG\_STYLE\_COLOUR), or should be left to the
-application to implement (wxBG\_STYLE\_CUSTOM).
-
-On GTK+, use of wxBG\_STYLE\_CUSTOM allows the flicker-free drawing of a custom
-background, such as a tiled bitmap. Currently the style has no effect on other platforms.
+Returns the background style of the window. The background style can be one of:
+\begin{twocollist}\itemsep=0pt
+\twocolitem{wxBG\_STYLE\_SYSTEM}{Use the default background, as determined by
+the system or the current theme.}
+\twocolitem{wxBG\_STYLE\_COLOUR}{Use a solid colour for the background, this
+style is set automatically if you call 
+\helpref{SetBackgroundColour}{wxwindowsetbackgroundcolour} so you only need to
+set it explicitly if you had changed the background style to something else
+before.}
+\twocolitem{wxBG\_STYLE\_CUSTOM}{Don't draw the background at all, it's
+supposed that it is drawn by the user-defined erase background event handler.
+This style should be used to avoid flicker when the background is entirely
+custom-drawn.}
+\twocolitem{wxBG\_STYLE\_TRANSPARET}{The background is (partially) transparent,
+this style is automatically set if you call 
+\helpref{SetTransparent}{wxwindowsettransparent} which is used to set the
+transparency level.}
+\end{twocollist}
 
 \wxheading{See also}
 
 \helpref{wxWindow::SetBackgroundColour}{wxwindowsetbackgroundcolour},\rtfsp
 \helpref{wxWindow::GetForegroundColour}{wxwindowgetforegroundcolour},\rtfsp
-\helpref{wxWindow::SetBackgroundStyle}{wxwindowsetbackgroundstyle}
+\helpref{wxWindow::SetBackgroundStyle}{wxwindowsetbackgroundstyle},\rtfsp
+\helpref{wxWindow::SetTransparent}{wxwindowsettransparent}
+
 
 \membersection{wxWindow::GetEffectiveMinSize}\label{wxwindowgeteffectiveminsize}
 
@@ -2793,19 +2816,15 @@ applications on the system.
 
 \func{virtual void}{SetBackgroundStyle}{\param{wxBackgroundStyle}{ style}}
 
-Sets the background style of the window. The background style indicates
-whether background colour should be determined by the system (wxBG\_STYLE\_SYSTEM),
-be set to a specific colour (wxBG\_STYLE\_COLOUR), or should be left to the
-application to implement (wxBG\_STYLE\_CUSTOM).
-
-On GTK+, use of wxBG\_STYLE\_CUSTOM allows the flicker-free drawing of a custom
-background, such as a tiled bitmap. Currently the style has no effect on other platforms.
+Sets the background style of the window. see 
+\helpref{GetBackgroundStyle()}{wxwindowgetbackgroundstyle} for the description
+of the possible style values.
 
 \wxheading{See also}
 
 \helpref{wxWindow::SetBackgroundColour}{wxwindowsetbackgroundcolour},\rtfsp
 \helpref{wxWindow::GetForegroundColour}{wxwindowgetforegroundcolour},\rtfsp
-\helpref{wxWindow::GetBackgroundStyle}{wxwindowgetbackgroundstyle}
+\helpref{wxWindow::SetTransparent}{wxwindowsettransparent}
 
 
 
@@ -3545,6 +3564,20 @@ See also: \helpref{GetToolTip}{wxwindowgettooltip},
  \helpref{wxToolTip}{wxtooltip}
 
 
+\membersection{wxWindow::SetTransparent}\label{wxwindowsettransparent}
+
+\func{bool}{SetTransparent}{\param{wxByte }{alpha}}
+
+Set the transparency of the window. If the system supports transparent windows,
+returns \true, otherwise returns \false and the window remains fully opaque.
+See also \helpref{CanSetTransparent}{wxwindowcansettransparent}.
+
+The parameter \arg{alpha} is in the range $0..255$ where $0$ corresponds to a
+fully transparent window and $255$ to the fully opaque one. The constants
+\texttt{wxIMAGE\_ALPHA\_TRANSPARENT} and \texttt{wxIMAGE\_ALPHA\_OPAQUE} can be
+used.
+
+
 \membersection{wxWindow::SetValidator}\label{wxwindowsetvalidator}
 
 \func{virtual void}{SetValidator}{\param{const wxValidator\&}{ validator}}
index 8e387b61edd250a5762fc1365e8dc7cbe360db23..66263a007ce364aa9fb66c729e62a5799484d3de 100644 (file)
@@ -1751,7 +1751,8 @@ enum wxBackgroundStyle
 {
   wxBG_STYLE_SYSTEM,
   wxBG_STYLE_COLOUR,
-  wxBG_STYLE_CUSTOM
+  wxBG_STYLE_CUSTOM,
+  wxBG_STYLE_TRANSPARENT
 };
 
 /*
index b123748caa2b0367f8c057f065df5679583b7ddd..71a5f1937cd1598a6b156ea8a993ad2df0d81d23 100644 (file)
@@ -70,6 +70,7 @@ public:
     virtual bool SetTransparent(wxByte alpha);
     virtual bool CanSetTransparent();
 
+    virtual bool SetBackgroundStyle(wxBackgroundStyle style);
 
     // implementation from now on
     // --------------------------
index cc8ed4a232cbf6f941e5ef0174a57d2d5f2810ce..1a9efa81324d33c58f99ea31cb156191fac7b502 100644 (file)
@@ -58,12 +58,13 @@ public:
 };
 
 
-// Define a new frame type: this is going to be our main frame
+// Define a new frame type: this is going to the frame showing the
+// effect of wxFRAME_SHAPED
 class ShapedFrame : public wxFrame
 {
 public:
     // ctor(s)
-    ShapedFrame();
+    ShapedFrame(wxFrame *parent);
     void SetWindowShape();
 
     // event handlers (these functions should _not_ be virtual)
@@ -84,6 +85,35 @@ private:
     DECLARE_EVENT_TABLE()
 };
 
+// Define a new frame type: this is going to the frame showing the
+// effect of wxWindow::SetTransparent and of
+// wxWindow::SetBackgroundStyle(wxBG_STYLE_TRANSPARENT)
+class SeeThroughFrame : public wxFrame
+{
+public:
+    // ctor(s)
+    SeeThroughFrame();
+
+    // event handlers (these functions should _not_ be virtual)
+    void OnDoubleClick(wxMouseEvent& evt);
+    void OnPaint(wxPaintEvent& evt);
+    void OnSize(wxSizeEvent& evt);
+
+private:
+    enum State
+    {
+        STATE_SEETHROUGH,
+        STATE_TRANSPARENT,
+        STATE_OPAQUE,
+        STATE_MAX
+    };
+
+    State m_currentState;
+
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
 
 // ----------------------------------------------------------------------------
 // event tables and other macros for wxWidgets
@@ -130,10 +160,14 @@ bool MyApp::OnInit()
 
     wxInitAllImageHandlers();
 
-    // Create the main application window
-    ShapedFrame *frame = new ShapedFrame();
-    frame->Show(true);
-    SetTopWindow(frame);
+    // Create the transparent window
+    SeeThroughFrame *seeThroughFrame = new SeeThroughFrame();
+    seeThroughFrame->Show(true);
+    SetTopWindow(seeThroughFrame);
+
+    // Create the shaped window
+    ShapedFrame *shapedFrame = new ShapedFrame(seeThroughFrame);
+    shapedFrame->Show(true);
 
     // success: wxApp::OnRun() will be called which will enter the main message
     // loop and the application will run. If we returned false here, the
@@ -142,12 +176,12 @@ bool MyApp::OnInit()
 }
 
 // ----------------------------------------------------------------------------
-// main frame
+// shaped frame
 // ----------------------------------------------------------------------------
 
 // frame constructor
-ShapedFrame::ShapedFrame()
-       : wxFrame((wxFrame *)NULL, wxID_ANY, wxEmptyString,
+ShapedFrame::ShapedFrame(wxFrame *parent)
+       : wxFrame(parent, wxID_ANY, wxEmptyString,
                   wxDefaultPosition, wxSize(100, 100), //wxDefaultSize,
                   0
                   | wxFRAME_SHAPED
@@ -235,3 +269,93 @@ void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
     SetWindowShape();
 }
 
+// ----------------------------------------------------------------------------
+// see-through frame
+// ----------------------------------------------------------------------------
+
+// frame constructor
+SeeThroughFrame::SeeThroughFrame()
+       : wxFrame(NULL, wxID_ANY, "Transparency test: double click here",
+                  wxPoint(100, 30), wxSize(300, 300),
+                  wxDEFAULT_FRAME_STYLE | wxSTAY_ON_TOP),
+         m_currentState(STATE_SEETHROUGH)
+{
+    SetBackgroundColour(wxColour(255, 255, 255, 255));
+    SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+}
+
+// Redraws the whole window on resize
+void SeeThroughFrame::OnSize(wxSizeEvent& WXUNUSED(evt))
+{
+    Refresh();
+}
+
+// Paints a grid of varying hue and alpha
+void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
+{
+    wxPaintDC dc(this);
+    dc.SetPen(wxNullPen);
+
+    int xcount = 8;
+    int ycount = 8;
+
+    float xstep = 1. / xcount;
+    float ystep = 1. / ycount;
+
+    int width = GetClientSize().GetWidth();
+    int height = GetClientSize().GetHeight();
+
+    for ( float x = 0.; x < 1.; x += xstep )
+    {
+        for ( float y = 0.; y < 1.; y += ystep )
+        {
+            wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
+            dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
+                                (int)(255*(1. - y)))));
+            int x1 = (int)(x * width);
+            int y1 = (int)(y * height);
+            int x2 = (int)((x + xstep) * width);
+            int y2 = (int)((y + ystep) * height);
+            dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
+        }
+    }
+}
+
+// Switches between colour and transparent background on doubleclick
+void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
+{
+    m_currentState = (State)((m_currentState + 1) % STATE_MAX);
+
+    switch ( m_currentState )
+    {
+        case STATE_OPAQUE:
+            SetBackgroundStyle(wxBG_STYLE_COLOUR);
+            SetTransparent(255);
+            SetTitle("Opaque");
+            break;
+
+        case STATE_SEETHROUGH:
+            SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+            SetTransparent(255);
+            SetTitle("See through");
+            break;
+
+        case STATE_TRANSPARENT:
+            SetBackgroundStyle(wxBG_STYLE_COLOUR);
+            SetTransparent(128);
+            SetTitle("Semi-transparent");
+            break;
+
+        case STATE_MAX:
+            wxFAIL_MSG( "unreachable" );
+    }
+
+    Refresh();
+}
+
+BEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
+    EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
+    EVT_PAINT(SeeThroughFrame::OnPaint)
+    EVT_SIZE(SeeThroughFrame::OnSize)
+END_EVENT_TABLE()
+
index d45476496af079be8230f4f7546710b1f752acfe..dec65979568fc26c3b53f84b6c4646c520f6caf7 100644 (file)
@@ -102,6 +102,7 @@ static const EventTypeSpec eventList[] =
     { kEventClassWindow , kEventWindowBoundsChanging } ,
     { kEventClassWindow , kEventWindowBoundsChanged } ,
     { kEventClassWindow , kEventWindowClose } ,
+    { kEventClassWindow , kEventWindowGetRegion } ,
 
     // we have to catch these events on the toplevel window level,
     // as controls don't get the raw mouse events anymore
@@ -804,6 +805,36 @@ static pascal OSStatus wxMacTopLevelWindowEventHandler( EventHandlerCallRef hand
         }
             break ;
 
+        case kEventWindowGetRegion :
+            {
+                if ( toplevelWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
+                {
+                    WindowRegionCode windowRegionCode ;
+
+                    // Fetch the region code that is being queried
+                    GetEventParameter( event,
+                                       kEventParamWindowRegionCode,
+                                       typeWindowRegionCode, NULL,
+                                       sizeof windowRegionCode, NULL,
+                                       &windowRegionCode ) ;
+
+                    // If it is the opaque region code then set the
+                    // region to empty and return noErr to stop event
+                    // propagation
+                    if ( windowRegionCode == kWindowOpaqueRgn ) {
+                        RgnHandle region;
+                        GetEventParameter( event,
+                                           kEventParamRgnHandle,
+                                           typeQDRgnHandle, NULL,
+                                           sizeof region, NULL,
+                                           &region) ;
+                        SetEmptyRgn(region) ;
+                        result = noErr ;
+                    }
+                }
+            }
+            break ;
+
         default :
             break ;
     }
@@ -1482,6 +1513,24 @@ void wxTopLevelWindowMac::SetExtraStyle(long exStyle)
 #endif
 }
 
+bool wxTopLevelWindowMac::SetBackgroundStyle(wxBackgroundStyle style)
+{
+    if ( !wxTopLevelWindowBase::SetBackgroundStyle(style) )
+        return false ;
+
+    WindowRef windowRef = HIViewGetWindow( (HIViewRef)GetHandle() );
+
+    if ( GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
+    {
+        OSStatus err = HIWindowChangeFeatures( windowRef, 0, kWindowIsOpaque );
+        verify_noerr( err );
+        err = ReshapeCustomWindow( windowRef );
+        verify_noerr( err );
+    }
+
+    return true ;
+}
+
 // TODO: switch to structure bounds -
 // we are still using coordinates of the content view
 //
index 9d32605485993c81ad7af2b639b107fbfb589826..bd25da73e0c7b0279acddf8c678de461a1dd648d 100644 (file)
@@ -278,6 +278,15 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                             }
                         }
                         CGContextSetAlpha( cgContext , alpha ) ;
+
+                        if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
+                        {
+                            HIRect bounds;
+                            HIViewGetBounds( controlRef, &bounds );
+                            CGContextClearRect( cgContext, bounds );
+                        }
+
+
 #endif
                         if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
                             result = noErr ;
@@ -2363,7 +2372,8 @@ void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
         return ;
 
 #if TARGET_API_MAC_OSX
-    if ( !m_macBackgroundBrush.Ok() || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT )
+    if ( !m_macBackgroundBrush.Ok() || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT
+         || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
     {
         event.Skip() ;
     }
@@ -3343,7 +3353,8 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
 
 void wxWindowMac::OnPaint( wxPaintEvent & event )
 {
-    if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
+    if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
+         && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
         CallNextEventHandler(
             (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
             (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
@@ -3387,6 +3398,8 @@ bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
 bool wxWindowMac::SetTransparent(wxByte alpha)
 {
 #if wxMAC_USE_CORE_GRAPHICS
+    SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
+
     if ( alpha != m_macAlpha )
     {
         m_macAlpha = alpha ;