Simplest Form Of Creating Your Own wxButton
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Simplest Form Of Creating Your Own wxButton
I would like to create my own wxButton (mostly so I can control the background color when the user clicks).
I have never created my own controls before. Can someone show me the simplest form of how to do this to get me started?
Thanks in advance
I have never created my own controls before. Can someone show me the simplest form of how to do this to get me started?
Thanks in advance
- xaviou
- Super wx Problem Solver
- Posts: 437
- Joined: Mon Aug 21, 2006 3:18 pm
- Location: Annecy - France
- Contact:
Re: Simplest Form Of Creating Your Own wxButton
If this is juste for buttons, you can have a look ad the "render" sample, witch does exactly this.
Regards
Xav'
Regards
Xav'
My wxWidgets stuff web page : X@v's wxStuff
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Re: Simplest Form Of Creating Your Own wxButton
Thank you for the example. I have been trying to get this working.doublemax wrote:https://wiki.wxwidgets.org/Painting_your_custom_control
Here is what I did. Created a class called wxCustomButton
//wxCustomButton.h
Code: Select all
#ifndef WXCUSTOMBUTTON_H
#define WXCUSTOMBUTTON_H
#include <wx/wx.h>
#include <wx/sizer.h>
class wxCustomButton : public wxWindow
{
bool pressedDown;
wxString text;
static const int buttonWidth = 200;
static const int buttonHeight = 50;
public:
wxCustomButton(wxFrame* parent, wxString text);
void paintEvent(wxPaintEvent & evt);
void paintNow();
void render(wxDC& dc);
// 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 keyPressed(wxKeyEvent& event);
void keyReleased(wxKeyEvent& event);
DECLARE_EVENT_TABLE()
};
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_KEY_DOWN(wxCustomButton::keyPressed)
EVT_KEY_UP(wxCustomButton::keyReleased)
EVT_MOUSEWHEEL(wxCustomButton::mouseWheelMoved)
// catch paint events
EVT_PAINT(wxCustomButton::paintEvent)
END_EVENT_TABLE()
wxCustomButton::wxCustomButton(wxFrame* parent, wxString text) :
wxWindow(parent, wxID_ANY)
{
SetMinSize( wxSize(buttonWidth, buttonHeight) );
this->text = text;
pressedDown = false;
}
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
void wxCustomButton::paintEvent(wxPaintEvent & evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Alternatively, you can use a clientDC to paint on the panel
* at any time. Using this generally does not free you from
* catching paint events, since it is possible that e.g. the window
* manager throws away your drawing when the window comes to the
* background, and expects you will redraw it when the window comes
* back (by sending a paint event).
*/
void wxCustomButton::paintNow()
{
// depending on your system you may need to look at double-buffered dcs
wxClientDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void wxCustomButton::render(wxDC& dc)
{
if (pressedDown)
dc.SetBrush( *wxRED_BRUSH );
else
dc.SetBrush( *wxGREY_BRUSH );
dc.DrawRectangle( 0, 0, buttonWidth, buttonHeight );
dc.DrawText( text, 20, 15 );
}
void wxCustomButton::mouseDown(wxMouseEvent& event)
{
pressedDown = true;
paintNow();
}
void wxCustomButton::mouseReleased(wxMouseEvent& event)
{
pressedDown = false;
paintNow();
wxMessageBox( wxT("You pressed a custom button") );
}
void wxCustomButton::mouseLeftWindow(wxMouseEvent& event)
{
if (pressedDown)
{
pressedDown = false;
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) {}
#endif // WXCUSTOMBUTTON_H
As soon as I add a include to
Code: Select all
#include <wxCustomButton.h>
Code: Select all
I get "/usr/include/wx-3.0/wx/event.h|3988|error: ‘const wxEventTable wxWindowBase::sm_eventTable’ is protected|"
Re: Simplest Form Of Creating Your Own wxButton
This seems to be an error in the wiki entry.
The base class (wxWindow vs wxPanel) must be the same.
Code: Select all
class wxCustomButton : public wxWindow
Code: Select all
BEGIN_EVENT_TABLE(wxCustomButton, wxPanel)
Use the source, Luke!
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Re: Simplest Form Of Creating Your Own wxButton
Thank you for the help!!!
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Re: Simplest Form Of Creating Your Own wxButton
How do I set the size of the control? This code draws the entire window green, I was thinking that it should only draw a small square slightly bigger then the button itself.
// main form.cpp
// wxCustomButton.h
// main form.cpp
Code: Select all
void MainDialog::OnInit(wxInitDialogEvent& event)
{
wxCustomButton* m_Button1;
m_Button1 = new wxCustomButton(this, "my button");
}
// wxCustomButton.h
Code: Select all
void wxCustomButton::render(wxDC& dc)
{
dc.SetBackground(*wxGREEN_BRUSH); // this paints the entire main/parent form green
if (m_bPressedDown)
{
dc.Clear();
dc.SetBrush( *wxRED_BRUSH );
dc.DrawRectangle(0, 0, m_iButtonWidth, m_iButtonHeight);
dc.DrawText(m_sButtonText, 0, 0);
}
else
{
dc.SetBrush( *wxGREY_BRUSH );
dc.DrawRectangle(0, 0, m_iButtonWidth, m_iButtonHeight);
dc.DrawText(m_sButtonText, 0, 0);
}
}
Re: Simplest Form Of Creating Your Own wxButton
If a control is the only child of a wxTopLevelWindow (like wxDialog or wxFrame) it will get stretched to fill the whole client area. Use a wxPanel as parent for the control.
It's not a good idea to store the button size in your own variables. Use the "real" size returned from GetSize() or GetClientSize().
Code: Select all
void MainDialog::OnInit(wxInitDialogEvent& event)
{
wxPanel *panel = new wxPanel(this, wxID_ANY);
// warning: shadowing of member variable if there is one
wxCustomButton* m_Button1 = new wxCustomButton(panel, "my button", wxPoint(10,10), wxSize(80,20));
}
Code: Select all
dc.DrawRectangle(0, 0, m_iButtonWidth, m_iButtonHeight);
Use the source, Luke!
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Re: Simplest Form Of Creating Your Own wxButton
Sorry to keep bothering, but I am actually quite lost here.
I can understand passing in the size of the button (because you need to draw it) but doesnt the top and left positions need to be managed by the container/parent object? In other words, shouldnt the canvas be the same size as the button and no bigger?
If I add one control then it takes up the entire window (like you said)
If I add two controls to the main window or a panel then it draws only a few pixels (25,25) estimated. I will continue to debug it.
I do apologize for the noob question, I am just trying to learn how to make my own controls.
I can understand passing in the size of the button (because you need to draw it) but doesnt the top and left positions need to be managed by the container/parent object? In other words, shouldnt the canvas be the same size as the button and no bigger?
If I add one control then it takes up the entire window (like you said)
If I add two controls to the main window or a panel then it draws only a few pixels (25,25) estimated. I will continue to debug it.
I do apologize for the noob question, I am just trying to learn how to make my own controls.
Re: Simplest Form Of Creating Your Own wxButton
I'm not sure what you're not understanding.
I only passed the wxPoint(10,10) as an example. If you put the control into a sizer, you can indeed just pass wxDefaultSize. However, if you wouldn't use sizers, you could position each control manually this way.I can understand passing in the size of the button (because you need to draw it) but doesnt the top and left positions need to be managed by the container/parent object?
The canvas *is* the button. But even if you intend to use it with a fixed size, it's good practice to assume it could have any size in your drawing code. Especially if you put it into a sizer.In other words, shouldnt the canvas be the same size as the button and no bigger?
Use the source, Luke!
-
- Earned some good credits
- Posts: 125
- Joined: Wed Oct 28, 2015 9:48 pm
Re: Simplest Form Of Creating Your Own wxButton
It seems to be clipping the drawing when I add it to a wxPanel and I cannot figure out why. This is the simplest version of the code I could come up with.
// CustomButton.h
// main.cpp
The code above gives me this
// if I add it to the main window it draws correctly.
why does it not draw the whole rectangle when it is added to a wxPanel?
// CustomButton.h
Code: Select all
#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
#include <wx/wx.h>
#include <wx/sizer.h>
using namespace std;
class CustomButton : public wxWindow
{
public:
CustomButton(wxWindow* parent, string sButtonText);
void paintEvent(wxPaintEvent & evt);
void paintNow();
void render(wxDC& dc);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(CustomButton, wxWindow)
// catch paint events
EVT_PAINT(CustomButton::paintEvent)
END_EVENT_TABLE()
CustomButton::CustomButton(wxWindow* parent, string sButtonText): wxWindow(parent, wxID_ANY)
{
}
void CustomButton::paintEvent(wxPaintEvent & evt)
{
wxPaintDC dc(this);
render(dc);
}
void CustomButton::paintNow()
{
wxClientDC dc(this);
render(dc);
}
void CustomButton::render(wxDC& dc)
{
dc.SetBackground(*wxGREEN_BRUSH);
dc.DrawRectangle(0, 0, 30, 50);
}
#endif // CUSTOMBUTTON_H
// main.cpp
Code: Select all
wxPanel *panel = new wxPanel(this, wxID_ANY);
panel->SetSize(500,500);
CustomButton* btn = new CustomButton(panel, "test");
// if I add it to the main window it draws correctly.
Code: Select all
CustomButton* btn = new CustomButton(this, "test");
why does it not draw the whole rectangle when it is added to a wxPanel?
Re: Simplest Form Of Creating Your Own wxButton
You're not setting the size of the button anywhere.
Use the source, Luke!