Dialog im Screensaver läßt sich nicht öffnen
-
Hallo.
Ich arbeite mit dem VS 2005 Prof. und baue gerade einen Screensaver für Windows XP. Der Screensaver soll, bevor es richtig losgeht, einen Dialog anzeigen. Letzteres bereitet Probleme.
Den Screensaver habe ich wie hier beschrieben erstellt (er funktioniert soweit auch gut):
http://www.c-plusplus.net/forum/viewtopic-var-t-is-275503-and-sid-is-a67f656521cacc449150f2641dce1572.htmlDanach habe ich einen weiteren Dialog angelegt und ihn im ScreenSaverProc wie folgt eingebunden:
... switch( uiMessage ) { case WM_CREATE: { bCallDefaultScrMsgProvider=false; CUserNoteDlg dlg; int nResponse = dlg.DoModal(); //Hier kracht es... (siehe unten) if (nResponse == IDOK) { AfxMessageBox(_T("IDOK")); } else if (nResponse == IDCANCEL) { AfxMessageBox(_T("IDCANCEL")); } } break; //EndCase WM_CREATE of uiMessage ...
Im Release-Modus läuft der Code durch und der Dialog wird eigenartigerweise fehlerfrei angezeigt. Im Debug-Modus werde ich aber auf einen Fehler hingewiesen: „Debug Assertion Failed! afxwin1.inl, Line 24 (AfxGetResourceHandle() -> ASSERT(afxCurrentResourceHandle != NULL );)“.
Mein erster Gedanke war es, den Aufruf von
AFX_MANAGE_STATE(AfxGetStaticModuleState());
der Funktion ScreenSaverProc voranzustellen. Das half aber nicht. Bin gerade richtig ratlos...
MarviESC
-
Und wo wird dieser Code aufgerufen?
Welche Art von Projket-Typ hast Du ausgewählt?
IMHO Musst Du eine Standard-DLL bauen. Der Fehler deutet daruf hin, dass die MFC nicht korrekt initialisiert wurde, zu dem Zeitpunkt zu dem Du sie benutzen willst.
-
Danke für Deine Antwort.
Martin Richter schrieb:
Und wo wird dieser Code aufgerufen?
Welche Art von Projket-Typ hast Du ausgewählt?Der Code wird im ScreenSaverProc aufgerufen. Das Projekt ist ein Win32-Projekt mit MFC-Unterstützung. Siehe hier:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-275503-and-sid-is-a67f656521cacc449150f2641dce1572.htmlMarviESC
-
Ich sehe aber keinen Code in dem Sample, auf das Du verweist der MFC benutzt.
Evtl. stimmt der DLL Entry Point nicht.
Hast Du überhaupt ein CWinApp Objekt in Deiner DLL definiert?Wenn nicht
- lies erstmal ein paar Grundlagen
- schreib alles in purem Win32 API
- Verwende nur die MFC
-
Martin Richter schrieb:
Ich sehe aber keinen Code in dem Sample, auf das Du verweist der MFC benutzt.
Hast Du überhaupt ein CWinApp Objekt in Deiner DLL definiert?Der Beitrag, auf den ich verwiesen habe, ist von mir (inkl. Sample). Es wird keine DLL erstellt, sondern eine exe. Für die Erstellung des Projekts wird der Projekt-Wizard vom VS 2005 benutzt. Er erstellt ein Win32-Projekt (VS .NET 2005 starten / Datei / neu / Win32 / Win32-Projekt; Anwendungseinstellung: „Windows Anwendung“ und „Leeres Projekt“ auswählen). Im Erstellungsdialog des Projekt-Wizards wird die MFC-Unterstützung angepriesen.
Das, was danach folgt, habe ich in meinem oben verlinkten TUT erklärt. Natürlich kann ich nicht ausschließen, dass ich dabei einen Fehler gemacht habe. Bis zu dem dort beschriebenen Punkt läuft jedenfalls alles fehlerfrei. Der Doku von MS
http://msdn.microsoft.com/en-us/library/cc144066(VS.85).aspx
kann ich nicht entnehmen, warum das, was ich vorhabe, nicht gehen sollte. Deren RegisterDialogClasses()-Gefummel bezieht sich einzig auf den Konfigurationsdialog (klar, sie starten den Dialog aus der lib heraus). Das sich die main in der scrnsave.lib befindet und dort eigene Ressourcen definiert sind, sollte zumindest bei der Verwendung von AFX_MANAGE_STATE auch kein Problem darstellen. *grübel*
MarviESC
-
1. Was nicht geht, ist einfach die MFC zu verwenden, wenn Du das Framework nicht korrekt initialisierts.
2. Das Problem tritt ja nicht in dem WinAPI teil auf, sondern in der MFC.
3. Inwiefern hast Du in eine EXE MFC Unterstützung? Das gibt es nur für Konsolen Programme... für alle anderen Projekte werden komplette Framework-Dateisätze erzeugt.
-
Danke für Deine Geduld.
Martin Richter schrieb:
3. Inwiefern hast Du in eine EXE MFC Unterstützung? Das gibt es nur für Konsolen Programme... für alle anderen Projekte werden komplette Framework-Dateisätze erzeugt.
Reden wir hier aneinander vorbei? Meinem Verständnis nach ist die MFC eine Sammlung objektorientierter Klassenbibliotheken. Sie dient der Programmierung von Anwendungen mit grafischen Benutzeroberflächen unter C++. Die Bibliotheken liegen in einer (genau genommen sind es mehrere) DLL. Sie können dynamisch oder statisch der exe hinzugefügt werden.
Zu 1.) Ich muss zugeben, dass ich mich bislang auf den Projekt-Assistenten verlassen konnte, wenn es darum ging, das Framework in einem vom Assistenten angelegten Projekt richtig zu initialisieren. Da auch dieses Projekt über den Assistenten angelegt wurde, habe ich mir darüber keine Gedanken gemacht. Allerdings hat die lib wohl "schlechten" Einfluss auf die Initialisierung, obgleich sie von MS stammt. Die MFC ist ein wichtiger (sogar der kostenpflichtige) Bestandteil der VS-Umgebung von MS. Es wäre doch eine Erwähnung wert, wenn dieser Bestandteil nicht mehr funktioniert, sobald man diese lib verwendet. Darüber steht auf den MS-Seiten aber nichts geschrieben.
Die lib beinhaltet die Main und den Rumpf. Den Teil kann ich nicht mehr beeinflussen. Keine Ahnung an welchen Schrauben ich hier noch drehen kann (bzw. muss). Hast Du eine Idee, wo ich da ansetzen kann?
Was mich vor allem wundert, ist, dass der Dialogaufruf im Release-Modus fehlerfrei funktioniert (also ohne die Debug Assertion). Ich kann dort sogar auf Fensternachrichten des Dialoges reagieren bzw. OnXYZ-Funktionen verwenden und auch Einfluss auf die Elemente des Dialoges nehmen – alles ohne Probleme. Warum funktioniert das unter diesen Bedingungen überhaupt?
Anders formuliert hätte ich ohne den Debug-Modus gar kein Problem. Nur werde ich mich hüten die Debug-Fehlermeldung zu ignorieren bzw. ein solches Programm produktiv einzusetzen, auch wenn es so erst einmal fehlerfrei zu laufen scheint. Ich muss verstehen, was hier schiefgelaufen ist und hoffe auf Deine weitere Geduld mit mir.
MarviESC
Nachtrag: Nach Deinem Hinweis zur MFC-Initialisierung habe ich mir im Netz einiges durchgelesen. Womöglich bringt es etwas, ::AfxWinInit() von Hand zu starten. Ich wühle mich weiter durch...
-
Die MFC ist keine Bibliothek, sie ist ein Ganzes Framework, wie es der Name schon sagt.
Ich weiß immer noch nicht wie Du Dein Projekt angelegt hast?
- Es um eine EXE geht muss ein CWinApp Objekt vorhanden sein und kein WinMain.
- Comsolen Applikatinen kommen mit einem Aufruf von AfxInit AfxWinInit aus.
- Standard DLLs benötigen auch ein CWinApp Objekt.
- Extension DLLs ein entsprechendes Modul.Was ich von Deinem Code sehe ist nur ein Stück WinApi Code. In den kanst Du nicht ohne weiteres irgendwelchen MFC Code verwenden, wenn keine Initialisierung des Frameworks vorhanden ist.
Nochmal: Wie hast Du Dein Projekt erzeugt? Ich habe es nicht verstanden...
Ein MFC Wizard war es sicherlich nicht.
-
-
Fehler gefunden. Er sitzt vor dem Bildschirm und fragt sich gerade, wie er das übersehen konnte... Aber eins nach dem anderen:
Martin Richter schrieb:
Wie hast Du Dein Projekt erzeugt?
Ich habe das Projekt wie folgt erstellt: VS .NET 2005 starten / Datei / neu (hier startet der Wizard) / _Win32_ / Win32-Projekt; Anwendungseinstellung: „Windows Anwendung“ und „Leeres Projekt“ auswählen.
Dort stand dann auch etwas von „MFC“. Zu diesem Zeitpunkt habe ich das aber nicht genauer beachtet, sondern nur zur Kenntnis genommen.
Dann habe ich die Projekteinstellungen vorgenommen, in der Projektdatei, die der Wizard erstellt hat. Dort steht ebenfalls etwas zur MFC, und zwar „Verwendung von MFC: Windows-Standardbibliotheken verwenden“.
Zudem fehlten dem Projekt die stdafx.h und stdafx.cpp, die ich – und das war der Fehler – aus einem anderen MFC-Anwendungs-Projekt in mein ScreenSaver-Projekt übernommen hatte. Der Effekt war der, dass ich tatsächlich MFC-Klassen verwenden konnte; nur eben der Debug-Modus wollte das nicht.
Im Zuge meiner Recherchen bin ich dann auf diese Seite von MS gestoßen:
http://msdn.microsoft.com/de-de/library/wydfdtb6(VS.80).aspxIch zitiere: „Sie können einer Win32-Anwendung keine MFC- oder ATL-Unterstützung hinzufügen.“
Das ist zwar komisch, weil man im Win32-Wizard bei der Auswahl von „Windows-Anwendung“ per Auswahlbox auch „ATL“ ankreuzen kann. Auf jeden Fall ist mir dann erst aufgefallen, dass da zwar etwas von einer MFC-Unterstützung steht, nur wird es ausgegraut, sobald man "Windows Anwendung" ausgewählt. Peinlich.
Ich bin davon ausgegangen, dass man bei einer Win32-Anwendung zwar einen anderen Ansatz verfolgt, aber nicht, dass man darin (ähnlich wie bei der ATL) keine MFC-Klassen mehr verwenden kann. Beide Ansätze sind offenbar nicht so entwickelt worden, dass sie nebeneinander existieren können.
Dieser Fall der Screensaver-Anwendung ist ohnehin etwas besonderes, da ja die lib die main und den Rumpf der Anwendung enthält. Aus dem zu erstellenden Code werden lediglich die Funktionen ScreenSaverProc() – wenn der Screensaver gestartet werden soll – oder ScreenSaverConfigureDialog() aufgerufen – wenn der Konfigurationsdialog angezeigt werden soll. Eine passende scrnsave.cpp liefert MS leider nicht mit. Es ist halt nicht oben Source; warum auch immer.
Wie dem auch sei, waren alle meine Versuche, die MFC dort korrekt zu initialisieren erfolglos. In Deinem Link eins drüber sagt MS auch klar, dass es nicht geht:
http://msdn.microsoft.com/en-us/library/aa233486Zitat: „[…] scrnsave.lib that is provided by the SDK, as that library does not fit the MFC architecture”
Bleibt für mich noch die Frage offen, warum es denn in der Release-Variante läuft. Ohne korrekten Handle auf die Ressourcen kann der Dialog eigentlich nicht angezeigt werden. Hier hätte es auch im Release-Modus zu einem Fehler führen müssen. *grübel*
MarviESC
-
MarviESC schrieb:
Fehler gefunden. Er sitzt vor dem Bildschirm und fragt sich gerade, wie er das übersehen konnte... Aber eins nach dem anderen:
Martin Richter schrieb:
Wie hast Du Dein Projekt erzeugt?
Ich habe das Projekt wie folgt erstellt: VS .NET 2005 starten / Datei / neu (hier startet der Wizard) / _Win32_ / Win32-Projekt; Anwendungseinstellung: „Windows Anwendung“ und „Leeres Projekt“ auswählen.
Dort stand dann auch etwas von „MFC“. Zu diesem Zeitpunkt habe ich das aber nicht genauer beachtet, sondern nur zur Kenntnis genommen.
Solch ein Projekt ist nicht MFC kompatibel. Du musst das ganze Framework dann selbst zusammenstecken.
MarviESC schrieb:
Dann habe ich die Projekteinstellungen vorgenommen, in der Projektdatei, die der Wizard erstellt hat. Dort steht ebenfalls etwas zur MFC, und zwar „Verwendung von MFC: Windows-Standardbibliotheken verwenden“.
Das nützt nichts.
Die Voraussetungen für das Framework schafst Du damit nicht!MarviESC schrieb:
Zudem fehlten dem Projekt die stdafx.h und stdafx.cpp, die ich – und das war der Fehler – aus einem anderen MFC-Anwendungs-Projekt in mein ScreenSaver-Projekt übernommen hatte. Der Effekt war der, dass ich tatsächlich MFC-Klassen verwenden konnte; nur eben der Debug-Modus wollte das nicht.
stdafx Dateien sind für jedes Projekt (auch MFC) optional...
Die Klassen kannst Du vielleicht kompilieren, aber sie werden ASSERTs werfen ohne Ende.MarviESC schrieb:
Im Zuge meiner Recherchen bin ich dann auf diese Seite von MS gestoßen:
http://msdn.microsoft.com/de-de/library/wydfdtb6(VS.80).aspxIch zitiere: „Sie können einer Win32-Anwendung keine MFC- oder ATL-Unterstützung hinzufügen.“
Lies Englisch.
Damit werden nur die Voraussetungen für das Linken geschaffen und einige Compiler schalter gesetzt.
Wenn Du die Klassen nicht initialisierst, also richtig verwendest läuft immer noch nicths.
Der Compiler kann Deine syntakitschen Fehler nicht ausgleichen.MarviESC schrieb:
Das ist zwar komisch, weil man im Win32-Wizard bei der Auswahl von „Windows-Anwendung“ per Auswahlbox auch „ATL“ ankreuzen kann. Auf jeden Fall ist mir dann erst aufgefallen, dass da zwar etwas von einer MFC-Unterstützung steht, nur wird es ausgegraut, sobald man "Windows Anwendung" ausgewählt. Peinlich.
Ich bin davon ausgegangen, dass man bei einer Win32-Anwendung zwar einen anderen Ansatz verfolgt, aber nicht, dass man darin (ähnlich wie bei der ATL) keine MFC-Klassen mehr verwenden kann. Beide Ansätze sind offenbar nicht so entwickelt worden, dass sie nebeneinander existieren können.
Kannst Du. Du musst es nur richtig, machen.
Du hast kein CWinApp Objekt und ein WinMain zuviel.MarviESC schrieb:
Dieser Fall der Screensaver-Anwendung ist ohnehin etwas besonderes, da ja die lib die main und den Rumpf der Anwendung enthält. Aus dem zu erstellenden Code werden lediglich die Funktionen ScreenSaverProc() – wenn der Screensaver gestartet werden soll – oder ScreenSaverConfigureDialog() aufgerufen – wenn der Konfigurationsdialog angezeigt werden soll. Eine passende scrnsave.cpp liefert MS leider nicht mit. Es ist halt nicht oben Source; warum auch immer.
Wie dem auch sei, waren alle meine Versuche, die MFC dort korrekt zu initialisieren erfolglos. In Deinem Link eins drüber sagt MS auch klar, dass es nicht geht:
http://msdn.microsoft.com/en-us/library/aa233486Zitat: „[…] scrnsave.lib that is provided by the SDK, as that library does not fit the MFC architecture”
Bleibt für mich noch die Frage offen, warum es denn in der Release-Variante läuft. Ohne korrekten Handle auf die Ressourcen kann der Dialog eigentlich nicht angezeigt werden. Hier hätte es auch im Release-Modus zu einem Fehler führen müssen. *grübel*
MarviESC
Ich habe Dir einen Link mit MFC Nutzung gesendet.
Und wenn Du im Netz MFC und Screensaver suchst findest Du genug Code!
-
Hm, in meinem vorherigen Post konnte ich mich offensichtlich nicht verständlich machen (bzw. hoffe ich, dass Du das nicht in den falschen Hals bekommen hast?). Ich habe den Fehler gefunden. Es lang an mir, weil ich übersehen hatte, dass der Wizard darauf hinweist, dass die Win32-App keine MFC unterstützt. Die zitierte Projekteinstellung („Verwendung von MFC: Windows-Standardbibliotheken verwenden“) habe ich nur erwähnt, um zu veranschaulichen, was mich vor dieser Erkenntnis zusätzlich in die Irre geführt hat. Dort hatte ich bereits verstanden, dass das so nicht geht.
Martin Richter schrieb:
Lies Englisch.
Mache ich: http://msdn.microsoft.com/en-us/library/s2zy4kwk(VS.80).aspx
In der englischen Variante steht dasselbe, nur anders "verpackt": "[...] you can add MFC classes only to those Win32 application types that support MFC (see the previous table) [table:] MFC support Console application; not Execuable [Win32] application [...]"
Nun schreibst Du oben jedoch folgendes:
Martin Richter schrieb:
Du musst das ganze Framework dann selbst zusammenstecken. [Du kannst in einem Win32-Projekt durchaus die MFC nutzen...] Du musst es nur richtig, machen. Du hast kein CWinApp Objekt und ein WinMain zuviel.
Es geht also doch? Das hört sich interessant an. Hast Du dazu schon einmal etwas geschrieben oder hast Du einen empfehlenswerten Link einer anderen Quelle zu diesem Thema?
Martin Richter schrieb:
Ich habe Dir einen Link mit MFC Nutzung gesendet.
Den habe ich nicht übersehen (ich habe ja oben auch daraus zitiert). An der MFC-Variante sitze ich schon längst. Dennoch ist auch das hier diskutierte Thema für mich weiter interessant. Zum einen sind die Erkenntnisse nicht nur in diesem Projekt nutzbar. Zum anderen lassen sich sämtliche hilfreiche Informationen in das eingangs erwähnte TUT packen, was es für andere Nutzer leichter macht, die vor einer ähnlichen Aufgabe stehen.
MarviESC
-
Den meine ich:
BTW: http://msdn.microsoft.com/en-us/library/aa233486(VS.60).aspxSicher geht es, auch das habe ich geschrieben:
Martin Richter schrieb:
Die MFC ist keine Bibliothek, sie ist ein Ganzes Framework, wie es der Name schon sagt.
Ich weiß immer noch nicht wie Du Dein Projekt angelegt hast?
- Es um eine EXE geht muss ein CWinApp Objekt vorhanden sein und kein WinMain.
- Comsolen Applikatinen kommen mit einem Aufruf von AfxInit AfxWinInit aus.
- Standard DLLs benötigen auch ein CWinApp Objekt.
- Extension DLLs ein entsprechendes Modul.Was ich von Deinem Code sehe ist nur ein Stück WinApi Code. In den kanst Du nicht ohne weiteres irgendwelchen MFC Code verwenden, wenn keine Initialisierung des Frameworks vorhanden ist.
-
Martin Richter schrieb:
Den meine ich:…
Ich weiß. Das war auch ein guter Hinweis und ich arbeite bereits daran.
Zum Win32-Projekt mit MFC-Unterstützung: Dann versuche ich jetzt einmal ein Win32-Projekt nach Deinen Hinweisen derart umzustellen, dass auch die MFC unterstützt wird. Das Projekt habe ich wie folgt erstellt: VS 2005 starten / Datei / neu / Win32 / Win32-Projekt / Name: Win32 / Windows Anwendung / Fertig stellen.
Dann habe ich in der Win32.h den folgenden Code hinzugefügt:
class CWin32App : public CwinApp { public: CWin32App(); public: virtual BOOL InitInstance(); }; extern CWin32App theApp;
In der Win32.cpp wurde die Funktion _tWinMain() komplett auskommentiert. Die dortige InitInstance()-Funktion habe ich der Eindeutigkeit halber nach InitInstanceWin32() umbenannt. Deren Code soll erst später eingebunden werden. Ein Schritt nach dem anderen.
Dann habe ich der Win32.cpp den folgenden Code hinzugefügt:
CWin32App theApp; CWin32App::CWin32App(){ } BOOL CWin32App::InitInstance(){ AfxMessageBox(_T("Enter InitInstance()")); CWinApp::InitInstance(); return TRUE; }
Die stdafx.h und stdafx.cpp habe ich ersetzt durch Dateien aus einem frisch erstellten MFC-Anwendungs-Projekt.
Dann habe ich die Projekteinstellungen wie folgt angepasst: Alt+F7 / Konfigurationseigenschaften / Allgemein / Verwendung von MFC: MFC in einer öffentlichen DLL verwenden
Nun läßt sich der Code ohne Fehlermeldung erstellen. InitInstance() wird aufgerufen und die AfxMessageBox gestartet, aber dargestellt wird sie nicht. Ohne Fehlermeldung lauft das Programm durch und beendet sich dann.
MarviESC