DebugAssert in LostFocus() bei Inplace-Edit (SDI View)
-
Hi,
ich bin gerade dabei eine Dialogfeldanwendung (funktioniert fehlerfrei) auf SDI umzubauen.
Ich verwende in der SDI Anwendung ein 'CGridCtrl' welches ein CEdit Control zum Labeledit erzeugt.
Ich klicke zwei Mal nacheinander auf eine Zelle im GridCtrl - das InPlaceEdit Control erscheint. Klicke ich wieder auf das ListCtrl verschwindet das InplaceEdit (KillFocus). Wenn ich aber direkt in das InplaceEdit Control klicke, Tritt die Fehlermeldung auf:
Debug Assertion bei CWnd::AssertValid() (wincore.cpp, Line 896).
'::IsWindow(m_hWnd)' liefert FALSE zurück.Nach einigem Rumprobieren habe ich festgestellt:
Die Fehlermeldung tritt laut Callstack auf nachdem das InplaceEdit Control den Focus verliehrt (KillFocus). In meiner Dialogfeldanwendung wurde KillFocus gar nicht erst aufgerufen wenn ich in das InplaceEdit Control klicke (nachvollziehbar). Aber bei der SDI Anwendung passiert das.In 'CInPlaceEdit::OnKillFocus(CWnd* pNewWnd)' ist 'pNewWnd' meine von CView abgeleitete Klasse...
Hierarchie:
CMyView
. CMFCTabCtrl (Child von CMyView)
.. CMySplitterWnd (Child von CMFCTabCtrl)
... CMyGridCtrl (Child von CMySplitterWnd)
.... CInPlaceEdit (Child von CMyGridCtrl)Gruß
-
Und wer führt die Prüfung aus. Offensichtlich ist das Fenster (vermutlich das Inplace Edit Control) schon zerstört.
Evtl. Behandelst Du eine Nachricht noch weiter nachdem das Control schon zerstört wurde...
-
Ja, das InplaceEdit Control wird zerstört. Der Fehler ist nachvollziehbar.
Aber warum wird OnKillFocus() überhaupt aufgerufen? Das passiert nicht in der Dialogfeldanwendung und ist auch nicht sinnvoll (KillFocus bei Klick ins eigene Fenster!?).
Ich könnte mir vorstellen dass es mit den Views und Splittern zu tun hat..
-
Eigentlich kommt diese nachricht auch in einem Dialog an... Evtl. nur in einer etwas anderen Reihenfolge.
Die Nachricht muss kommen, denn bevor das Control zerstört wird, verliert es den Focus und ein anderes bekommt ihn.
Dein Problem ist eher, dass Du nach einer Funktion (wie z.B. dem zerstören des Controls), dieses Control noch einmal verwendest... Der Assert deutet ja genau darauf hin, das Handle ist NULL Und ungültig. Das COntrol ist zersört, aber Du willst etwas damit machen.
-
Also ich sehe das so:
Das InplaceEdit verlieht seinen Focus (OnKillFocus) weil ein anderes Control ihn bekommt. Daraufhin wird das InplaceEdit zerstört.
Wenn der Benutzer aber auf das InplaceEdit klickt soll es weder zerstört werden, noch einfach so OnKillFocus aufgerufen werden - das macht an der Stelle doch keinen Sinn.In der Dialogfeldanwendung ist genau das der Fall: Man klickt auf das Control und weil es ein Edit-Control ist bewegt sich der Cursor an die Stelle wo man hinklickt.
In der SDI Anwendung wird aber fälschlicher Weise OnKillFocus() aufgerufen. Daraufhin wird das Control zerstört and anschließend weiterbenutzt (> Assertion). OnKillFocus darf gar nicht aufgerufen werden. Ich suche nur nen Grund warum es doch so ist, das kann ich mir nicht erklären.
Der CallStack sagt mir auch leider nichts besonderes (Nur CWnd-, CWinThread- und CWinApp-Klassen sind dort aufgelistet).
Kann es sein (da ich nen View, Splitter, usw. habe) dass ich klicke, "irgendein" View o.Ä. weiß nicht dass das Fenster existiert und löst KillFocus() aus?
Kanns mir nicht anders erklären..
-
Schau Dir den Callstack an... Irgendwer versetzt vermutlich den Focus...
Evtl. ist es sogar das Grid, oder das View selbst.Wie hast Du das GridCtrl intergriert, in einen View, oder als View.
-
Es ist immer meine CView-abgeleitete Klasse die den Focus bekommt... egal wo ich hinklicke.
Genauso integriert wie es im ersten Post in der Hierarchie steht (View - TabCtrl - Splitter - Grid - InPlaceEdit).
EDIT:
Es ist immer meine CView-abgeleitete Klasse die den Focus bekommt... egal wo ich im VIEW hinklicke. Wenn ich auf ein anderen dockable Window klicke ist es dann schon die entsprechende Fensterklasse. Aber der View scheint sich nur für sich selbst zu interessieren...
-
Habe das Problem jetzt umgangen (nicht glöst) da ich es nicht nachvollziehen konnte:
CInPlaceEdit::OnMouseActivate() gibt jetzt immer TRUE zurück...