Using derived Class from CEdit in my DIalog - c++

I'm doing an application using MFC. I just made a class that is derived from CEdit so I could intercept OnChar() and do data validation. How do I substitute the edit control in my application with the derived one I made?

Do NOT use GetDlgItem!!
GetDlgItem() returns a CWnd-pointer and nothing else. This means you have a sliced CMyCustomEdit pointer. Sure, it works in all cases where your method sends a message to the underlying HWND. But that's just pure luck! You can read more about the problem here.
The right solution is to subclass your edit control using DDX_Control.

I found the solution. The reason why I was having such a hard time is because I didn't use the Class Wizard to create the new class, making things very complicated. If you simply use the Class Wizard, you have the option to add control variables to your derived classes like if they were regular classes, as long as the base class is the right class for your element. This is not necessary though. All you have to do is create a pointer of the type of your derived class and cast the item you are trying to get, like you would normally do with a non-derived class.
Example of accessing an Edit Control using a class derived from CEdit
CMyCustomEdit * editPtr = (CMyCustomEdit*)GetDlgItem(IDC_EDIT1);
As mentioned below by another member (Thanks for that), using GetDlgItem is not a good idea. I actually, in my code, ended up Sub-Classing it so I could use my new class with my Edit Controls that already existed. As mentioned before, I did not understand that an Edit Control was not necessarily attached to CEdit, so the example above should give a clear idea that your IDC_EDIT can be used as CMyCustomEdit as well as a CWnd and so on; it will behave naturally as long as you reference it with the right classes.
Now for the Sub-Classing. If you actually want to make you Edit Control to always call your derived class before your base class, you will have to make it a Sub Class. Don't think of it as an Object Oriented concept, this is only so the messages (Like WN_CHAR) will go through your derived class first and then call the base class.
Example of Sub-Classing CMyCustomEdit on an Edit Control:
First you need to include the .h file of your new class in the .cpp and .h of your dialog box. Those are the ones that usually has the same name as your project. Here it will be MyMainDialog.
#include "CMyCustomEdit.h"
In the derived dialog class include a variable of the type of your new derived class:
class MyMainDialog : public CDialogEx
{
protected:
CMyCustomEdit m_cmCEdit;
}
Then in the OnInitDialog() of your derived dialog class (MyMainDialog) Sub-Class your edit control. For safety, add this after the regular code in the function and before the return (As usual):
m_cmCEdit.SubclassDlgItem(IDC_EDIT1, this);
After this is done, when you do anything in your Edit Control with the ID IDC_EDIT1, the messages will go trough CMyCustomEdit before going to CEdit. This usually is necessary when you need to overwrite messages from the base classes.
Hope it helps anyone with a similar question.

Related

Variable types from inherited classes

If I have a class that inherits from a base class, can I use that base class as a variable type in c++?
class Component {
// Code here
};
class TransformComponent : public Component {
// Code here
};
class Entity {
// Code here
Component *getComponent(Component *searchComponent) {
// Code Here
}
};
as you can see here, I am using the base class "Component" as a return type and a variable type. The problem is that the user may input a "TransformComponent". The only reason I am asking this is because the "TransformComponent" class inherits from the "Component" class and there might be a way to do this?
<Entity>.getComponent(Component &TransformComponent());
The answer I'm looking for is one that works both for the return type, and the variable type.
Absolutely! It's one of the beauties of OOP. Your instanced class of type TransformComponent is both an instance of Component as well as TransformComponent.
If you had some function that returned a type of Component, this could return any class derived from Component as a Component! If you later wanted to refer to it as its sub-class, you might have to check its type and then cast to it, but what you want is absolutely possible, and you're going the right way about it.
In fact, in the example you describe, were you are using Component and the user might pass a TransformComponent, all of the base methods and properties that the Component possesses will be possessed by TransformComponent too. It will look and feel as if it was a Component, with all the benefits of being one.
The only time a problem will arise is if you specifically want to access the features of a TransformComponent, and the user passed a Component. The parent class doesn't know about the sub-class stuff, because it isn't an instance of one, it will throw up errors for you. Sub-classes build upon the base class, so they have all the base-class stuff, plus more. Basically its only an issue when your example is reversed.
Your Entity.getComponent() method suggests that it only cares that the provided argument is a Component ... not any specialization, such as TransformComponent, of that original class.
So, if you find yourself writing logic that actually cares that "this Component might actually be a TransformComponent," then "warning bells should be going off." Create method definitions within the class that are as specific as possible.

c++ base class object to call unknown methods in subclasses

I am facing this problem:
An upstream application defines a class (e.g. box), and a member (say property) with a base class type. I would make a derived class for that member, add new members and methods without updating their application.
Essentially I do box->property = make_shared<myProperty>(). Is there a way to keep the interface of calling the members and methods the same? That is, to access a property using box->property->length or box->property->GetWeight(), rather than dynamic_pointer_cast<myProperty>(box->property)->GetWeight(). The challenge here is they won't update the base property class, and I am not supposed to change box. But we wish to keep the interface the same so our customers won't complain.
Is it possible? If not, how could we do to best keep the main app and my plugin relatively independent while minimize the changes on the customer side? Any suggestions are welcome.
Looks to me like the derived class for that member property violates Liskov's substitution principle.
You mentioned not being able to modify the Box class.
But are you allowed to modify the property base class? I suggest you add your "additional" methods of your derived class to the property base class.
The intent here being that the interface between the base and derived class should be one and the same. So do this only if it makes sense design wise.

Need Of DECLARE_DYNAMIC?

DECLARE_DYNAMIC() is used for getting RTTI, when a class derived from CObject class, I know it.
But i saw in a code,a class derived from CPropertySheet have this MACRO.
-> what is the need of it, as neither iskindof() nor any other Run time information is used?
this derived class has two constructors , called via new when creating objects.
my question is What is the need of DECLARE_DYNAMIC() ,in this class ?
The use of this macro allows easy type checking in the MFC way. Assume you have a special CPropertyPage base class, Or you have a special derived CPropertySheet with a special interface named CMyClass you can easily do a cast with a type check with DYNAMIC_DOWNCAST.
So the fast answer is: If you want to use DYNAMIC_DOWNCAST or STATIC_DOWNCAST with the MFC type checking. It just allows the usage of IsKindOf.
It is the lowest form of the tripple DECLARE_DYNAMIC, DECLARE_DYNCREATE, DECLARE_SERIAL.
Also there are more answers on this here in stack overflow.

How to share code between two classes having same parent?

Although I am using MFC, I believe this is primarily a C++ question.
I have CResizingDialog derived from CDialog which is the base class for all my dialogs in the application. It gives them the ability to automatically (you guessed it) resize according to target screen size. CResizingDialog achieves this by overrides CDialog's several virtual functions including OnSize(), OnInitDialog(), OnPaint(). So far well and good.
Now I am adding a property sheet/page which also needs the same resizing functionality however I can't use CResizingDialog as base class for my property page. This means I will need a new base class say CResizingPage derived from CPropertyPage which will contain same functionality as CResizingDialog.
However the code that resizes the dialogs and its controls is exactly the same. Is there a way I can reuse the CResizingDialog somehow? I have never used multiple inheritance, will that help here?
I have 2 suggestions how to solve this, you'll have to decide which is easier/nicer for your situation.
If possible you can move the resizing code into a standalone function with the appropriate parameters that you can call from your 2 virtual functions.
The other way is to make the base class a template. Something like this:
template< typename Base >
CResizingBase
: public Base
{
// override the appropriate functions here
};
class CResizingDialog
: public CResizingBase< CDialog >
{
};
class CResizingPage
: public CResizingBase< CPropertyPage >
{
};

Porting Nuclues Grafix GUI to QT

I am trying to port/re-write GUI made using Nucleus Grafix to QT on Linux.In Nucleus code there is a control class which is the base class for the rest of the controls like Button,Editbox, radiobutton etc.This base class uses Nucleus API's and control structs to maximum.My question is whether to port/re-write the base class or make the control classes like Button to inherit from QPushButton.Which is better?
Oftentimes for a situation like this, it is easier to do dual-inheritence. It may not be the best long-term solution, but it will probably get you to your desired result the fastest. Remember that the QObject-derived class has to be the first one inherited from, and to avoid diamond inheritance with QObjects.