I recently discovered the power of lambda expressions and how they can be utilized with wxWidgets (
http://wxwidgets.blogspot.com/2013/08/wxwidgets-and-c-11.html). I can't begin to explain the versatility of lambda expressions as well as some people have (
http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11), but using them can greatly simplify the coding process as I hope to demonstrate with my take on the wxWidgets/SFML tutorial (
http://sfml-dev.org/tutorials/1.6/graphics-wxwidgets.php).
In this sample, I have demonstrated using the Bind() method to handle events that use lambda functions as callbacks. I have also demonstrated that a parent's Bind() method handling one event may be "overriden" in a child's Bind() method; finally, I have demonstrated that a child's "overriden" Bind() may Skip() back to the parent's Bind() handling to take advantage of its implementation.
Comments, critique, and discussion is welcome.
wxIMPLEMENT_APP_CONSOLE(MyApp);
class wxsfControl
: public wxControl
, public sf::RenderWindow
{
public:
wxsfControl(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0L)
: wxControl (parent, id, pos, size, style) // initialize wxControl first...
, sf::RenderWindow (this->GetHandle()) // ...before initializing sf::RenderWindow with wxControl::GetHandle()
, _color (sf::Color::Black)
{
// handle idle event, aka OnIdle()
Bind(wxEVT_IDLE, [=](wxIdleEvent&) {
Refresh(); // wxWindow::Refresh()
} );
// handle paint event, aka OnPaint()
Bind(wxEVT_PAINT, [=](wxPaintEvent&) {
wxPaintDC dc(this);
update(); // wxsfControl::update()
display(); // sf::RenderWindow::display()
} );
// handle erase background event, aka OnEraseBackground()
Bind(wxEVT_ERASE_BACKGROUND, [=](wxEraseEvent&) {
// catch erase event to prevent flickering but do nothing or do something particular that needs to be done at this event
} );
// handle enter window event, aka OnEnterWindow()
Bind(wxEVT_ENTER_WINDOW, [=](wxMouseEvent&) {
std::cout << "wxsfControl handled mouse event: enter window." << std::endl;
} );
// handle leave window event, aka OnLeaveWindow()
Bind(wxEVT_LEAVE_WINDOW, [=](wxMouseEvent&) {
std::cout << "wxsfControl handled mouse event: leave window." << std::endl;
} );
// handle mouse motion event, aka OnMouseMotion()
Bind(wxEVT_MOTION, [=](wxMouseEvent& e) {
wxPoint mouse = e.GetPosition();
std::cout << "wxsfControl handled mouse event: motion (x: " << mouse.x << " , y: " << mouse.y << ")." << std::endl;
} );
// handle mouse left down, aka OnLeftDown()
Bind(wxEVT_LEFT_DOWN, [=](wxMouseEvent&) {
_color = sf::Color::Red;
std::cout << "wxsfControl handled mouse event: left down." << std::endl;
} );
// handle mouse right down, aka OnRightDown()
Bind(wxEVT_RIGHT_DOWN, [=](wxMouseEvent&) {
_color = sf::Color::Blue;
std::cout << "wxsfControl handled mouse event: right down." << std::endl;
} );
std::cout << "wxsfControl constructed..." << std::endl;
}
~wxsfControl() { std::cout << "...wxsfControl destructed." << std::endl; }
protected:
private:
virtual void update() { clear(_color); }
sf::Color _color;
};
class MyControl
: public wxsfControl
{
public:
MyControl(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0L)
: wxsfControl(parent, id, pos, size, style)
{
// handle mouse left down, similar to overriding a virtual method, such as OnLeftDown()
Bind(wxEVT_LEFT_DOWN, [=](wxMouseEvent& e) {
std::cout << "MyControl handled mouse event: left down." << std::endl;
e.Skip(); // give parent class, wxsfControl, a chance to handle this overriden event
} );
}
protected:
private:
// override virtual wxsfControl::update() with special implementation here
};