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/graphics.h"
|
||||
#include "wx/image.h"
|
||||
#include "wx/scopedptr.h"
|
||||
#include "wx/sizer.h"
|
||||
#include "wx/slider.h"
|
||||
|
||||
#ifndef wxHAS_IMAGES_IN_RESOURCES
|
||||
#include "../sample.xpm"
|
||||
@@ -50,6 +53,7 @@ enum
|
||||
{
|
||||
Show_Shaped = 100,
|
||||
Show_Transparent,
|
||||
Show_TransparentBg,
|
||||
|
||||
// must be consecutive and in the same order as wxShowEffect enum elements
|
||||
Show_Effect_First,
|
||||
@@ -134,12 +138,14 @@ private:
|
||||
class SeeThroughFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
void Create();
|
||||
void Create(wxWindow* parent);
|
||||
|
||||
private:
|
||||
// event handlers (these functions should _not_ be virtual)
|
||||
void OnPaint(wxPaintEvent& evt);
|
||||
|
||||
void OnAlpha(wxCommandEvent& event);
|
||||
|
||||
// any class wishing to process wxWidgets events must use this macro
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
@@ -238,6 +244,7 @@ bool MyApp::OnInit()
|
||||
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||
EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
|
||||
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(wxID_EXIT, MainFrame::OnExit)
|
||||
wxEND_EVENT_TABLE()
|
||||
@@ -252,6 +259,8 @@ MainFrame::MainFrame()
|
||||
wxMenu * const menuFrames = new wxMenu;
|
||||
menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
|
||||
menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
|
||||
menuFrames->Append(Show_TransparentBg,
|
||||
"Show with &transparent background\tShift-Ctrl-T");
|
||||
menuFrames->AppendSeparator();
|
||||
menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
|
||||
menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
|
||||
@@ -272,19 +281,27 @@ void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
|
||||
shapedFrame->Show(true);
|
||||
}
|
||||
|
||||
void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
|
||||
void MainFrame::OnShowTransparent(wxCommandEvent& event)
|
||||
{
|
||||
wxString reason;
|
||||
if (IsTransparentBackgroundSupported(&reason))
|
||||
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
||||
|
||||
if ( event.GetId() == Show_TransparentBg )
|
||||
{
|
||||
SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
|
||||
seeThroughFrame->Create();
|
||||
seeThroughFrame->Show(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogError("%s, can't create transparent window.", reason);
|
||||
wxString reason;
|
||||
if (IsTransparentBackgroundSupported(&reason))
|
||||
{
|
||||
seeThroughFrame->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogError("Can't use transparent background: %s", reason);
|
||||
delete seeThroughFrame;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
seeThroughFrame->Create(this);
|
||||
seeThroughFrame->Show(true);
|
||||
}
|
||||
|
||||
void MainFrame::OnShowEffect(wxCommandEvent& event)
|
||||
@@ -474,44 +491,77 @@ wxBEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
|
||||
EVT_PAINT(SeeThroughFrame::OnPaint)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
void SeeThroughFrame::Create()
|
||||
void
|
||||
SeeThroughFrame::Create(wxWindow* parent)
|
||||
{
|
||||
SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||
wxFrame::Create(NULL, wxID_ANY, "Transparency test",
|
||||
wxPoint(100, 30), wxSize(300, 300),
|
||||
wxFrame::Create(parent, wxID_ANY, "Transparency test",
|
||||
wxDefaultPosition, wxWindow::FromDIP(wxSize(300, 300), parent),
|
||||
wxDEFAULT_FRAME_STYLE |
|
||||
wxFULL_REPAINT_ON_RESIZE |
|
||||
wxSTAY_ON_TOP);
|
||||
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
|
||||
void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(wxNullPen);
|
||||
wxScopedPtr<wxGraphicsContext> gc(wxGraphicsContext::Create(dc));
|
||||
|
||||
int xcount = 8;
|
||||
int ycount = 8;
|
||||
// Draw 3 bands: one opaque, one semi-transparent and one transparent.
|
||||
const wxSize size = GetClientSize();
|
||||
const double h = size.y / 3.0;
|
||||
|
||||
double xstep = 1.0 / xcount;
|
||||
double ystep = 1.0 / ycount;
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
path.AddRectangle(0, 0, size.x, h);
|
||||
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_OPAQUE)));
|
||||
gc->FillPath(path);
|
||||
|
||||
int width = GetClientSize().GetWidth();
|
||||
int height = GetClientSize().GetHeight();
|
||||
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_OPAQUE / 2)));
|
||||
gc->Translate(0, h);
|
||||
gc->FillPath(path);
|
||||
|
||||
for ( double x = 0; x < 1; x += xstep )
|
||||
{
|
||||
for ( double 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);
|
||||
}
|
||||
}
|
||||
// This blue won't actually be seen and instead the white background will
|
||||
// be visible, because this brush is fully transparent.
|
||||
gc->SetBrush(wxBrush(wxColour(0, 0, 255, wxALPHA_TRANSPARENT)));
|
||||
gc->Translate(0, h);
|
||||
gc->FillPath(path);
|
||||
}
|
||||
|
||||
void SeeThroughFrame::OnAlpha(wxCommandEvent& event)
|
||||
{
|
||||
SetTransparent(event.GetInt());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user