How can I access a dialog item in MFC from another class? - mfc

I'm trying to access a dialog item from a function that is not in the same class as the dialog class. How can I do that?
Example:
class AnotherClass : CClas
{
AnotherClass();
public:
void MyFunction();
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
I know I can use "this" if it is the same dialog item than the message, but I want to access another dialog item.
Thanks for your attention.
Solution:
As suggested by Moo-Juice, you can simply pass the dialog when you instantiate the class. In my case, I couldn't do that. For some reason subclassing didn't work that way. If you face the same issue when doing an application in MFC , you can create a pointer to a CDialog and pass it your main dialog at OnInitDialog():
Example (Class):
class AnotherClass : CClass
{
AnotherClass();
public:
void MyFunction();
CDialog * mainDialog;
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)mainDialog->GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
Example (OnInitDialog()):
MyMainDialog::OnInitDialog()
{
...
AnotherClass obj; //Instantiate class
obj->mainDialog = this;
return true;
}
In this example simply passing it as a parameter when creating the object makes more sense. It just didn't work with me for what I was doing.
Hope it helps anyone with a similar question.

When you instantiate AnotherClass, pass it the dialog class:
class AnotherClass
{
private:
CDialog& dialog_;
public:
AnotherClass(CDialog& dialog) : dialog_(dialog) { }
void MyFunction();
};
void AnotherClass::MyFunction()
{
CClass* temp = (CClass*)dialog_.GetDigItem(IDC_ID);
temp->doSOmething();
}

Related

Access child member methods from function taking parent class

A test function needs to take in any object of a class that is derived from Parent and access the Child implementation of Function(). To me, this would seem like something easy to do. I tried to do the following. it feels intuitively right, but it does not work. It still calls the Parent implementation of Function()
Class Parent
{
Public:
Parent();
~Parent();
virtual void Function() = 0;
};
Class Child : public Parent
{
Public:
Child();
~Child();
void Function(){
// Do something
};
};
void Test(Parent Object)
{
Object.Function();
};
int main()
{
Child Object;
Test(Child);
return 0;
}
How would one implement such a thing?
Am I missing something small? or is this solution far off what I am trying to achieve?
Thanks in advance.
To use virtual functions in C++ you must use a reference or a pointer. Try this
void Test(Parent& Object) // reference to Parent
{
Object.Function();
};
You should research object slicing to understand what goes wrong with your version, and why you must use a reference or a pointer.

How to make a vector with variables that have different template parameters?

I'm making a program were all the buttons need to be in a vector so I can easily call the render function for all of them with a for loop. I created a shortened down version of my problem. So the code below has the class called Button. When I create a Button variable I have to send the class containing the function I want to be called and the function pointer in the template. When I call the buttons Pressed function it will call the function I sent. When I call the buttons Render function it will render. I then have two different classes with functions that should be called when there corresponding button is pressed. I haven't used templates before so i'm not sure how I would put the buttons into a vector if the buttons have different template parameters so i cant write:
for (int i = 0; i < buttons.size(); i++) {
buttons[i].Render();
}
instead of:
button1.Render();
button2.Render();
button3.Render();
but...
Right so here is the code:
template<class CWF> //CWF = Class with Function
class Button {
public:
typedef void(CWF::*eventMethod)();
Button(CWF& cwf_, eventMethod method_) : method(method_), cwf(cwf_) {};
~Button() {}
void Pressed() {
(cwf.*(method))();
}
void Render() {};
private:
eventMethod method;
CWF& cwf;
};
Class1 class1;
Class2 class2;
Button<Class1> button1 = Button<Class1>(class1,&Class1::MyButtonWasPressed);
Button<Class2> button2 = Button<Class2>(class2, &Class2::MyButtonWasPressed);
int main() {
// loop here
button1.Render();
button2.Render();
//
//exiting herer
string line;
getline(cin, line);
return 0;
}
The best option in your example is to just remove the template altogether, and instead pass a std::function with your callback.
However, if your needs are complicated enough that that is not feasible, you would need to implement some form of type erasure. The most intuitive way would be to make your template class derive from some interface that provides the functions you need:
class AbstractButton {
public:
virtual void Pressed() = 0;
virtual void Render() const = 0;
};
template <typename CWF>
class Button : AbstractButton {
public:
// ...
void Pressed() override { /* ... */ }
void Render() const override { /* ... */ }
};
To use:
// store in vector
std::vector<std::unique_ptr<AbstractButton>> buttons;
buttons.push_back(std::unique_ptr<AbstractButton>(new Button<Class1>(/* ... */)));
// (or std::make_unique if you have C++14)
// use:
buttons[i]->Render();

Pass in and store function pointer to object

I'm writing a basic GUI framework as a school project and I'm trying to create an object (think a button) that, when interacted with, will call a particular function.
To explain my setup simply, I have a button class and a window manager class. The window manager is instantiated once from main and many buttons are instantiated from the window manager, with all 3 being in separate files. Nothing should go in main.
I'm a bit of a C++ noob, but as far as I can see, it would be best to use function pointers for this. My idea is to instantiate my button object then to pass it a function pointer to a function that when called would edit another object.
Firstly, I presume that the best way to do this would be to have the functions be defined locally to the window manager otherwise I'd have trouble with access? I had wanted to initially not have them listed in the header to make things easier (with a view to creating a kind of drag and drop editor in the future).
Second, how would I pass (from the window manager) a pointer to a function (which would exist within the window manager) to an instance of a button object? I thought I'd be able to treat it similarly to any other variable and do something as:
Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);
But, after looking through various tutorials I don't quite understand how I'd implement this. For example, how do I even define somewhere to store the function pointer in my button class?
Would appreciate any insight, I think I've confused myself enough for one day.
EDIT: Seems I should add that my Button and WindowManager classes are in separate files and my entry point so to speak is an instance of WindowManager. All the setup of my GUI including assigning a function to a button would be done in the constructor of WindowManager.
Here is one approach by using function pointers. However using std::function makes the code more flexible. For example you can use lambda expressions.
To use std::function you can simply change the typedef to typedef std::function<void(Button*)> EventCallback; and add the include #include <functional>
#include <iostream>
class Button
{
public:
// Typedef of the event function signature
typedef void(*EventCallback)(Button* button);
Button() : onClick(nullptr) {}
// Set the function to call
void SetOnClick(EventCallback func) { onClick = func; }
// Call the function if exists
void OnClick() {
if (onClick)
onClick(this);
}
private:
// This stores the function pointer for the button
EventCallback onClick;
};
// just some example function that has the same signature as Button::EventCallback
void MyEventFunc(Button* button)
{
std::cout << "Triggered" << std::endl;
}
int main() {
Button button;
button.SetOnClick(&MyEventFunc);
button.OnClick();
return 0;
}
http://ideone.com/x5O49B
You can do it with pointer to member function like this (in this case Button has to know WindowManager);
class WindowManager
{
public:
typedef void (WindowManager::* TypeOnClickFunc)( void );
void anyfunction( void ) {}
};
class Button
{
public:
Button( WindowManager * wm ) :_windowmanager( wm ) {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(_windowmanager->*_onclickfptr )( ); // indirect call WindowManager::anyfunction
}
private:
WindowManager *_windowmanager;
WindowManager::TypeOnClickFunc _onclickfptr;
};
WindowManager wm;
Button *btn1 = new Button( &wm );
btn1->SetOnClick( &WindowManager::anyfunction );
... or with pointer to static function like this ...
class WindowManager
{
public:
typedef void (*TypeOnClickFunc)( void );
static void anyfunction( void ) {}
};
class Button
{
public:
Button() {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call static WindowManager::anyfunction
}
private:
WindowManager::TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
... with typdef in Button instead of WindowManager ...
class WindowManager
{
public:
static void anyfunction( void ) {}
};
class Button
{
public:
typedef void (*TypeOnClickFunc)( void );
Button() {}
void SetOnClick( TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call
}
private:
TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );

where to declare object to use it (fltk)

I am having a problem accessing an object or its methods in fltk.
I have a Class named MyWindow which is a child class of Fl_Window.
so basically i would like to use an object which is either declared int the main or Mywindow in private section. My problem is that I can't use it that way. It only lets me to use the object if it is declared global. Can i somehow put it on the heap like this: Classname *pointer = new Classname(); ? IF i can where do I do that?
How would the callback function work if i need that object or its functions in the callback?
Should i use a pointer to it in the callback arguements?
lets say i want to click on the button and I need it to do something with the object and change a value.
lots of questions I know, I am really lost.
Can someone just point me to the right direction? Thank you! :)
Simple case for passing data to the GUI
class MyData
{
// The data model
};
class MyWindow: public FL_Window
{
MyData* m_data;
public:
void Data(MyData* data) { m_data = data; }
...
};
int main()
{
MyWindow gui;
MyData data;
// Tell the gui about the data
gui.Data(data);
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
For the callbacks, do it in two stages
class NeedingACallback
{
public:
void Setup()
{
...
FL_xxx* w = new FL_xxx(xpos, ypos, wid, hgt, name);
...
// v Pass the instance to the static
w->callback(_EventCB, this);
}
// The callback
static void _EventCB(FL_Widget* w, void* client)
{
// Convert the void* back to the instance
NeedingACallback* self = reinterpret_cast<NeedingACallback*>(client);
self->EventCB();
}
// Make life simple so you don't have to put self-> in front of
// all the instance data accessed
void EventCB()
{
// Callback for this instance of the class
}
};
EDIT It sounds like you're having multiple instances of data. An alternative technique is to have data as a reference. This must be done in the constructor. This way, m_data and the data in main both refer to the same area of memory.
class MyWindow: public FL_Window
{
MyData& m_data;
public:
MyWindow(int wid, int hgt, MyData& data, const char* title=0)
: FL_Window(wid,hgt,title)
, m_data(data)
{
...
}
};
int main()
{
MyData data;
MyWindow gui(100, 100, data, "Call me Mr");
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}

C++ an object with its own method?

I'm sorry, this is probably a stupid question. I am obviously misunderstanding something fundamental about object oriented programming. I am used to C and am now trying to use C++.
I have some buttons in a class called Button. Each button does something different. What I want to write is something like this:
Button button1;
Button button2;
...
void button1::onClick () {
...
}
void button2::onClick () {
...
}
But that does not work ("button 1 is not a class, namespace or enumeration" - yes I know!). I know I could just make a separate class for each button:
class button1_class : public Button {
public:
void onclick () {
...
}
} button1;
class button2_class : public Button {
...
}
But to me it 'feels' wrong to make a class when I know for sure it will only have one member.
I'm using Agui, a GUI library for Allegro 5.
EDIT
Thanks for the responses. While they are all helpful and (I think) all valid answers, nobody has actually said yet "no you cannot have an object with its own unique method because..."
So for example, if object1 is of type ObjectClass then object1 is not allowed to have a method (a member function) that is unique to object1, but rather possesses only the methods that are defined as part of ObjectClass. Is that right?
I'm sorry I did not include my actual use case. I was kind of more interested in just getting my head around OOP so that I can do it properly on my own.
EDIT2
Looking at the responses in more detail I suppose it is possible with lambda expressions, it's just not in the way I imagined it. Thanks again
The natural C++ way is to do as vsoftco explained, with virtuals and inheritance.
However, if your Button class has already everything needed, and the only thing that changes between the buttons is the unique (trhow-away) action to be performed, you may want to consider this alternative:
class Button {
function<void()> f;
public:
Button(function<void()> mf) : f(mf) {}
void onClick() { f(); }
};
This variant of your class uses a function object (think of it as a kind of function pointer but much more flexible to use).
You can then use it with lambda-functions as in this example:
int main(int ac, char**av)
{
Button button1([&]() { cout << "Hello 1!\n"; });
Button button2 ([]() { cout << "Hello 2!\n"; });
button1.onClick();
button2.onClick();
}
If the buttons have different functionalities, best thing to do is to create a BaseButton class in which you mark the onclick() as virtual (or make it pure virtual, which will make BaseButton an abstract class), then derive each other button from BaseButton, making sure to override onclick() in each derived class. You then need to use the buttons via a reference or pointer to a BaseButton, this way you achieve what is called "polymorphic behaviour".
For example:
class BaseButton
{
virtual void onclick() {/*implement here or declare pure virtual*/}
};
class RedButton: public BaseButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Red Buttons */}
};
class ShinyRedButton: public RedButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Shiny Red Buttons */}
};
then use it like (C++14 smart pointers)
std::unique_ptr<BaseButton> bb = new ShinyRedButton;
bb->onclick(); // will pick up the "right" ShinyRedButton::onclick()` function
You can do this in many ways.
Using a Button class where button objects have a pointer to methods that are invoked onClick. In C you would do this using a callback and you can also do it that way in C++:
class Button {
using funType = void(void);
public:
Button(funType* callback) : function(callback) { }
void onClick() { function(); }
private:
funType* function;
};
However do take note that function pointers are error prone, can't really be inlined by the compiler, and should generally be avoided. This method also works with capture-less lambdas.
Button red([] { std::cout << "Red button\n"; });
Button green(&green_button_function);
Creating different Button objects with different onClick methods on the fly. C++ has a mechanism to do this called templates:
template <class Fun>
class Button {
public:
Button(Fun f) : functor(f) { }
void onClick() { functor(); }
private:
Fun functor;
};
template <class Fun>
Button<Fun> make_button(Fun f) { return Button<Fun>(f); }
I am omitting details such as references on purpose here.
You could then use the Button class with callbacks as well as lambdas in the following way:
auto green = make_button([] { std::cout << "Green button pressed!\n"; });
auto red = make_button(&red_button_function);
You need to use auto with this method because otherwise you would have to specify the type of the functionality by hand, which is not possible e.g. for lambda objects.
Using polymorphism as shown by vsoftco, where you create separate classes for each Button functionality. Or you can make a ButtonAction abstract class to which Button has a reference. Then you implement different functionalities in different classes, but stay with one Button class. This is known as the strategy pattern:
class ButtonAction {
public:
virtual void onClick() = 0;
};
class Button {
public:
Button(std::unique_ptr<ButtonAction> action) :
action_(std::move(action)) {}
void onClick() { action_->onClick(); }
private:
std::unique_ptr<ButtonAction> action_;
};
class RedButtonAction : public ButtonAction {
void onClick() override { red(); }
};
class GreenButtonAction : public ButtonAction {
void onClick() override { green(); }
};
Using this method requires constructing Buttons from ButtonAction unique_ptrs
Button red(std::unique_ptr<ButtonAction>(new RedButtonAction));
Button green(std::unique_ptr<ButtonAction>(new GreenButtonAction));
You're right in that, if each button is fundamentally the same but needs different event handlers bound to it, implementing a new type for each one is not quite right.
Instead your Button type would have a member function that allows users to "attach" an event handler, and a member function to invoke it.
class Button
{
public:
Button()
: onClickHandler()
{}
void setOnClickHandler(std::function<void()> callback)
{
onClickHandler = callback;
}
friend class UI;
private:
void onClick()
{
onClickHandler();
}
std::function<void()> onClickHandler;
};
Then your user does:
void foo()
{
std::cout << "Some buttons do this!\n";
}
Button btn;
btn.setOnClickHandler(foo);
And your program's internals will set up things such that your window manager (above I've assumed that it's some class called UI) invokes btn.onClick() for you, which, since you "attached" foo, will end up invoking foo.
(In modern C++ you'd probably make use of lambda functions to tidy this up, but the above is a simple example to showcase the general design idea.)
In this way, you can attach different handlers to different Button instances, but the Button interface itself is stable.
This is similar to how, for example, you manipulate the DOM in JavaScript.
Using a std::function is the key here. You will have the virtual call overheard and potential memory allocation if your callable (lambda, function, member function) is large. This achieves your requirements of a single type executing different callbacks without defining an class inheritance. Also using uniform initialization makes it very convenient to construct Button class with a lambda without manually creating a constructor.
Live example:
http://coliru.stacked-crooked.com/a/f9007c3f103f3ffe
#include <functional>
#include <vector>
using namespace std;
struct Button
{
function<void()> OnClick;
};
int main()
{
vector<Button> buttons =
{
{[] { printf("Button0::OnClick()\n"); }},
{[] { printf("Button1::OnClick()\n"); }},
{[] { printf("Button2::OnClick()\n"); }},
};
for(auto&& button : buttons)
button.OnClick();
}
Your Agui library supports a signaling system, with the member function addActionListener.
This allows you to derive a class from agui::ActionListener to perform the specific task intended for one or more buttons:
class SimpleActionListener : public agui::ActionListener
{
public:
virtual void actionPerformed(const agui::ActionEvent &evt)
{
std::cout << "Button pushed" << std::endl;
}
};
The object above can be attached to a button's "press" action with:
SimpleActionListener simpleAL;
button1.addActionListener(&simpleAL);