Make transparency window in the shaped sample work under MSW
Still show transparent window even if IsTransparentBackgroundSupported() returns false, just don't make their background transparent and only use SetTransparent() in this case. In fact, don't try to use transparent background style at all by default and add a separate menu item to do it if wanted. Also add a slider to allow changing opacity of the window. Finally, make the window big enough in high DPI under MSW by using FromDIP().
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
wxString reason;
|
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
||||||
if (IsTransparentBackgroundSupported(&reason))
|
|
||||||
|
if ( event.GetId() == Show_TransparentBg )
|
||||||
{
|
{
|
||||||
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
wxString reason;
|
||||||
seeThroughFrame->Create();
|
if (IsTransparentBackgroundSupported(&reason))
|
||||||
seeThroughFrame->Show(true);
|
{
|
||||||
}
|
seeThroughFrame->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||||
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