Merge branch 'win-transparency'
Improve shaped sample and its documentation. See #22230.
This commit is contained in:
@@ -690,10 +690,14 @@ utility under macOS).
|
|||||||
|
|
||||||
@section page_samples_shaped Shaped Window Sample
|
@section page_samples_shaped Shaped Window Sample
|
||||||
|
|
||||||
@sampleabout{how to implement a shaped or transparent window\, and a window showing/hiding with effect}
|
@sampleabout{Showing unusual, e.g. shaped or semi-transparent windows}
|
||||||
|
|
||||||
|
This sample shows windows with non-rectangular shapes and non-opaque windows as
|
||||||
|
well as how the windows can be shown with a special effect.
|
||||||
|
|
||||||
@see wxTopLevelWindow::SetShape(), wxTopLevelWindow::SetTransparent(),
|
@see wxTopLevelWindow::SetShape(), wxTopLevelWindow::SetTransparent(),
|
||||||
wxWindow::ShowWithEffect(), wxWindow::HideWithEffect()
|
wxWindow::ShowWithEffect(), wxWindow::HideWithEffect(),
|
||||||
|
wxWindow::SetBackgroundStyle()
|
||||||
|
|
||||||
@sampledir{shaped}
|
@sampledir{shaped}
|
||||||
|
|
||||||
|
|||||||
@@ -585,6 +585,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
If the platform supports it will set the window to be translucent.
|
If the platform supports it will set the window to be translucent.
|
||||||
|
|
||||||
|
Note that in wxGTK this function must be called before the window is
|
||||||
|
shown the first time it's called (but it can be called again after
|
||||||
|
showing the window too).
|
||||||
|
|
||||||
|
See @ref page_samples_shaped "the shaped sample" for an example of
|
||||||
|
using this function.
|
||||||
|
|
||||||
@param alpha
|
@param alpha
|
||||||
Determines how opaque or transparent the window will be, if the
|
Determines how opaque or transparent the window will be, if the
|
||||||
platform supports the operation. A value of 0 sets the window to be
|
platform supports the operation. A value of 0 sets the window to be
|
||||||
|
|||||||
@@ -2395,7 +2395,9 @@ public:
|
|||||||
Under wxGTK and wxOSX, you can use ::wxBG_STYLE_TRANSPARENT to obtain
|
Under wxGTK and wxOSX, you can use ::wxBG_STYLE_TRANSPARENT to obtain
|
||||||
full transparency of the window background. Note that wxGTK supports
|
full transparency of the window background. Note that wxGTK supports
|
||||||
this only since GTK 2.12 with a compositing manager enabled, call
|
this only since GTK 2.12 with a compositing manager enabled, call
|
||||||
IsTransparentBackgroundSupported() to check whether this is the case.
|
IsTransparentBackgroundSupported() to check whether this is the case,
|
||||||
|
see the example of doing it in @ref page_samples_shaped "the shaped
|
||||||
|
sample".
|
||||||
|
|
||||||
Also, in order for @c SetBackgroundStyle(wxBG_STYLE_TRANSPARENT) to
|
Also, in order for @c SetBackgroundStyle(wxBG_STYLE_TRANSPARENT) to
|
||||||
work, it must be called before Create(). If you're using your own
|
work, it must be called before Create(). If you're using your own
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
#include "wx/dcclient.h"
|
#include "wx/dcclient.h"
|
||||||
#include "wx/graphics.h"
|
#include "wx/graphics.h"
|
||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
|
#include "wx/scopedptr.h"
|
||||||
|
#include "wx/sizer.h"
|
||||||
|
#include "wx/slider.h"
|
||||||
|
|
||||||
#ifndef wxHAS_IMAGES_IN_RESOURCES
|
#ifndef wxHAS_IMAGES_IN_RESOURCES
|
||||||
#include "../sample.xpm"
|
#include "../sample.xpm"
|
||||||
@@ -50,6 +53,7 @@ enum
|
|||||||
{
|
{
|
||||||
Show_Shaped = 100,
|
Show_Shaped = 100,
|
||||||
Show_Transparent,
|
Show_Transparent,
|
||||||
|
Show_TransparentBg,
|
||||||
|
|
||||||
// must be consecutive and in the same order as wxShowEffect enum elements
|
// must be consecutive and in the same order as wxShowEffect enum elements
|
||||||
Show_Effect_First,
|
Show_Effect_First,
|
||||||
@@ -134,12 +138,14 @@ private:
|
|||||||
class SeeThroughFrame : public wxFrame
|
class SeeThroughFrame : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Create();
|
void Create(wxWindow* parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// event handlers (these functions should _not_ be virtual)
|
// event handlers (these functions should _not_ be virtual)
|
||||||
void OnPaint(wxPaintEvent& evt);
|
void OnPaint(wxPaintEvent& evt);
|
||||||
|
|
||||||
|
void OnAlpha(wxCommandEvent& event);
|
||||||
|
|
||||||
// any class wishing to process wxWidgets events must use this macro
|
// any class wishing to process wxWidgets events must use this macro
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
@@ -238,6 +244,7 @@ bool MyApp::OnInit()
|
|||||||
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||||
EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
|
EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
|
||||||
EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
|
EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
|
||||||
|
EVT_MENU(Show_TransparentBg, MainFrame::OnShowTransparent)
|
||||||
EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
|
EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
|
||||||
EVT_MENU(wxID_EXIT, MainFrame::OnExit)
|
EVT_MENU(wxID_EXIT, MainFrame::OnExit)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
@@ -252,6 +259,8 @@ MainFrame::MainFrame()
|
|||||||
wxMenu * const menuFrames = new wxMenu;
|
wxMenu * const menuFrames = new wxMenu;
|
||||||
menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
|
menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
|
||||||
menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
|
menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
|
||||||
|
menuFrames->Append(Show_TransparentBg,
|
||||||
|
"Show with &transparent background\tShift-Ctrl-T");
|
||||||
menuFrames->AppendSeparator();
|
menuFrames->AppendSeparator();
|
||||||
menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
|
menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
|
||||||
menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
|
menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
|
||||||
@@ -272,19 +281,27 @@ void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
|
|||||||
shapedFrame->Show(true);
|
shapedFrame->Show(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
|
void MainFrame::OnShowTransparent(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
||||||
|
|
||||||
|
if ( event.GetId() == Show_TransparentBg )
|
||||||
|
{
|
||||||
wxString reason;
|
wxString reason;
|
||||||
if (IsTransparentBackgroundSupported(&reason))
|
if (IsTransparentBackgroundSupported(&reason))
|
||||||
{
|
{
|
||||||
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
seeThroughFrame->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||||
seeThroughFrame->Create();
|
|
||||||
seeThroughFrame->Show(true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxLogError("%s, can't create transparent window.", reason);
|
wxLogError("Can't use transparent background: %s", reason);
|
||||||
|
delete seeThroughFrame;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seeThroughFrame->Create(this);
|
||||||
|
seeThroughFrame->Show(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnShowEffect(wxCommandEvent& event)
|
void MainFrame::OnShowEffect(wxCommandEvent& event)
|
||||||
@@ -474,44 +491,77 @@ wxBEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
|
|||||||
EVT_PAINT(SeeThroughFrame::OnPaint)
|
EVT_PAINT(SeeThroughFrame::OnPaint)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
void SeeThroughFrame::Create()
|
void
|
||||||
|
SeeThroughFrame::Create(wxWindow* parent)
|
||||||
{
|
{
|
||||||
SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
wxFrame::Create(parent, wxID_ANY, "Transparency test",
|
||||||
wxFrame::Create(NULL, wxID_ANY, "Transparency test",
|
wxDefaultPosition, wxWindow::FromDIP(wxSize(300, 300), parent),
|
||||||
wxPoint(100, 30), wxSize(300, 300),
|
|
||||||
wxDEFAULT_FRAME_STYLE |
|
wxDEFAULT_FRAME_STYLE |
|
||||||
wxFULL_REPAINT_ON_RESIZE |
|
wxFULL_REPAINT_ON_RESIZE |
|
||||||
wxSTAY_ON_TOP);
|
wxSTAY_ON_TOP);
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
|
|
||||||
|
const int initialAlpha = wxALPHA_OPAQUE / 2;
|
||||||
|
|
||||||
|
// Create control for choosing alpha and put it in the middle of the window.
|
||||||
|
wxPanel* panel = new wxPanel(this);
|
||||||
|
wxSlider* slider = new wxSlider
|
||||||
|
(
|
||||||
|
panel,
|
||||||
|
wxID_ANY,
|
||||||
|
initialAlpha,
|
||||||
|
wxALPHA_TRANSPARENT,
|
||||||
|
wxALPHA_OPAQUE,
|
||||||
|
wxDefaultPosition,
|
||||||
|
FromDIP(wxSize(256, -1)),
|
||||||
|
wxSL_HORIZONTAL | wxSL_LABELS
|
||||||
|
);
|
||||||
|
slider->Bind(wxEVT_SLIDER, &SeeThroughFrame::OnAlpha, this);
|
||||||
|
|
||||||
|
const wxSizerFlags center = wxSizerFlags().Center().Border();
|
||||||
|
|
||||||
|
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sizer->Add(new wxStaticText(panel, wxID_ANY, "Window opacity:"), center);
|
||||||
|
sizer->Add(slider, center);
|
||||||
|
panel->SetSizer(sizer);
|
||||||
|
|
||||||
|
wxSizer* sizerTop = new wxBoxSizer(wxVERTICAL);
|
||||||
|
sizerTop->AddStretchSpacer();
|
||||||
|
sizerTop->Add(panel, center);
|
||||||
|
sizerTop->AddStretchSpacer();
|
||||||
|
SetSizer(sizerTop);
|
||||||
|
|
||||||
|
// Note that this must be called before the frame is shown.
|
||||||
|
SetTransparent(initialAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paints a grid of varying hue and alpha
|
// Paints a grid of varying hue and alpha
|
||||||
void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
|
void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
|
||||||
{
|
{
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
dc.SetPen(wxNullPen);
|
wxScopedPtr<wxGraphicsContext> gc(wxGraphicsContext::Create(dc));
|
||||||
|
|
||||||
int xcount = 8;
|
// Draw 3 bands: one opaque, one semi-transparent and one transparent.
|
||||||
int ycount = 8;
|
const wxSize size = GetClientSize();
|
||||||
|
const double h = size.y / 3.0;
|
||||||
|
|
||||||
double xstep = 1.0 / xcount;
|
wxGraphicsPath path = gc->CreatePath();
|
||||||
double ystep = 1.0 / ycount;
|
path.AddRectangle(0, 0, size.x, h);
|
||||||
|
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_OPAQUE)));
|
||||||
|
gc->FillPath(path);
|
||||||
|
|
||||||
int width = GetClientSize().GetWidth();
|
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_OPAQUE / 2)));
|
||||||
int height = GetClientSize().GetHeight();
|
gc->Translate(0, h);
|
||||||
|
gc->FillPath(path);
|
||||||
|
|
||||||
for ( double x = 0; x < 1; x += xstep )
|
// This blue won't actually be seen and instead the white background will
|
||||||
{
|
// be visible, because this brush is fully transparent.
|
||||||
for ( double y = 0; y < 1; y += ystep )
|
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_TRANSPARENT)));
|
||||||
{
|
gc->Translate(0, h);
|
||||||
wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
|
gc->FillPath(path);
|
||||||
dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
|
}
|
||||||
(int)(255*(1. - y)))));
|
|
||||||
int x1 = (int)(x * width);
|
void SeeThroughFrame::OnAlpha(wxCommandEvent& event)
|
||||||
int y1 = (int)(y * height);
|
{
|
||||||
int x2 = (int)((x + xstep) * width);
|
SetTransparent(event.GetInt());
|
||||||
int y2 = (int)((y + ystep) * height);
|
|
||||||
dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user