"illegal call of non-static member function" bei SetWindowPos in eigener Klasse
-
Hallo,
ich habe ein Problem.
Ich habe bisher in einem sehr einfachen MFC-Programm im OnOK() ein SetWindowPos benutzt:CAViewDlg::SetWindowPos(&CWnd::wndTopMost,300,0,600,20,0);
Um es für später(wenn ich mal ein richtiges Programm habe) übersichtlicher zu haben, will ich möglichst alles in eine App.h und App.cpp auslagern.
Also, mach in ne App.h:
//--------------------------------------------------------------------
#include "blablabla" //Alle .h eingebunden die ich im Projekt habeclass CInit
{
CInit();
DoInit();
};
//--------------------------------------------------------------------in die App.cpp schreib ich:
//------------------------------------------------------------------
#include "blablabla" //Alle .h eingebunden die ich im Projekt habeCInit::CInit() {}
CInit::DoInit()
{
CAViewDlg::SetWindowPos(&CWnd::wndTopMost,300,0,600,20,0);
}
//------------------------------------------------------------------und dann mach ich im OnOk():
CInit INIT;
INIT::DoInit;Das komische ist, dass es tut, wenn ich das SetWindowPos direkt im OnOK() mache, aber wenn ich es in meine Init-Klasse auslagere kommt:
error C2352: 'CWnd::SetWindowPos' : illegal call of non-static member function
Es kommt auch ohne den Aufruf in OnOk(). Also wird wohl an der Implementierung liegen. Aber wo ist das Problem?
-
also erstens sind deine Methoden private, also hast gar keinen Zugriff, zweitens muss das INIT**.**DoInit() sein
-
slide schrieb:
Aber wo ist das Problem?
Das Problem ist, dass du zum Aufruf von SetWindowPos ein konkretes CAViewDlg-Objekt brauchst. Das hast du implizit aber nur innerhalb von nichtstatischen Methoden von CAViewDlg, wie z.B. OnOK. Da kannst dir das CAViewDlg:: übrigens auch sparen.
Kann es sein, dass dir der Unterschied zwischen Klasse und Instanz noch nicht ganz klar ist?
-
Tut mir leid, ich habe das alles abgekürzt, damit man nich soviel zum lesen hat, da hab ich glatt das public: weggemacht.
Zu dem INIT.DoInit() : Kann sein, aber die Meldung kommt ja schon ohne Aufruf von DoInit.
Es kommt sobald ich die CInit klasse hinzugefügt habe und dass
CAViewDlg::SetWindowPos(&CWnd::wndTopMost,300,0,600,500,0);
hineingeschrieben habe.
Er blickt das CAViewDlg::SetWindow nicht, aber wiso tut es dann, wenn ichs im OnOk() mache.
-
MFK schrieb:
Kann es sein, dass dir der Unterschied zwischen Klasse und Instanz noch nicht ganz klar ist?
Doch, der ist mir klar. Ich habs auch schon mit der Instanz versucht, die in der AView.cpp erstellt wird ( CAViewDlg dlg; )
Aber wenn ich dlg::SetWindowPos versuche kennt er dlg nicht.
Was kann ich machen, damit ich ein SetWindowPos des Fensters machen kann?Muss ich da mit FindWindow nen Handle holen und davon dann nen CWnd holen oder einen globalen Pointer definieren den ich dann auf dlg zeigen lasse?
Bitte sag mir wie da die beste Lösung ist.
-
Hallo, inzwischen funktioniert es recht gut, aber immer noch nicht so wie ich denke, dass es sein sollte.
Damit ihr es alle Nachvollziehen könnt, beschreibe ich es mal Schritt für Schritt:
Ich öffne VC++ 6.0 und wähle MFC-Application Wizard aus, meinem Projekt gebe ich den Namen "TRY".
Nun wähle ich Dialogbasierend, mit 3D-Controlls und Sockets, MFC Standard, mit Kommentare, statisch gelinkte Library.Nun habe ich ein frisches Projekt an dem ich noch nichts kaputt gemacht habe

Wenn ich nun in die TRY.cpp schaue, sehe ich:
-defs und includes
-Messagemap
-CTRYApp Konstruktor
-und hier nun:
// The one and only CTRYApp object
CTRYApp theApp;Nach allem was ich von C++ verstehe, auch wenn es anscheinend nicht viel zu sein scheint, wird hier ein Objekt(eine Instanz der Klasse CTRYApp generiert.
Somit müsste ich Unmittelbar nach der Erstellung(1 zeile darunter)
"theApp." eingeben können um die Syntax-Hilfe zu sehen, oder zumindest etwas wie
"theApp.AssertValid;" machen können.Doch es wird mir keine Syntaxhilfe angezeigt und bei "theApp.AssertValid;" wird angezeigt, dass er ein ; statt des . erwartet.
Als wenn er es nicht als Objekt erkennen würde.
Das komische ist, dass im Konstruktor z.b. bei "theApp." sofort die syntaxhilfe angezeigt wird.
Und ebenfalls wenn ich "= theApp." eingebe.
Ich versteh dass nicht. Wiso kann ich nicht direkt nach der Erstellung das Objekt genau so nutzen wie im Konstruktor auch? Oder wie auch in andere "Klassenfremden" Funktionen?
-
IntelliSense (die "Syntax-Hilfe") funktioniert in VC6 nur sehr schlecht, also vergiss einfach dass der dir irgendwas irgendwo nicht anzeigt, wenn du genug "komplizierten" Code schreibst zeigt der nämlich gleich garnixmehr an.
Dass "theApp.AssertValid;" nicht geht liegt einfach daran dass es falsch ist, was du willst ist "theApp.AssertValid();".
("&theApp.AssertValid;" wäre ein "legales nop", macht aber keinen Sinn)Und direkt nach "CTRYApp theApp;" kannst du theApp einfach deswegen nicht verwenden, weil du da auf "(global) namespace scope" bist, und auf "namespace scope" kannst du keine Funktionen "direkt" aufrufen.
Indirekt ja, das sähe dann z.B. so aus:int globale_dummy_variable = (globales_objekt.funktion(), 0);Würde ich aber nicht empfehlen solange du nicht weisst was du tust.
-
hustbaer schrieb:
IntelliSense (die "Syntax-Hilfe") funktioniert in VC6 nur sehr schlecht, also vergiss einfach dass der dir irgendwas irgendwo nicht anzeigt, wenn du genug "komplizierten" Code schreibst zeigt der nämlich gleich garnixmehr an.
Dass "theApp.AssertValid;" nicht geht liegt einfach daran dass es falsch ist, was du willst ist "theApp.AssertValid();".
("&theApp.AssertValid;" wäre ein "legales nop", macht aber keinen Sinn)Und direkt nach "CTRYApp theApp;" kannst du theApp einfach deswegen nicht verwenden, weil du da auf "(global) namespace scope" bist, und auf "namespace scope" kannst du keine Funktionen "direkt" aufrufen.
Indirekt ja, das sähe dann z.B. so aus:int globale_dummy_variable = (globales_objekt.funktion(), 0);Würde ich aber nicht empfehlen solange du nicht weisst was du tust.
Das theApp.AssertValid war nur ein Bsp. da es das erste war dass ich gefunden hab das keine Parameter braucht.
Direkt dahinter wollte ich es benutzen um z.b. sowas zu machen:CTRYApp theApp;
CInit INIT;
INIT.pointertoApp = &theApp;
(auch wenn ich inzwischen glaub, dass ich diesen Pointer garnich mehr brauch)Das mit den namespaces blick ich noch nich so ganz, da muss ich wohl erstmal noch was drüber lesen.
Auf jedenfall:
Ich will in meinem Programm zur Übersichtlichkeit mehrere Objekte haben von denen jede nur für seine Aufgabe zuständig ist.
- "CDataFrame DFRAME" für Daten die ich überall im Programm brauche(praktisch globale vars)
- "CInitFrame INIT" für Initialisierung (Winow-Positionierung, eigenschaften festlegen)
- "CGrafx GRAF" für alle Grafiksachen (zeichnen, bmps einladen, usw..)Über die einzelnen Member der Klassen bin ich mir noch nicht sicher.
Auf jedenfall will ich später z.B. per Timer oder auch buttonclick so arbeiten können:
INIT.SetWnd(DFRAME.WndSizeX, DFRAME.WndSizeY);
GRAF.makeline(DFRAME.WndSizeX, DFRAME.WndSizeY, DFRAME.Color);Wenn ich in meinem Init z.B. ein FindWindow machen will, muss ich dann den Pointer auf den Dialog übergeben, oder kann ich auch etwas in dieser Art machen:
( theApp.GetDialog() )->FindWindow();
Ist theApp dann von Init aus aufrufbar? Oder ist das vieleicht ein anderer namespace?Wie läuft das eigentlich bei etwas professionelleren MFC-Programmen ab?
Wird dort nicht für jede Aufgabe eine Klasse "erschaffen"? Oder wird da alles in Funktionen der Dialog oder APP -Klasse gepackte?
Gibt es Dokumente oder Festlegungen wie man es machen "sollte" ? Oder einfach auch nur Tipps, mit denen ihr gute Erfahrungen gemacht habt.
-
Hmm, ich denk zwar dass ichs inzwischen halbwegs verstehe, aber es tut noch nicht.
Ich habe nun in der App.h:
//Keine Includes class CInit() public: CInit(); DoInit(); };In der App.cpp:
#include "stdafx.h" #include "AView.h" #include "AViewDlg.h" #include "App.h" CInit::CInit() {} CInit::DoInit() { theApp.m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,300,0,600,20,0); DFRAME.Wnd_SIZE = 0; }In der AView.cpp habe ich direkt unter der Instanzerstellung der Window-Klasse theApp eine Instanz meiner Klasse erstellt: CInit INIT;
Nun dachte ich, dass ich aus meiner DoInit heraus auf theApp zugreifen kann, aber dies scheint nicht der Fall zu sein, denn ich bekomme folgenden Fehler:error C2065: 'theApp' : undeclared identifier
Wiso kennt der Compiler "theApp" an dieser Stelle nicht? Wiso wird es mir vom IntelliSense trotzdem angezeigt?
Ein namespace-Problem? Oder ein Fehler mit den Includes?
Muss man ihm vieleicht irgendwie sagen, dass er AView.cpp vor App.cpp kompilieren muss, damit er die Instanzen kennt?Vielend Dank schonmal an alle die Antworten und schon geantwortet haben.
Ich merke richtig wie sich mein Kopf mit Wissen füllt

-
#include "MainFrm.h" CInit::DoInit() { AfxGetMainWnd()->SetWindowPos(&CWnd::wndTopMost,300,0,600,20,0); DFRAME.Wnd_SIZE = 0; }?
-
Danke, für diesen Fall funktioniert das.
Aber jetzt habe ich eine 2.Klasse erstellt. Wie ich schon weiter oben mal erwähnt habe, um variablen zu speichern, die ich an vielen stellen brauche.
Ich nenne sie DFRAME.
App.hclass CDFrame { public: CDFrame(); CAViewDlg* ptoDLG; CAViewApp* ptoAPP; int Wnd_SIZE; };App.cpp
CDFrame::CDFrame() { ptoDLG = NULL; ptoAPP = NULL; Wnd_SIZE = 0; }Aber ich kann aus der DoInit() Funktion nicht DFRAME.Wnd_SIZE = 0; ausführen, da sonst wieder kommt:
error C2065: 'DFRAME' : undeclared identifierIch dachte, wenn ich ich die Instanzen in der AView.cpp erstelle sind sie global nutzbar. Wiso sind sie dass nicht? Kann man das irgendwie hinbekommen?