X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/98dd66cf4ff5d41643bafdb510ec9b0e4d544062..56d85ddeece939e0d2cf602a45286e8368544320:/samples/erase/erase.cpp diff --git a/samples/erase/erase.cpp b/samples/erase/erase.cpp index 3e3d9635a6..37fc81bb88 100644 --- a/samples/erase/erase.cpp +++ b/samples/erase/erase.cpp @@ -1,11 +1,11 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: erase.cpp -// Purpose: Erase wxWindows sample -// Author: Robert Roebling -// Modified by: +// Name: samples/erase/erase.cpp +// Purpose: Erase wxWidgets sample +// Author: Robert Roebling, Vadim Zeitlin // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Robert Roebling +// Copyright: (c) 1998 Robert Roebling +// (c) 2009 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,11 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "erase.cpp" - #pragma interface "erase.cpp" -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -30,17 +25,22 @@ #endif // for all others, include the necessary headers (this file is usually all you -// need because it includes almost all "standard" wxWindows headers) +// need because it includes almost all "standard" wxWidgets headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif +#include "wx/custombgwin.h" +#include "wx/dcbuffer.h" +#include "wx/artprov.h" + // ---------------------------------------------------------------------------- // resources // ---------------------------------------------------------------------------- + // the application icon -#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__) - #include "mondrian.xpm" +#ifndef wxHAS_IMAGES_IN_RESOURCES + #include "../sample.xpm" #endif // ---------------------------------------------------------------------------- @@ -54,33 +54,146 @@ public: }; -class MyFrame : public wxFrame +class MyCanvas : public wxCustomBackgroundWindow { public: - MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + MyCanvas(wxFrame *parent); - void OnQuit(wxCommandEvent& event); - void OnAbout(wxCommandEvent& event); + void UseBuffer(bool useBuffer) { m_useBuffer = useBuffer; Refresh(); } + bool UsesBuffer() const { return m_useBuffer; } -private: - DECLARE_EVENT_TABLE() -}; + void UseBgBitmap(bool useBgBmp) + { + m_useBgBmp = useBgBmp; + SetBackgroundBitmap(m_useBgBmp ? GetBgBitmap() : wxBitmap()); + Refresh(); + } -class MyCanvas : public wxScrolledWindow -{ -public: - MyCanvas( MyFrame *parent ); + void EraseBgInPaint(bool erase) { m_eraseBgInPaint = erase; Refresh(); } +private: void OnPaint( wxPaintEvent &event ); void OnEraseBackground( wxEraseEvent &event ); + void DoPaint(wxDC& dc); + + // Create an easily recognizable background bitmap. + static wxBitmap GetBgBitmap() + { + static const int BMP_SIZE = 40; + + wxBitmap bmp(BMP_SIZE, BMP_SIZE); + wxMemoryDC dc(bmp); + dc.SetBackground(*wxCYAN); + dc.Clear(); + + dc.SetPen(*wxBLUE_PEN); + dc.DrawLine(0, BMP_SIZE/2, BMP_SIZE/2, 0); + dc.DrawLine(BMP_SIZE/2, 0, BMP_SIZE, BMP_SIZE/2); + dc.DrawLine(BMP_SIZE, BMP_SIZE/2, BMP_SIZE/2, BMP_SIZE); + dc.DrawLine(BMP_SIZE/2, BMP_SIZE, 0, BMP_SIZE/2); + + return bmp; + } + wxBitmap m_bitmap; + // use wxMemoryDC in OnPaint()? + bool m_useBuffer; + + // use background bitmap? + bool m_useBgBmp; + + // erase background in OnPaint()? + bool m_eraseBgInPaint; + + + DECLARE_EVENT_TABLE() +}; + +class MyFrame : public wxFrame +{ +public: + MyFrame(); + private: + void OnUseBuffer(wxCommandEvent& event); + void OnUseBgBitmap(wxCommandEvent& event); + void OnEraseBgInPaint(wxCommandEvent& event); + void OnChangeBgStyle(wxCommandEvent& event); + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + // we can only use double-buffering with wxBG_STYLE_PAINT + void OnUpdateUIUseBuffer(wxUpdateUIEvent& event) + { + event.Enable( m_canvas->GetBackgroundStyle() == wxBG_STYLE_PAINT ); + } + + void OnUpdateUIChangeBgStyle(wxUpdateUIEvent& event) + { + event.Enable( !m_canvas->UsesBuffer() ); + } + + MyCanvas *m_canvas; + DECLARE_EVENT_TABLE() }; +class ControlWithTransparency : public wxWindow +{ +public: + ControlWithTransparency(wxWindow *parent, + const wxPoint& pos, + const wxSize& size) + { + wxString reason; + if ( parent->IsTransparentBackgroundSupported(&reason) ) + { + SetBackgroundStyle (wxBG_STYLE_TRANSPARENT); + m_message = "This is custom control with transparency"; + } + else + { + m_message = "Transparency not supported, check tooltip."; + } + + Create (parent, wxID_ANY, pos, size, wxBORDER_NONE); + Connect(wxEVT_PAINT, + wxPaintEventHandler(ControlWithTransparency::OnPaint)); + + if ( !reason.empty() ) + { + // This can be only done now, after creating the window. + SetToolTip(reason); + } + } + +private: + void OnPaint( wxPaintEvent& WXUNUSED(event) ) + { + wxPaintDC dc(this); + + dc.SetPen(*wxRED_PEN); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(GetClientSize()); + + dc.SetTextForeground(*wxBLUE); + dc.SetBackgroundMode(wxTRANSPARENT); + dc.DrawText(m_message, 0, 2); + + // Draw some bitmap/icon to ensure transparent bitmaps are indeed + // transparent on transparent windows + wxBitmap bmp(wxArtProvider::GetBitmap(wxART_WARNING, wxART_MENU)); + wxIcon icon(wxArtProvider::GetIcon(wxART_GOTO_LAST, wxART_MENU)); + dc.DrawBitmap (bmp, GetSize().x - 1 - bmp.GetWidth(), 2); + dc.DrawIcon(icon, GetSize().x - 1 - bmp.GetWidth()-icon.GetWidth(), 2); + } + + wxString m_message; +}; + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -88,8 +201,14 @@ private: enum { // menu items - Minimal_Quit = 1, - Minimal_About + Erase_Menu_UseBuffer = 100, + Erase_Menu_UseBgBitmap, + Erase_Menu_EraseBgInPaint, + Erase_Menu_BgStyleErase, + Erase_Menu_BgStyleSystem, + Erase_Menu_BgStylePaint, + Erase_Menu_Exit = wxID_EXIT, + Erase_Menu_About = wxID_ABOUT }; @@ -101,12 +220,14 @@ IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { - MyFrame *frame = new MyFrame(_T("Minimal wxWindows App"), - wxPoint(50, 50), wxSize(450, 340)); + if ( !wxApp::OnInit() ) + return false; + + MyFrame *frame = new MyFrame; - frame->Show(TRUE); + frame->Show(true); - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -114,153 +235,210 @@ bool MyApp::OnInit() // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(Minimal_Quit, MyFrame::OnQuit) - EVT_MENU(Minimal_About, MyFrame::OnAbout) + EVT_MENU(Erase_Menu_UseBuffer, MyFrame::OnUseBuffer) + EVT_MENU(Erase_Menu_UseBgBitmap, MyFrame::OnUseBgBitmap) + EVT_MENU(Erase_Menu_EraseBgInPaint, MyFrame::OnEraseBgInPaint) + EVT_MENU_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint, + MyFrame::OnChangeBgStyle) + + EVT_MENU(Erase_Menu_Exit, MyFrame::OnQuit) + EVT_MENU(Erase_Menu_About, MyFrame::OnAbout) + + EVT_UPDATE_UI(Erase_Menu_UseBuffer, MyFrame::OnUpdateUIUseBuffer) + EVT_UPDATE_UI_RANGE(Erase_Menu_BgStyleErase, Erase_Menu_BgStylePaint, + MyFrame::OnUpdateUIChangeBgStyle) END_EVENT_TABLE() // frame constructor -MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame((wxFrame *)NULL, -1, title, pos, size) +MyFrame::MyFrame() + : wxFrame(NULL, wxID_ANY, "Erase sample", + wxPoint(50, 50), wxSize(450, 340)) { -#ifdef __WXMAC__ - wxApp::s_macAboutMenuItemId = Minimal_About; -#endif - - SetIcon(wxICON(mondrian)); + SetIcon(wxICON(sample)); wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF); + menuFile->AppendCheckItem(Erase_Menu_UseBuffer, "&Use memory DC\tCtrl-M"); + menuFile->AppendCheckItem(Erase_Menu_UseBgBitmap, + "Use background &bitmap\tCtrl-B"); + menuFile->AppendCheckItem(Erase_Menu_EraseBgInPaint, + "&Erase background in EVT_PAINT\tCtrl-R"); + menuFile->AppendSeparator(); + menuFile->AppendRadioItem(Erase_Menu_BgStyleErase, + "Use wxBG_STYLE_&ERASE\tCtrl-E"); + menuFile->AppendRadioItem(Erase_Menu_BgStyleSystem, + "Use wxBG_STYLE_&SYSTEM\tCtrl-S"); + menuFile->AppendRadioItem(Erase_Menu_BgStylePaint, + "Use wxBG_STYLE_&PAINT\tCtrl-P"); + menuFile->AppendSeparator(); + menuFile->Append(Erase_Menu_Exit, "E&xit\tAlt-X", "Quit this program"); - wxMenu *helpMenu = new wxMenu; - helpMenu->Append(Minimal_About, _T("&About...\tCtrl-A"), _T("Show about dialog")); - menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); + wxMenu *helpMenu = new wxMenu; + helpMenu->Append(Erase_Menu_About, "&About\tCtrl-A", "Show about dialog"); wxMenuBar *menuBar = new wxMenuBar(); - menuBar->Append(menuFile, _T("&File")); - menuBar->Append(helpMenu, _T("&Help")); + menuBar->Append(menuFile, "&File"); + menuBar->Append(helpMenu, "&Help"); SetMenuBar(menuBar); -#if wxUSE_STATUSBAR - // create a status bar just for fun (by default with 1 pane only) - CreateStatusBar(2); - SetStatusText(_T("Welcome to wxWindows erase sample!")); -#endif // wxUSE_STATUSBAR + m_canvas = new MyCanvas( this ); +} + - (void)new MyCanvas( this ); +void MyFrame::OnUseBuffer(wxCommandEvent& event) +{ + m_canvas->UseBuffer(event.IsChecked()); } +void MyFrame::OnUseBgBitmap(wxCommandEvent& event) +{ + m_canvas->UseBgBitmap(event.IsChecked()); +} + +void MyFrame::OnEraseBgInPaint(wxCommandEvent& event) +{ + m_canvas->EraseBgInPaint(event.IsChecked()); +} + +void MyFrame::OnChangeBgStyle(wxCommandEvent& event) +{ + int style = wxBG_STYLE_ERASE + event.GetId() - Erase_Menu_BgStyleErase; + m_canvas->SetBackgroundStyle(static_cast(style)); + + m_canvas->Refresh(); +} void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { - Close(TRUE); + Close(true); } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { - wxMessageBox(_T("This sample shows how you can draw custom background."), - _T("About Erase Sample"), wxOK | wxICON_INFORMATION, this); + wxMessageBox + ( + "This sample shows differences between different background styles " + "and how you may draw custom background.\n" + "\n" + "(c) 1998 Robert Roebling\n" + "(c) 2009 Vadim Zeitlin\n", + "About Erase Sample", + wxOK | wxICON_INFORMATION, + this + ); } BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) - EVT_PAINT( MyCanvas::OnPaint) - EVT_ERASE_BACKGROUND( MyCanvas::OnEraseBackground) + EVT_PAINT(MyCanvas::OnPaint) + EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackground) END_EVENT_TABLE() -MyCanvas::MyCanvas( MyFrame *parent ) - : wxScrolledWindow( parent, -1, wxDefaultPosition, wxDefaultSize, - wxScrolledWindowStyle | - wxNO_FULL_REPAINT_ON_RESIZE| - wxSUNKEN_BORDER ) +MyCanvas::MyCanvas(wxFrame *parent) { - SetScrollbars( 10, 10, 40, 100, 0, 0 ); - - m_bitmap = wxBitmap( wxICON(mondrian) ); + Create(parent, wxID_ANY); - new wxStaticBitmap( this, -1, m_bitmap, wxPoint(80,20) ); -} + m_useBuffer = false; + m_useBgBmp = false; + m_eraseBgInPaint = false; -void MyCanvas::OnPaint( wxPaintEvent &event ) -{ - wxPaintDC dc(this); - PrepareDC( dc ); + SetScrollbars( 10, 10, 40, 100, 0, 0 ); - dc.SetBrush( *wxBLACK_BRUSH ); - dc.DrawRectangle( 0,0,200,50 ); + m_bitmap = wxBitmap( wxICON(sample) ); - dc.DrawBitmap( m_bitmap, 10, 20, TRUE ); + new wxStaticBitmap( this, wxID_ANY, m_bitmap, wxPoint(80,20) ); - dc.SetTextForeground(*wxBLUE); - dc.DrawText(_T("This text is drawn from OnPaint"), 65, 65); + new wxStaticText(this, wxID_ANY, + "Left bitmap is a wxStaticBitmap,\n" + "right one drawn directly", + wxPoint(150, 20)); -#if 0 - wxRegionIterator upd( GetUpdateRegion() ); - while (upd) - { - wxLogDebug( "Paint: %d %d %d %d", upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); - upd ++; - } -#endif + new ControlWithTransparency(this, wxPoint(65, 125), wxSize(350, 22)); -#if 0 - wxSize size = GetSize(); - wxSize client_size = GetClientSize(); - wxLogDebug( "size %d %d client_size %d %d", size.x, size.y, client_size.x, client_size.y ); -#endif + SetFocusIgnoringChildren(); + SetBackgroundColour(*wxCYAN); +} -#if 0 - int i; - dc.SetPen( *wxWHITE_PEN ); - for (i = 0; i < 20; i += 2) - dc.DrawLine( i,i, i+100,i ); +void MyCanvas::DoPaint(wxDC& dc) +{ + PrepareDC(dc); - dc.SetPen( *wxWHITE_PEN ); - for (i = 200; i < 220; i += 2) - dc.DrawLine( i-200,i, i-100,i ); + if ( m_eraseBgInPaint ) + { + dc.SetBackground(*wxLIGHT_GREY); - wxRegion region( 110, 110, 80, 80 ); - wxRegion hole( 130, 130, 40, 1 ); - region.Intersect( hole ); - dc.SetClippingRegion( region ); + // Erase the entire virtual area, not just the client area. + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(GetBackgroundColour()); + dc.DrawRectangle(GetVirtualSize()); - dc.SetBrush( *wxRED_BRUSH ); - dc.DrawRectangle( 100, 100, 200, 200 ); + dc.DrawText("Background erased in OnPaint", 65, 110); + } + else if ( GetBackgroundStyle() == wxBG_STYLE_PAINT ) + { + dc.SetTextForeground(*wxRED); + dc.DrawText("You must enable erasing background in OnPaint to avoid " + "display corruption", 65, 110); + } - dc.DestroyClippingRegion(); + dc.DrawBitmap( m_bitmap, 20, 20, true ); - dc.SetPen( *wxTRANSPARENT_PEN ); + dc.SetTextForeground(*wxRED); + dc.DrawText("This text is drawn from OnPaint", 65, 65); +} - wxRegion strip( 110, 200, 30, 1 ); - wxRegionIterator it( strip ); - while (it) +void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) +{ + if ( m_useBuffer ) + { + wxAutoBufferedPaintDC dc(this); + DoPaint(dc); + } + else { - dc.DrawRectangle( it.GetX(), it.GetY(), it.GetWidth(), it.GetHeight() ); - it ++; + wxPaintDC dc(this); + DoPaint(dc); } -#endif // 0 } void MyCanvas::OnEraseBackground( wxEraseEvent& event ) { + // We must not erase the background ourselves if we asked wxPanel to erase + // it using a background bitmap. + if ( m_useBgBmp ) + { + event.Skip(); + return; + } + + wxASSERT_MSG + ( + GetBackgroundStyle() == wxBG_STYLE_ERASE, + "shouldn't be called unless background style is \"erase\"" + ); + wxDC& dc = *event.GetDC(); dc.SetPen(*wxGREEN_PEN); - // this line is needed, otherwise the junk is left on win the background + // clear any junk currently displayed dc.Clear(); - wxSize size = GetClientSize(); - for ( int x = 0; x < size.x; x+= 10 ) + PrepareDC( dc ); + + const wxSize size = GetVirtualSize(); + for ( int x = 0; x < size.x; x += 15 ) { dc.DrawLine(x, 0, x, size.y); } - for ( int y = 0; y < size.y; y+= 10 ) + for ( int y = 0; y < size.y; y += 15 ) { dc.DrawLine(0, y, size.x, y); } dc.SetTextForeground(*wxRED); - dc.DrawText(_T("This text is drawn from OnEraseBackground"), 60, 60); + dc.SetBackgroundMode(wxSOLID); + dc.DrawText("This text is drawn from OnEraseBackground", 60, 160); }