Zeiger auf Dialog löschen
-
sasse schrieb:
Und wie, ich weiß es halt nicht.
Setze ein Flag, das abgeprüft wird...
Wenn Du nicht weißt wie das geht, dann lerne erst einmal etwas von den Grundzügen des Programmierens!
Fröhliche Weihnachten! :xmas1:
-
Ich erzeuge ja aber gar kein Thread. Dies geschiet ja durch eine andere Applikation.
Ich erzeuge in InitInstance meinen Dialog und in ExitInstance soll er wieder gelöscht werden. ExitInstance wird nun aber von einem anderen Thread aufgerufen. Also wo soll ich da bitte ein Flag setzen.
Und wieso darf ich WM_DESTROY nicht senden?
-
Es ist schon seltsam. Man versucht hier sein Problem zu klären. Dann erhält man Tipps, was auch echt toll ist. Nur das Problem ist wenn einem diese Tipps nicht helfen und man versucht das Problem genauer zu erläutern. Und erklärt wieso einem die Tipps nichts bringen. Schüttelt man unverständlicherweise den Kopf und das wars dann.
Ich versuche hier nochmals mein Problem genau zu definieren.Also ich habe eine DLL die von einer fremden Applikation geladen wird. In InitInstance werden mehrere Dialoge mit new und Create angelegt. Nun sollte ja bei ExitInstance diese Dialoge wieder zerstört und gelsöcht werden. Also mit DestroyWindow und mit delete. Nun allerdings wird von der fremden Applikation allerdings ein anderer Thread dazu verwendet um die DLL zu entladen. Das sehe ich daran dass ich im Debugger den aktuellen Thread kontrolliere.
Wenn ich nun einfach m_myDlg1->DestroyWindow() aufrufe erhalte ich einen Fehler weil DestroyWindow nicht von einem anderen Thread aufgerufen werden darf, als der der ihn erzeugt hat. Sprich ich muss nun eine Nachricht senden die den Dialog zerstört. Und dort drin kann ich dann auch delete this aufrufen.
Aber nun weiß ich halt nicht was ich da genau senden soll und wie das ganze dann abfangen.
Also bitte kann mir da keiner eine genaue Auskunft geben.
-
Wenn eine fremde EXE Deine DLL aus mehreren Threads verwendet, dann ist die MFC bestimmt nicht das Tool der Wahl, denn MFC Objekte sind threadafin, d.h. sie dürfen nur von dem Thread aus verwendet werden, der das Objekt/Fenster erzeugt hat.
- Wenn das aufrufende Programm ein Stück .NET Software ist, dann ist es sehr wahrscheinlich, dass der Garbage Collector aus einem anderen Thread Objekt abräumt.
- Wenn Dir also geraten wird aus enem Thread an ein Fenster eine Nachricht zu senden, dann mach dies doch einfach (SendMessage)
- Eine eigene Nachricht definieren geht ja auch (WM_APP+n)
- Einen Handler für die Nachricht in Deinen Dialog einbauen geht auch (ON_MESSAGE).Mit den Angaben, die ich Dir gemacht habe, hättest Du all dies ohne Probleme in Google nachschlagen können.
Wenn die fremde Software DLLs lädtmuss es ja wohl auch eine Doku dazu geben, oder geht es hier wieder um Hooks etc.?
-
Hallo nochmal
Einen Handler für die Nachricht in Deinen Dialog einbauen geht auch (ON_MESSAGE).
Ja aber was mach ich den in der Funktion dann? DestroyWindow aufrufen oder was?
-
sasse schrieb:
Hallo nochmal
Einen Handler für die Nachricht in Deinen Dialog einbauen geht auch (ON_MESSAGE).
Ja aber was mach ich den in der Funktion dann? DestroyWindow aufrufen oder was?
Ja sicher! Was sonst?
Dann bist Du doch im selben Thread! Durch SendMessage erfolgt (wenn notwendig) ein Threadwechsel.
-
Ok werde ich versuchen. Aber jetzt habe ich Urlaub :xmas1:
Also Danke mal.
-
So Urlaub vorbei. Habe das ganze nun getestet. Es funktioniert allerdings nur teilweise. Ich rufe SendMessage für 4 Dialoge auf. Bei 2en kommt die Nachricht aber nur an. Gibt es dafür eine Erklärung.
-
Hm merkwürdig, wenn es bei 2 Dialogen funktioniert. - Hast du denn nähere Informationen dazu?
-
Ich rufe hintereinander Sendmessage auf für alle 4 Dialoge
SendMessage(m_pmydlg1->m_hWnd,WM_APPWICI,NULL,NULL); SendMessage(m_pmydlg2->m_hWnd,WM_APPWICI,NULL,NULL); SendMessage(m_pmydlg3->m_hWnd,WM_APPWICI,NULL,NULL); SendMessage(m_pmydlg4->m_hWnd,WM_APPWICI,NULL,NULL);
folgendes in jeder MessageMap der jeweiligen Klassen
ON_MESSAGE(WM_APPWICI,&CMyDlg1::MyDestroyWindow)
Funktion sieht dann wie folgt aus
LRESULT CRuntimeInfoDlg::MyDestroyWindow(WPARAM wparam, LPARAM lparam) { DestroyWindow(); delete this; return (LRESULT)0; }
Und noch was wenn DestroyWindow vom ersten Dialog aufgerufen wird. Wird DestroyWindow auch in allen weiteren Dialogen ausgeführt. Also vor SendMessage des jeweiligen Dialoges.
-
Also jetzt habe ich nochmals einen Test gemacht. Habe eine Extra DLL geschrieben die nur 3 Dialoge enthält. Und eine exe die die DLL verwendet. Und es stellt sich genau selbiges Verhalten ein.
Wenn ich folgendes aufrufe:
#define WM_APPDLG WM_APP + 1 SendMessage(m_myDialog1->m_hWnd,WM_APPDLG,NULL,NULL);
Wird die Nachricht vom Dialog 1 abgefangen was ja auch richtig ist. Nach dem aufruf von DestroyWindow(); wird dann allerdings von jeder Dialogklasse PostNcDestroy(); aufgerufen. Die Nachrichten die dann an die anderen Dialoge gesendet werden ja dann nicht mehr abgefangen. Da die Dialoge zu dem Zetpunkt dann zerstört sind. Wieso werden denn die anderen Dialoge auch gleich zerstört.
Wie ist denn die richtige Vorgehensweise.
-
Wenn das Kind Dialoge des ersten Dialoges sind, ist dieses Verhalten doch logisch oder?
-
Wenn das Kind Dialoge des ersten Dialoges sind, ist dieses Verhalten doch logisch oder?
Ja wenn es Kind Dialoge wären. Sind es aber nicht. Sind alles eigenständige Dialoge.
-
Wurden wie folgt angelegt in InitInstance() angelegt:
m_myDialog1 = new CMyDialog1; m_myDialog1->Create(IDD_DIALOG_MYDIALOG1); m_myDialog2 = new CMyDialog2; m_myDialog2->Create(IDD_DIALOG_MYDIALOG2); m_myDialog3 = new CMyDialog3; m_myDialog3->Create(IDD_DIALOG_MYDIALOG3);
Nun ist doch von keinem das andere Kind oder etwa doch?
-
Kann mir denn keiner helfen. Ist doch nun kein aussergewöhnliches Verhalten oder doch?
-
Du hast einen Debugger.
Setz einen Breakpoint PostNcDestroy!
Schau Dir den Callstack an und dann kannst Du genau sehen wer Deine Objekte zerstört!Ansonsten: Minisample bauen und zum Testen zur Verfügung stellen.
-
Mit Callstack meinst du die Aufrufliste. (Armes Deutschland)
Ok und darin sehe ich dass PostNCDestroy von der Funktion CWnd::OnNcDestroy() aus wincore.cpp aufgerufen wird und diese wiederum von CWnd::OnWndMsg(...) und nun. Das sagt mir leider immer noch nichts.
Wie kann ich den mein mini beispiel hochladen. Muss ich mich registrieren?
-
Zeigt der Callstack nicht mehr?
Komisch. Vermutlich lädst Du nicht alle Debug Infos für die Systemdateien.
Lade es irgendwohin und gib mir den Link!
-
Ok. Konnte jetzt erst antworten da ich in meiner Firma nicht uploaden darf.
Also hier der Link. Projekt für Visual Studio 2008.http://www.file-upload.net/download-2146695/Dialogtest.zip.html
-
Das ist doch Unfug was Du machst. Wenn Dein Prozess terminiert, dann muss Dir doch klar sein, dass alle Fenster aufgeräumt werden. Und das macht Windows bevor die DLLs alle entladen werden.
Das zeigt auch der Stacktrace:
> DialogDll.dll!CDialogDllApp::ExitInstance() Line 76 C++ DialogDll.dll!InternalDllMain(HINSTANCE__ * hInstance=0x665d0000, unsigned long dwReason=0, void * __formal=0x00000001) Line 155 C++ DialogDll.dll!DllMain(HINSTANCE__ * hInstance=0x665d0000, unsigned long dwReason=0, void * lpReserved=0x00000001) Line 272 C++ DialogDll.dll!__DllMainCRTStartup(void * hDllHandle=0x665d0000, unsigned long dwReason=0, void * lpreserved=0x00000001) Line 546 + 0x11 bytes C DialogDll.dll!_DllMainCRTStartup(void * hDllHandle=0x665d0000, unsigned long dwReason=0, void * lpreserved=0x00000001) Line 510 + 0x11 bytes C ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes ntdll.dll!_LdrShutdownProcess@0() - 0x96 bytes ntdll.dll!_RtlExitUserProcess@4() + 0x74 bytes kernel32.dll!75952ae4() msvcr90d.dll!__crtExitProcess(int status=0) Line 732 C msvcr90d.dll!doexit(int code=0, int quick=0, int retcaller=0) Line 644 + 0x9 bytes C msvcr90d.dll!exit(int code=0) Line 412 + 0xd bytes C Dialogtest.exe!__tmainCRTStartup() Line 599 C Dialogtest.exe!WinMainCRTStartup() Line 403 C kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes