Problem mit wxBufferedPaintDC bzw. Transparenz und Flicker'n



  • Schönen Guten Abend,

    seit gestern versuche ich verzweifelt meine kleine Button Owner-Draw Klasse zum laufen zu bringen, aber wxWidgets möchte mich ärgern 🤡
    Die Klasse Zeichnet eigene Button(s) was auch funktioniert. Aber man kann sich entscheiden ob man Starkes Flicker'n haben möchte,
    oder lieber doch keine funktionierende Transparenz. Im Code ist es Kommentiert.

    main.h

    #include <wx/wx.h>
    #include "dialog.h"
    
    class MainApp : public wxApp
    {
      public:
        virtual bool OnInit();
      private:
    	MainlDialog * frame;
    };
    

    main.cpp

    #include "main.h"
    
    bool MainApp::OnInit()
    {
    	wxInitAllImageHandlers();
    
    	frame = new MainlDialog(wxT("wxDC Test"), wxDefaultPosition, wxDefaultSize);
    	frame->SetBackgroundColour(wxColor(215,215,215));
    	frame->Center();
    	frame->Show();
    	return true;
    } 
    
    IMPLEMENT_APP(MainApp)
    

    dialog.h

    #ifndef INCLUDED_DLG_H
    #define INCLUDED_DLG_H
    
    #include <wx/wx.h>
    #include <wx/sizer.h>
    #include <wx/image.h>
    
    #include "odButton.h"
    
    class MainlDialog : public wxDialog
    {
    public:
        MainlDialog(const wxString& title, const wxPoint& pos, const wxSize& size);
        void OnPaint(wxPaintEvent &event);
    	void OnErase(wxEraseEvent& event);
    	void OnProgressTimer(wxTimerEvent& event);
    	void SetState(wxCommandEvent& WXUNUSED(event));
    	void StartTimer(wxCommandEvent& WXUNUSED(event));
        void OnClose(wxCloseEvent& e);
    
    private:
        wxButton *m_btnSet;
        wxButton *m_btnStart;
    	wxCustomButton *m_btnOd;
    	wxTimer *m_timer;
    
    	long int m_count;
    
        DECLARE_EVENT_TABLE()
    };
    
    enum
    {
    	BTN_Close = 1,
    	BTN_SET,
    	BTN_START,
    	EVT_TIMER,
    };
    
    #endif
    

    dialog.cpp

    #include "dialog.h"
    
    MainlDialog::MainlDialog(const wxString& title, const wxPoint& pos, const wxSize& size)
           : wxDialog((wxDialog *)NULL, -1, title, pos, size)
    {
    	m_count = 0;
    
    	wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
    
    	m_btnSet = new wxButton(this, BTN_SET, wxT("Bitte klick mich!"));
    	m_btnStart = new wxButton(this, BTN_START, wxT("Start Timer"));
    	m_btnOd = new wxCustomButton(this, BTN_Close, wxT("ein wxCustomButton"));
    	m_timer = new wxTimer(this, EVT_TIMER);
    
    	sizerTop->Add(m_btnSet, 0, wxALIGN_CENTER | wxALL, 10);
    	sizerTop->Add(m_btnStart, 0, wxALIGN_CENTER | wxALL, 10);
    	sizerTop->Add(m_btnOd, 0, wxALIGN_CENTER | wxALL, 10);
    
    	SetSizerAndFit(sizerTop);	
    
        m_btnSet->SetFocus();
        m_btnSet->SetDefault();
    
        Connect (-1, wxEVT_CLOSE_WINDOW,wxCloseEventHandler (MainlDialog::OnClose),NULL, this);
    }
    
    void MainlDialog::SetState(wxCommandEvent& WXUNUSED(event))
    {
    	if(m_btnOd->IsEnabled())
    	{
    		m_btnOd->Disable();
    		m_btnOd->SetLabel(wxT("bin deaktiviert!"));
    	}
    	else
    	{
    		m_btnOd->Enable();
    		m_btnOd->SetLabel(wxT("bin aktiviert!"));
    	}	
    }
    
    void MainlDialog::StartTimer(wxCommandEvent& WXUNUSED(event))
    {
    	if(m_timer->IsRunning())
    	{
    		m_timer->Stop();
    		m_count = 0;
    		m_btnStart->SetLabel(wxT("Start Timer"));
    	}
    	else
    	{
    		m_timer->Start(10);
    		m_btnStart->SetLabel(wxT("Stop Timer"));
    	}
    }
    
    void MainlDialog::OnClose(wxCloseEvent& e)
    {
    	m_timer->Stop();
    	Destroy();
    }
    
    void MainlDialog::OnPaint(wxPaintEvent& event)
    {
    
    }
    
    void MainlDialog::OnProgressTimer(wxTimerEvent& event)
    {
    	m_count++;
    	m_btnOd->SetLabel(wxString::Format(wxT("count => %d"), m_count));
    }
    
    // ----------------------------------------------------------------------------
    // event tables and other macros
    // ----------------------------------------------------------------------------
    
    BEGIN_EVENT_TABLE(MainlDialog, wxDialog)
    	EVT_BUTTON(BTN_SET, MainlDialog::SetState)
    	EVT_BUTTON(BTN_START, MainlDialog::StartTimer)
        EVT_PAINT(MainlDialog::OnPaint)
    	EVT_TIMER(EVT_TIMER, MainlDialog::OnProgressTimer)
    END_EVENT_TABLE()
    

    odButton.h

    #ifndef INCLUDED_ODB_H
    #define INCLUDED_ODB_H
    
    #include <wx/wx.h>
    
    #include <wx/dcbuffer.h>
    #include <wx/dcgraph.h>
    
    class wxCustomButton : public wxPanel
    {
    
        bool pressedDown;
        wxString text;
    
    	wxImage pngimage;
    	wxBitmap bitmap;
    
        static const int buttonWidth = 150;
        static const int buttonHeight = 32;
    
    public:
        wxCustomButton(wxWindow* parent, const int & id, const wxString & text);
    
        void paintNow();
        void render(wxDC& dc);
    
        void SetLabel(const wxString & text);
    	void Enable();
    	void Disable();
    
        void paintEvent(wxPaintEvent & evt);
    	void wxCustomButton::OnEraseBackGround(wxEraseEvent& event);
    
        // some useful events
        void mouseMoved(wxMouseEvent& event);
        void mouseDown(wxMouseEvent& event);
        void mouseWheelMoved(wxMouseEvent& event);
        void mouseReleased(wxMouseEvent& event);
        void rightClick(wxMouseEvent& event);
        void mouseLeftWindow(wxMouseEvent& event);
        void mouseEnterWindow(wxMouseEvent& event);
        void keyPressed(wxKeyEvent& event);
        void keyReleased(wxKeyEvent& event);
    
        DECLARE_EVENT_TABLE()
    };
    
    #endif
    

    odButton.cpp

    #include "odButton.h"
    
    BEGIN_EVENT_TABLE(wxCustomButton, wxPanel)
    
        EVT_MOTION(wxCustomButton::mouseMoved)
        EVT_LEFT_DOWN(wxCustomButton::mouseDown)
        EVT_LEFT_UP(wxCustomButton::mouseReleased)
        EVT_RIGHT_DOWN(wxCustomButton::rightClick)
        EVT_LEAVE_WINDOW(wxCustomButton::mouseLeftWindow)
    	EVT_ENTER_WINDOW(wxCustomButton::mouseEnterWindow)
        EVT_KEY_DOWN(wxCustomButton::keyPressed)
        EVT_KEY_UP(wxCustomButton::keyReleased)
        EVT_MOUSEWHEEL(wxCustomButton::mouseWheelMoved)
    
        // catch paint events
        EVT_PAINT(wxCustomButton::paintEvent)
    	EVT_ERASE_BACKGROUND(wxCustomButton::OnEraseBackGround)
    
    END_EVENT_TABLE()
    
    wxCustomButton::wxCustomButton(wxWindow* parent, const int & id, const wxString & text) :
    wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxTRANSPARENT_WINDOW, "panel")
    {
        SetMinSize( wxSize(buttonWidth, buttonHeight) );
        this->text = text;
        pressedDown = false;
    	pngimage = wxImage("test.png", wxBITMAP_TYPE_PNG);
    	bitmap = wxBitmap(wxT("test.bmp"), wxBITMAP_TYPE_BMP);
    }
    
    void wxCustomButton::SetLabel(const wxString & text)
    {
        this->text = text;
        paintNow();
    }
    
    void wxCustomButton::Enable()
    {
    	wxPanel::Enable();
    	paintNow();
    }
    
    void wxCustomButton::Disable()
    {
    	wxPanel::Disable();
    	paintNow();
    }
    
    void wxCustomButton::paintEvent(wxPaintEvent & evt)
    {
    	//starkes Flicker'n aber dafuer funktioniert die Transparenz
    	wxPaintDC dc(this);
        render(dc);
    
    	//Transparenz funktioniert nicht aber dafuer kein Flicker'n 
    	//wxBufferedPaintDC dc(this);
        //render(dc);
    }
    
    void wxCustomButton::paintNow()
    {
    	//starkes Flicker'n aber dafuer funktioniert die Transparenz	
    	wxClientDC cdc(this);
    	render(cdc);
    
    	//Transparenz funktioniert nicht aber dafuer kein Flicker'n
    	//wxDC * cdc;
    	//cdc = new wxClientDC(this);
    	//render(wxBufferedDC(cdc));
    }
    
    void wxCustomButton::OnEraseBackGround(wxEraseEvent& event)
    {
    }
    
    void wxCustomButton::render(wxDC& dc)
    {
    	wxRect cr = GetClientRect();
    
    	if (pressedDown && IsEnabled())
    	{
    		dc.DrawBitmap(pngimage, 0, 0, true);
    		dc.SetTextForeground(wxColor(255,255,255));
    	}
    	else if(!pressedDown && IsEnabled())
    	{
    
    		dc.DrawBitmap(pngimage,0, -32, true);
    		dc.SetTextForeground(wxColor(182,184,187));
    	}
    	else
    	{
    		dc.DrawBitmap(pngimage,0, -64, true);
    		dc.SetTextForeground(wxColor(100,101,103));
    	}
    
    	dc.DrawLabel(text, cr, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL);
    
    }
    
    void wxCustomButton::mouseDown(wxMouseEvent& event)
    {
        pressedDown = true;
        paintNow();
    }
    void wxCustomButton::mouseReleased(wxMouseEvent& event)
    {
        pressedDown = false;
    	Disable();
    	SetLabel(wxT("deaktiviert durch klick"));
    	paintNow();
    }
    void wxCustomButton::mouseLeftWindow(wxMouseEvent& event)
    {
        if (pressedDown)
        {
            pressedDown = false;
            paintNow();
        }
    }
    
    void wxCustomButton::mouseEnterWindow(wxMouseEvent& event)
    {
        pressedDown = true;
        paintNow();
    }
    
    // currently unused events
    void wxCustomButton::mouseMoved(wxMouseEvent& event) {}
    void wxCustomButton::mouseWheelMoved(wxMouseEvent& event) {}
    void wxCustomButton::rightClick(wxMouseEvent& event) {}
    void wxCustomButton::keyPressed(wxKeyEvent& event) {}
    void wxCustomButton::keyReleased(wxKeyEvent& event) {}
    

    test.png

    Ist es möglich den Button mit Transparenz und ohne Flicker'n darzustellen?

    Freue mich über jede Antwort 🙂
    Vielen Dank im Voraus 😉



  • kann mir keiner weiterhelfen? 😞


Anmelden zum Antworten