Im trying to create a simple windows api.
I need a little help in setting a function pointer in side class
Im getting errors trying to set the function to a function that is inside a class, Is there anyway this can be done without using static in the class?
class Window
{
public:
WIN_API Window();
struct WIN_API
{
bool(*OnMouseClick)(Vector2D position, MouseButton button);
bool(*OnCreate)();
}Event;
};
class MainWindow : public Window
{
public:
MainWindow() : Window()
{
//error here
this->Event.OnCreate = OnCreate;
this->Event.OnMouseClick = OnMouseClick;
}
bool OnCreate()
{
return true;
}
bool OnMouseClick(Vector2D position, MouseButton button)
{
return true;
}
};
You have to bind the member function of a particular instance. This is best done using a lambda and std::function objects.
class Window
{
public:
Window();
struct WIN_API
{
std::function<bool(Vector2D, MouseButton)> OnMouseClick;
std::function<bool()> OnCreate;
} Event;
};
class MainWindow : public Window
{
public:
MainWindow()
{
this->Event.OnCreate =
[this] () { return this->OnCreate(); };
this->Event.OnMouseClick =
[this] (Vector2D position, MouseButton button)
{ return this->OnMouseClick(position, button); };
}
bool OnCreate()
{
return true;
}
bool OnMouseClick(Vector2D position, MouseButton button)
{
return true;
}
};
Related
I am writing an Arduino program where LEDs and a bunch of other electronics are controlled by different buttons. To simplify the code, I am using the Observer Mode:
class Observer observes EventThrowers, who performs check() every frame and notifies Observers if necessary. The code definition for Observer and EventThrower looks like this:
class Observer {
public:
virtual void handleEvent(int label, bool state) = 0; // Virtual method called by EventThrowers.
};
class EventThrower {
private:
std::vector<Observer *> observer_list;
protected:
void notifyObservers(int label, bool state) {
for (Observer *observer : observer_list) {
observer->handleEvent(label, state);
}
}
public:
virtual void check() = 0; // Virtual method used in loop() for frame checking.
void addObserver(Observer *_observer) {
this->observer_list.push_back(_observer);
}
};
And my LEDCtrl class (an Observer) and ButtonClick class (an EventThrower) definitions are:
class LEDCtrl : public Observer {
public:
// properties
LEDCtrl(int _led_pin) { ... } // constructor
void handleEvent(int label, bool state) { ... } // overridden handleEvent method
private:
void toggleLight(bool new_status) { ... } // assistant method
};
class ButtonClick : public EventThrower {
public:
// properties
ButtonClick(int _button_pin, int _default, int _label) { ... } // constructor
void check() { ... } // overridden check() that is called every frame to check the status of the button and choose to notify Observers or not
};
My initialization of a LEDCtrl-ButtonClick instance pair looks like:
ButtonClick *buttonClick1 = new ButtonClick(BUTTON1, 0, 0);
LEDCtrl *ledCtrl1 = new LEDCtrl(LED1);
buttonClick1->addObserver(ledCtrl1);
However, the above code throws this compile error:
error: 'buttonClick1' does not name a type
buttonClick1->addObserver(ledCtrl1);
^~~~~~~~~~~~
How can I fix this?
I have a parent class Window
class Window
{
public:
Window(int x, int y);
virtual void Display();
virtual ~Window();
}
and a base class Console
class Console : public Window
{
public:
Console(int x, int y);
virtual void Display();
virtual ~Console();
}
I store the results in a manager class with the following signature:
class WindowManager
{
public:
WindowManager() {};
void AddWindow(int x, int y)
{
m_Windows.emplace(nle::WindowType::RenderWindow, std::make_unique<nle::Window>(x,y))
}
void AddConsole(int x, int y)
{
m_Windows.emplace(nle::WindowType::ConsoleWindow, std::make_unique<nle::Console>(x,y));
}
nle::Window* GetRenderWindow()
{
return m_Windows[nle::WindowType::RenderWindow].get();
}
nle::Window* GetConsoleWindow()
{
return m_Windows[nle::WindowType::ConsoleWindow].get();
}
private:
std::unordered_map<WindowType, std::unique_ptr<nle::Window>> m_Windows;
};
When calling the Get___Window functions the base class is always called, I tried returning a reference to the windows instead of a pointer but the base class is still called, I've seen references of others doing a for ranged loop to directly access the container:
for(const window& : m_Windows)
{
window->Display();
}
This would work, but i would like to avoid using direct access to my manager.
An example of this code is:
static WindowManager m_WindowManager; // static purely for simplicity to avoid using a class for SO
int main()
{
InitResources();
while(1)
{
DisplayWindow();
}
return 1;
}
void InitResources()
{
m_WindowManager.AddConsoleWindow(1080, 720);
}
void DisplayWindow()
{
m_WindowManager.GetConsoleWindow()->Display(); // Base class is called
}
I'm trying to create a simple events system, which will have many different events. So, I've tried to create an event class which allows you to register functions, taking the correct type of event, and returning a boolean.
What I want is that the method post in any subclass of Event will take that subclass rather than Event, and the functions in the list listeners in each subclass should take the correct subclass type. Here's the code I already have, which forces the function to cast to the correct event type:
events.h:
namespace events {
class Event {
public:
static const std::List<bool (*)(Event)> listeners;
void post(Event event);
}
class ExampleEvent : Event {
int eventData;
}
}
events.cpp:
namespace events {
void Event::post(Event event) {
for(int i = 0; i < listeners.size(); i++) {
if(listeners[i](event)) return;
}
}
}
Is there some way I can get this to work with subclassed events without having to do the following?
bool handleExample(Event event) {
ExampleEvent exampleEvent = (ExampleEvent)event;
std::cout << exampleEvent.eventData << std::endl;
return false;
}
// Somewhere else in the code
ExampleEvent::listeners.push_back(&handleExample);
I apologise for any incorrect code, I don't quite have the rules of the language perfect yet.
The common way is to use CRTP:
namespace events {
template<typename Derived>
class Event {
public:
static const std::list<bool (*)(Derived)> listeners;
void post(Derived event)
{
static_cast<Derived&>(*this).post(event);
}
};
class ExampleEvent : Event<ExampleEvent> {
int eventData;
void post(ExampleEvent event)
{
//implement post
}
};
}
Just use virtual functions:
namespace events {
class EventHandler {
public:
static const std::list<Event*> listeners;
void post() {
for (Event * listener : listeners) {
if (listener->post()) break;
}
}
};
class BaseEvent {
public:
virtual bool post() = 0;
virtual ~BaseEvent() {}
};
class ExampleEvent : public BaseEvent { // use public inheritance
int eventData;
public:
virtual bool post() override {
if (eventData == 0) return true;
return false;
}
};
}
I have this class
typedef void(*callback)();
class Button : public Control
{
private:
callback onClickCallback;
public:
void bind(callback func)
{
onClickCallback = func;
}
void onClick()
{
onClickCallback();
}
};
Button inherits Control which is mapped as a component in the Gui class.
The Gui class has a method which will call the onClick method of every component on the list. The onClick method callback is lambda expression
Gui gui;
gui.addControl<Button>(x, y, width, height).bind([] {
MessageBox(NULL, "OK", "OK", 0);
//How to capture gui
//Eg add another button on click:
//gui.addControl<Button>(x, y, width, height);
});
Here is the gui class
class Gui
{
private:
int index;
std::unordered_multimap<int, Control*> controls;
public:
template <typename T, typename ...Args>
T& addControl(Args... args)
{
auto control = new T{ std::forward<Args>(args)... };
std::pair<int, Control*> pair(index, control);
controls.insert(pair);
index++;
return *control;
}
void processMessages()
{
for (auto it = controls.begin(); it != controls.end(); ++it)
{
it->second->onClick();
}
}
};
I actually did it, i don't know if this is the right solution but it seems to work.
Updated the Button class.
class Button : public Control
{
private:
std::function<void()> onClickCallback;
public:
//Override
void bind(std::function<void()> func)
{
onClickCallback = func;
}
//Override
void onClick()
{
onClickCallback();
}
};
It works now !
Also added support for different events eg mouse_click, on_focus_gained etc...
gui.addControl<Button>(hWnd, "Button", 3, 26, 70, 23).bind("mouse_click", [&] {
gui.getControl<Button>(0).setText("Clicked");
});
I'm not very experienced in cpp (used to work in python).
I have the following problem:
1) I have a main class A (a window) and the methods m_A1 and m_A2
2) I have a little class B (a dialog) with a callback m_B1
3) the class B is instantiated and destroyed inside of m_A1
4) from the callback m_B1 I need to call m_A2
I tried to give to B reference to the instance of A (with 'this') but this solution that worked in python here doesn't.
I tried to declare the class B inside of A to have the methods of A accessible inside of B but I can't understand how to write the code of the methods of B, writing for example the class constructor of B would be
A::B::A::B() but gives syntax errors.
Here's some code:
class Centrino
{
public:
Centrino();
virtual ~Centrino();
Gtk::Window *mp_window;
protected:
...
bool on_window_key_press(GdkEventKey *event);
void io_process_incoming_command(char *in_str_complete);
...
};
class DebugDialog : public Gtk::Dialog
{
public:
DebugDialog(const char *title, Gtk::Window& parent, bool modal);
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
};
void Centrino::io_process_incoming_command(char *in_str_complete)
{
...
}
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog("Debug Dialog", *mp_window, true);
int response = dialog.run();
}
}
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
io_process_incoming_command(entry_content.c_str());
}
Centrino is the class that I called A, DebugDialog is the class that I called B.
From DebugDialog:: on_button_send_clicked() I need to call Centrino:: io_process_incoming_command().
The scope of the class DebugDialog instance is inside of Centrino:: on_window_key_press().
Can anybody point me to an example? Thanks in advance.
Add a Centrino reference in DebugDialog attributes and provide it in DebugDialog contructor. Declare Centrino::io_process_incoming_command() method public and invoke it from DebugDialog::on_button_send_clicked() method:
class Centrino
{
public:
Centrino();
virtual ~Centrino();
Gtk::Window *mp_window;
void io_process_incoming_command(char *in_str_complete);
protected:
...
bool on_window_key_press(GdkEventKey *event);
...
};
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog("Debug Dialog", *mp_window, true, *this);
int response = dialog.run();
}
}
...
}
class DebugDialog : public Gtk::Dialog
{
public:
DebugDialog(const char *title, Gtk::Window& parent, bool modal, Centrino ¢rino);
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
Centrino ¢rino_;
};
DebugDialog::DebugDialog(const char *title, Gtk::Window& parent, bool modal, Centrino ¢rino) :
....
centrino_(centrino)
{
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
centrino_.io_process_incoming_command(entry_content.c_str());
}
The scope of DebugDialog is global, and as written, DebugDialog has
no knowledge of the context in which it was created. You need to pass
and save this information explicitly:
class DebugDialog : public Gtk::Dialog
{
Centrino* myOwner;
public:
DebugDialog( Centrino* owner, const char *title, Gtk::Window& parent, bool modal );
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
};
DebugDialog::DebugDialog( Centrino* owner... )
: myOwner( owner )
, ...
void Centrino::io_process_incoming_command(char *in_str_complete)
{
...
}
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog(this, "Debug Dialog", *mp_window, true);
int response = dialog.run();
}
}
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
myOwner->io_process_incoming_command(entry_content.c_str());
}