how to inherit dialogs correctly in MFC - c++

I am building a 3d painter in C++ with OpenGL and MFC.
I created dialogs for creating every shape that i have: like cube, cylinder and etc...
My cube class inherits the cylinder class with the difference of amount of stack and slices only.
Hence the CreateCylinder dialog should look the same as the CreateCube dialog.
I was able to inherit it fine, but i have an error that says:
Error 6 error C2065: 'IDD_BASEWIN_DIALOG' : undeclared identifier c:\users\l122\desktop\opengl\opengl\basewindlg.h 19 1 OpenGL
This happens every new compilation after some minor code changes.
To fix it, i comment this line:
enum { IDD = IDD_BASEWIN_DIALOG };
then compile and uncomment the same line, which helps in the next compilation to work fine.
That how i inherited the CreateCylinder dialog class in my CreateCube dialog class:
IMPLEMENT_DYNAMIC(CreateCube, CreateCylinder)
CreateCube::CreateCube()
: CreateCylinder(this->GetSafeOwner())
{
}
CreateCube::~CreateCube()
{
}
void CreateCube::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
CreateCylinder::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CreateCube, CreateCylinder)
END_MESSAGE_MAP()
and i also edited this line in the CreateCylinder constructor:
CreateCylinder::CreateCylinder(CWnd* pParent /*=NULL*/)
: CDialogEx(CreateCylinder::IDD, this->GetSafeOwner())
The header file:
#pragma once
#include "CreateCylinder.h"
// CreateCube dialog
class CreateCube : public CreateCylinder
{
DECLARE_DYNAMIC(CreateCube)
public:
CreateCube(); // standard constructor
virtual ~CreateCube();
// Dialog Data
enum { IDD = IDD_CREATE_CUBE_DLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
};
I want to know what have i done wrong with the inheritance. is it necessary to send parent's pointer to the base dialog as i did?
And is the error above has to do anything with it?

The problem here is the scope of the enum symbol IDD_CREATE_CUBE_DLG. When you inherit a class, you don't inherit it's "symbol scope", you merely inherit its "members namespace". I'm sure some language lawyer can give a more precise (technically correct) explanation. But, a simple explanation is that you don't inherit symbol - thus enum - definitions. You should be able to access them even if they are in protected scope, though.
So, assuming that IDD_CREATE_CUBE_DLG is used in CreateCylinder class to set "its" IDD, then, instead of:
enum { IDD = IDD_CREATE_CUBE_DLG };
you should write:
enum { IDD = CreateCylinder::IDD };
I think that the correct wording would be to say that you need the "fully qualified" name here.
This is actually a good thing, and some class libraries use it to play tricks, like enumerating messages supported by a class, and such - see, for example, the FOX (widget) toolkit library.
UPDATE:
If you change your declaration as is updated here, thus avoiding the use of IDD_CREATE_CUBE_DLG, it's probable that you won't have problems with IDD_CREATE_CUBE_DLG any more. But, if you still do, the problem would be that IDD_CREATE_CUBE_DLG, since it's declared in Resource.h, then, at the time it was used (which is the line for which the error is reported), the Resource.h wasn't (properly) included. So, check what is the .cpp file that is compiled when your error is reported. Then check the includes in that file. You should clean them up, but, for starters, you may "just" #include "Resource.h" at the top (of the .h file).
As for the constructor of CDialogEx, just pass the parameter along, like this:
CreateCylinder::CreateCylinder(CWnd* pParent)
: CDialogEx(CreateCylinder::IDD, pParent)

Actually adding resource.h to my base dialog header solved the problem. I just can't understand how it worked flawlessly, before i have added the inherited classes. In both cases this header file wasn't included, so how did it work in a first place?

Related

"Using" is not solving the "hides virtual function" warning

I have been googling high and low and can't find a solution that will remove the warning, even when I use the using directive.
class TShowException_Form : public TForm {
__published: // IDE-managed Components
TButton *Send_Button;
TButton *Cancel_Button;
TLabel *Message_Label;
private: // User declarations
using TCustomForm::ShowModal;
//using TForm::ShowModal;
public: // User declarations
__fastcall TShowException_Form(TComponent* Owner);
int __fastcall ShowModal(System::Sysutils::Exception *E);
};
I want to hide the original virtual int __fastcall ShowModal(void) and expose a new one taking an Exception parameter.
But it still complaints on "hides virtual function":
[bcc32 Warning] TShowExceptionForm.h(32): '_fastcall TShowException_Form::ShowModal(Exception *)' hides virtual function '_fastcall TCustomForm::ShowModal()'
I have also tried using TForm::ShowModal; but with the same result.
Any ideas of how to solve this warning?
EDIT
I found out that it works perfectly well if I override the show() method instead:
class TShowException_Form : public TForm {
__published: // IDE-managed Components
TButton *Send_Button;
TButton *Cancel_Button;
TLabel *Message_Label;
private: // User declarations
using TForm::ShowModal;
using TForm::Show;
public: // User declarations
__fastcall TShowException_Form(TComponent* Owner);
int __fastcall Show(System::Sysutils::Exception *E);
};
So why isn't it working with ShowModal()?
bcc32 is, in many respects, not very compliant with the C++ standard. Whenever I find myself asking, "Why does this technique that I think should work in C++ not work in bcc32?", I usually assume it's yet another compiler bug.
The fact that Show works while ShowModal doesn't is interesting. Looking at Vcl.Forms.hpp shows the difference: Show is defined with HIDESBASE (a macro that expands to __declspec(hidesbase)).
Adding HIDESBASE to your ShowModal should work as well. You may also have to declare a virtual destructor, if you don't already have one, due to bcc32 compiler weirdness.
virtual __Fastcall ~TShowException_Form() {}
You must declare overloaded version as virtual too:
virtual int __fastcall ShowModal(System::SysUtils::Exception * E);
Does not know if C++Builder supports C++11, but if it does, try also to delete overload which you want to hide:
virtual int __fastcall ShowModal() = delete;
instead of placing it into private section.
You get the warning because what you are trying to do happens very often by mistake and is a serious and very hard to find bug if it is done by mistake. Maybe you should use a different name.

send reference qplaintextedit to C++ constructor class

I need to send reference a QPlainTextEdit to my C++ class Analizador for add lines to QPlainTextEdit from my class. I add the include <QPlainTextEdit> to the class, create the QPlainTextEdit from the graphic interface and call the constructor function just like that
Analizador *anal=new Analizador(ui->textProgres);
the constructor function is:
Analizador(QPlainTextEdit* text);
the compiler throw the error :
mainwindow.cpp:23: error: undefined reference to
`Analizador::Analizador(QPlainTextEdit*)'
so I guess the error is because I'm not sending a pointer to the constructor function but I don't know how to access the pointers of QPlainTextEdit
PS. I'm new in Qt and C++
In this case, compiler complains that it cannot find the definition of Analizador constructor when it tries to link your application.
Make sure you have written the definition of Analizador::Analizador(QPlainTextEdit*) constructor.
If you have written the constructor but still you gets this issue, The cpp file where your constructor exists may not have got compiled. If you are using QtCreator, try Build -> Run QMake and then Build -> Rebuild All
You can try this workaround.
#ifndef ANALIZADOR_H
#define ANALIZADOR_H
#include <QPlainTextEdit>
class Analizador
{
public:
Analizador(QPlainTextEdit *text)
{
plainTextEdit = text;
}
void addLines(QString line)
{
plainTextEdit->appendPlainText(line);
}
private:
QPlainTextEdit *plainTextEdit;
};
#endif // ANALIZADOR_H
And use this class like this.
analizador = new Analizador(ui->plainTextEdit);
analizador->addLines("Hello");
analizador->addLines("World");

OOP with resource and header declaration: invalid keyword

I am creating a project that uses a dll resource named GUI.dll for its dialogs.
At first, when I had everything in the .cpp except a few lines (that were in the header), the GUI.cpp looked like
class AuswertungsGUI : public Dialog
{
public:
AuswertungsGUI() : Dialog(DA_Window, "GUI")
{
InitMsgMap();
}
that worked. But now I've split everything up into a header GUI.h with the class declaration and the GUI.cpp with the implementation. I obviously don't know how to create the appropriate dialog out off the resource:
GUI.h:
#ifndef AUSWERTUNGSGUI_H
#define AUSWERTUNGSGUI_H
#include <Origin.h>
class AuswertungsGUI:public Dialog
{
public:
AuswertungsGUI();
~AuswertungsGUI();
private:
//...
};
GUI.cpp:
#include "GUI.h" //Definition der Klassen: AuswertungsGUI, ...
AuswertungsGUI::AuswertungsGUI():Dialog(DA_Window, "GUI")
//Dialog( LPCTSTR DlgName, LPCTSTR DllName )
{
InitMsgMap();
}
AuswertungsGUI::~AuswertungsGUI() //Desktruktor
{
printf("Im Desktrutor\n");
this->Close();
}
Error at GUI.h in line class AuswertungsGUI:public Dialog. The compiler says (translated): Invalid keyword, expcted identifier of base class, then
class/struct not found and then error in declaration of datatype
In this case, the compiler is complaining that Dialog isn't a base class identifier because it hasn't encountered its declaration (and thus can't subclass it, as it doesn't "know" it).
Include the header that contains Dialog and it'll be fine.

Dialog in MFC programming

I am learning MFC programming. In the part of dialog design, I entered a problem.
The resource is IDD_PEN_WIDTH, which is the ID of the dialog. And there is a piece of automatically generated code related to this:
class PenWidthDlg : public CDialogEx
{
DECLARE_DYNAMIC(PenWidthDlg)
public:
PenWidthDlg(CWnd* pParent = NULL); // standard constructor
virtual ~PenWidthDlg();
// Dialog Data
enum { IDD = IDD_PEN_WIDTH };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
int m_nPenWidth;
};
Before I run my program, the IDD_PEN_WIDTH shows "#define IDD_PEN_WIDTH 301" while hovering mouse on IDD_PEN_WIDTH in the code. But when I run it, there is one error says IDD_PEN_WIDTH is an undefined identifier. Then I hover mouse on "IDD_PEN_WIDTH", it also says it's undefined.
I am usually confused in MFC studying, and I will appreciate very much for your detailed explanations. Thanks.
It has to be defined in every cpp file that uses it. Add #include "Resource.h" in those cpp files. Do that #include before the #include of the dialog .h file.

error C2504: 'BASECLASS' : base class undefined

I checked out a post similar to this but the linkage was different the issue was never resolved. The problem with mine is that for some reason the linker is expecting there to be a definition for the base class, but the base class is just a interface. Below is the error in it's entirety
c:\users\numerical25\desktop\intro todirectx\godfiles\gxrendermanager\gxrendermanager\gxrendermanager\gxdx.h(2) : error C2504: 'GXRenderer' : base class undefined
Below is the code that shows how the headers link with one another
GXRenderManager.h
#ifndef GXRM
#define GXRM
#include <windows.h>
#include "GXRenderer.h"
#include "GXDX.h"
#include "GXGL.h"
enum GXDEVICE {
DIRECTX,
OPENGL
};
class GXRenderManager {
public:
static int Ignite(GXDEVICE);
private:
static GXRenderer *renderDevice;
};
#endif
at the top of GxRenderManager, there is GXRenderer , windows, GXDX, GXGL headers. I am assuming by including them all in this document. they all link to one another as if they were all in the same document. correct me if I am wrong cause that's how a view headers. Moving on...
GXRenderer.h
class GXRenderer {
public:
virtual void Render() = 0;
virtual void StartUp() = 0;
};
GXGL.h
class GXGL: public GXRenderer {
public:
void Render();
void StartUp();
};
GXDX.h
class GXDX: public GXRenderer {
public:
void Render();
void StartUp();
};
GXGL.cpp and GXDX.cpp respectively
#include "GXGL.h"
void GXGL::Render()
{
}
void GXGL::StartUp()
{
}
//...Next document
#include "GXDX.h"
void GXDX::Render()
{
}
void GXDX::StartUp()
{
}
Not sure whats going on. I think its how I am linking the documents, I am not sure.
The problem is You need to have #include "GXRenderer.h" at the top of both: GXGL.h and also GXDX.h.
The base type must be defined not just declared before defining a derived type.
By the way, the error is a compiling error not linking error.
Edit: About your class type redefinition:
at the top of every header file you should have #pragma once.
The #pragma once directive specifies that the file will be included at most once by the compiler in a build.
You included them all into GXRenderManager.h, meaning that GXRenderManager.h is OK.
But you forgot to include them all into GXGL.cpp and GXDX.cpp. In these .cpp files GXRenderer class is completely unknown.
There are at least two "schools" of #include strategies. One says that header file must include everything that is needed for its own compilation. That would mean that GXGL.h and GXDX.h must include GXRenderer.h. If you followed that strategy, your GXGL.cpp and GXDX.cpp would be OK as they are now.
Another "school" says that header files must not include each other at all, i.e. all inclusions must be done through .cpp files. At first sight one could guess that your GXGL.h and GXDX.h follow that strategy (since you are not including anything into them), but then your GXRenderManager.h looks completely different.
You need to decide which strategy you are trying to follow and follow it. I'd recommend the first one.
I got an error C2504: 'CView' : base class undefined
where CView is not directly my base class from which I am inheriting.
I am inherting mYClass from MScrollView, "for this matter any class which is not actual Base Class is what the point is to be noted down here"
but the error is the C2504. When I have included it in the header where this problem is arising, this problem is resolved.
#include "stdafx.h"
where stdafx.h has #include which contains all the basic class defined...hope this answer resolves everyone who are facing this issue.