CWnd::SubclassWindow() Wie wird CWnd::Create() aufgerufen?
-
Sorry,
die Frage hatte ich schon einmal in einem anderen thread gestellt, aber ich komme hier irgendwie zu keiner Lösung. MSDN und google habe ich hierfür ebenso schon missbraucht.
Bin aber leider noch blutiger Anfänger und bekomme hier einfach keinen Durchblick. Daher bitte ich hiermit untertänigst um Hilfe!Ich habe eine Klasse
VideoWindow: public CWnd
In dieser kapsel ich durch subclassing ein durch eine OpenCV Funktion erzeugtes Fenster:
BOOL VideoWindow::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // Ueberpruefen ob gleichnamiges Fenster bereits existiert. // Wenn Fenster existiert wird es geschlossen. // if(IsWindow((HWND)cvGetWindowHandle(name)) == TRUE) cvDestroyWindow(name); // Durch OpenCV Erzeugtes Fenster skaliert sich selbst. // if(cvNamedWindow(name, CV_WINDOW_AUTOSIZE) < 1) throw UIException("Videofenster kann nicht erzeugt werden!"); // Window Handle vom erzeugten Fenster holen. WindowHandle = (HWND) cvGetWindowHandle(name); // Handle des Fensters an SubclassWindow() übergeben. // Damit wird das erzeugte Fenster an das // VideoWindow Objekt "angeheftet". // if(this->SubclassWindow(WindowHandle) == 0) { // Erzeugtes Fenster kann nicht angehangen werden, daher wird es wieder // zerstört. cvDestroyWindow(name); throw UIException("Videofenster kann nicht erzeugt werden!"); } return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); }
Nun möchte ich irgendwann in meiner Anwendung dieses Fenster erzeugen, weiß aber leider nicht wie ich dieses realisieren kann. Ich habe es mit dem folgenden Konstrukt probiert:
// Aufruf von VideoWindow::Create() // VWindow.Create( NULL, pApp->Data.getWindowName(), WS_BORDER | WS_VISIBLE, CRect(0,0, a, b), this, 1212 ); // a und b bei CRect() gebe ich der Übersichtlichkeit halber mal extra an: // a= cvGetCaptureProperty(pApp->Data.getVideoCapture(), CV_CAP_PROP_FRAME_WIDTH); b= cvGetCaptureProperty(pApp->Data.getVideoCapture(), CV_CAP_PROP_FRAME_HEIGHT);
...wie zu erwarten funktioniert das ganze jedoch nicht
. Ich erhalte immer folgende Assertion:
Debug Assertion Failed! (wincore.cpp, Zeile: 628) an dieser steht folgende
Assertion: ASSERT(pWnd->m_hWnd == NULL); // only do once...Mir schwant schlimmes
?!?!
Wie oder durch was wird dieses VideoWindow::Create() aufgerufen ? Bin am verzweifeln !!
-
Läuft das überhaupt in Deinen Code rein?
An welcher Stelle in Deinem Code kommt der ASSERT?
-
Hallo,
ich hab den Code wie folgt nochmal etwas verändert, da ich vergessen hatte name zu initialisieren bevor ich ein Fenster per cvCreateWindow(name) erzeugt habe. (name =""; // <--im Konstruktor nur leerer String). Allerdings war das leider nicht der Fehler, die Assertion tritt trotzdem auf.
Die Assertion tritt in der if-Schleife auf. Ok, d. h. SubclassWindow() war nicht erfolgreich. Die Assertion kommt daher sicherlich durch das cvDestroyWindow(name); Aber warum? Das Fenster wurde erzeugt, SubclassWindow() war nicht erfolgreich (warum weiß ich nicht), daher dürfte der Aufruf von cvDestroyWindow(name) doch eigentlich keine Probleme bereiten (das Fenster existiert ja noch).
BOOL VideoWindow::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // Ueberpruefen ob gleichnamiges Fenster bereits existiert. // Wenn Fenster existiert wird es geschlossen. // if(IsWindow((HWND)cvGetWindowHandle(lpszWindowName)) == TRUE) cvDestroyWindow(lpszWindowName); // Fenstername für zu erzeugendes Fenster setzen. name = lpszWindowName; // Durch OpenCV Erzeugtes Fenster skaliert sich selbst. // if(cvNamedWindow(name, CV_WINDOW_AUTOSIZE) < 1) throw UIException("Videofenster kann nicht erzeugt werden!"); // Window Handle vom erzeugten Fenster holen. WindowHandle = (HWND) cvGetWindowHandle(name); // Handle des Fensters an SubclassWindow() übergeben. // Damit wird das erzeugte Fenster an das // VideoWindow Objekt "angeheftet". // if(this->SubclassWindow(WindowHandle) == 0) { // ******* ASSERTION ******* tritt in der folgenden Zeile auf: // Erzeugtes Fenster kann nicht angehangen werden, daher wird es wieder // zerstört. cvDestroyWindow(name); throw UIException("Videofenster kann nicht erzeugt werden!"); } return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); }
Ist der folgende Aufruf von VideoWindow::Create() zum Erzeugen des Fensters korrekt?
// Aufruf von VideoWindow::Create() // VWindow.Create( NULL, pApp->Data.getWindowName(), WS_BORDER | WS_VISIBLE, CRect(0,0, a, b), this, 1212 ); // a und b bei CRect() gebe ich der Übersichtlichkeit halber mal extra an: // a= cvGetCaptureProperty(pApp->Data.getVideoCapture(), CV_CAP_PROP_FRAME_WIDTH); b= cvGetCaptureProperty(pApp->Data.getVideoCapture(), CV_CAP_PROP_FRAME_HEIGHT);
MfG
-
Gibt es im www irgendwo ein passendes Beispiel (source) wie man subclassing realisiert, bzw. mit welchen Parametern man ein Objekt dieser Klasse erzeugt ?
Bei letzterem weiss ich leider nicht so recht wie es gemacht werden sollte. Create() aufrufen oder an entsprechender Stelle eine Create-Nachricht schicken?
Wenn jemand ein passendes Codeschnippsel auf dem Rechner liegen hat und dieses hier posten könnte wäre ich sehr dankbar.
Grüße
-
Alles in der MFC geschieht über Subclassing. Ein Objekt wird angelegtund mit DDX_Control (welches SubclassWindow benutzt) wird an das Objekt das bestehnde Fenser gebunden.
Wenn Du einen ASSERT an dieser Stelle bekommst, dann ist diesem Fensterobjekt bereits ein Fenster zugeordnet (m_hWnd ist nicht mehr NULL).
Das prüft der ASSERT.Win CWnd Objekt ist nur eine Hülle um ein HWND Handle. Ein CWnd Objekt kann nur einmal einem Fenster zugerodnet werden, oder erzuget werden.
Beim erzeugen wird in Create das Handle durch die Windows API belegt. Wenn Du einen Subclass machst wird ein bestehendes Handle einem leeren Objekt zugeordnet.
Gleichfalls kann man auch ein Windows Handle nicht mehreren Objekten zurodnen...
-
Hallo Martin,
vielen Dank für deine Hilfe !! Ohne wäre ich echt aufgeschmissen (Das ganze ist für eine wichtige Arbeit und der Abgabetermin ist die kommende Woche
- bis dahin muss ich das ganze irgendwie laufen zum laufen bekommen
).
Ich hab das ganze nochmal probiert und bekomme nun:
Unhandled exception in meiner Anwendung: 0xC00000FD: Stack Overflow.Diese tritt an folgender Stelle auf:
// wincore.cpp///////////////////// CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd) { // ***** an dieser Stelle tritt der Fehler auf ***** CHandleMap* pMap = afxMapHWND(); CWnd* pWnd = NULL; if(pMap != NULL) { // only look in the permanent map - does no allocations pWnd = (CWnd*)pMap->LookupPermanent(hWnd); ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd); } return pWnd; }
Mir ist leider nicht klar, was ich falsch mache bzw. wo der Fehler liegt ?
-
...dauert manchmal etwas länger. D. h. das Fenster wurde schon ge-subclassed
. Wie komme ich nun an dieses dem Fenster zugeordnete CWnd Objekt?
-
Dann musst Du doch ach ds Objekt schon haben...
Wer hat das denn gesubclassed?Ansonsten CWnd::FromHandle!
-
Hab nochmal ein bisschen gegoogelt, durch:
CWnd *pWnd = CWnd::FromHandle((HWND) cvGetWindowHandle(name));
würde ich einen Zeiger auf dieses Fenster erhalten (wenn ich das richtig verstanden habe).
Wie oder Wo finde ich jetzt die Message Handler zu diesem Fensterobjekt, bzw. überhaupt erstmal dieses Fensterobjekt?
-
Du stellst Fragen!
Bei demjenigen, der dieses Fenser gesubclassed hat. Das muss doch jemand gemacht haben... Das passiert doch nicht einfach so...
-
Sorry,
ich habe aber leider keinen richtigen Durchblick bei der ganzen Sache.
Kannst du bitte mal ein minimales Beispiel hier rein stellen. Welche Funktionen ich benötige bzw. wie ich das Fenster aus meinem Dialog heraus erzeugen kann.
Ich komme hier irgendwie absolut nicht weiter.
-
Durch meinen Aufruf von
Vwindow.Create (NULL, pApp->Data.getName(), WS_BORDER | WS_VISIBLE, CRect(0,0, cvGetCaptureProperty(pApp->Data.getCaptureVideo(), CV_CAP_PROP_FRAME_WIDTH)), cvGetCaptureProperty(pApp->Data.getCaptureVideo(), CV_CAP_PROP_FRAME_WIDTH)), this, 1234 );
will ich das Fenster doch erst subclassen. Aber es scheint schon gesubclassed zu sein ????
-
Das entwickelt sich langsam zum Monolog
. Das Fenster existiert doch schon...ist der aufruf von Create() mit den ganzen Parametern (s.o.) überhaupt richtig um das Fenster zu erzeugen?
-
Dann ist VWindow doch das Objekt Deiner wahl und irgendwo ist Vwindow definiert und ene Message-Map drin.