Probleme mit PreTranslateMessage....evtl.Überlauf!



  • Hallo,
    schreibe unter VS6.0 an einer SDI-Anwendung mit diversen Dialogen und Unterdialogen.

    Befindet sich der Mauszeiger in einem Unterdialog über einem Steuerelement, so soll im Hauptdialog in einem Edit-Fenster ein Hinweis (und in einem Picture-Element evtl. ein Bild).
    Hierfür habe ich in jedem Unterdialog die PreTranslateMessage folgendermaßen eingefügt, z.B.

    // ----------------------------------------------------------------------------
    BOOL CDataLink::PreTranslateMessage(MSG* pMsg) 
    // ----------------------------------------------------------------------------
    {	
    	// Lokala Instanz* auf "Hauptdialog"
    	CKonfigurationDlg *pParent =	((CKonfigurationDlg*)GetParent());
    
    	// ------ Anzahl der zu überprüfenden Elemente
    	int AnzElemente;
    	AnzElemente = 15;	
    
    	// ------ ID jedes Steuerelementes (dieses Unterdialoges) auslesen und in Array schreiben
    
    	int nID[15];								// Anzahl der zu überprüfenden Steuerelemente	
    	nID[0]	=	IDC_RADIO_CAN;                  //1026
    	nID[1]	=	IDC_RADIO_COM;                  //1027
    	nID[2]	=	IDC_RADIO_STANDARD;             //1029
    	nID[3]	=	IDC_RADIO_EXTENDED;             //1030
    	//.... normalerweise noch mehr.....		
    
    	// wurde die Maus bewegt?
    	if (pMsg->message == WM_MOUSEMOVE || WM_NCHITTEST)
    	{
    		// ------ Mauszeiger im Nirgendwo --> dann folgenden HINT anzeigen	und LOGO anzeigen
    		pParent->m_strHint	=	H_STANDARD;
    
    		// ++ Genesys-Logo als Standard anzeigen
    		pParent->m_bmpHint.DeleteObject();
    		pParent->m_bmpHint.LoadBitmap(IDB_BMP_GENESYS_LOGO);
    		pParent->m_ctlPicHint.SetBitmap(pParent->m_bmpHint);
    
    		// ++ Hauptdialog aktualisieren
    		pParent->UpdateData(FALSE);
    
    		// ------ Alle IDs der Elemente durchgehen und Handle vergleichen
    		for ( int i = 0; i < AnzElemente; i++)
    		{
    			if (pMsg->hwnd == GetDlgItem(nID[i])->m_hWnd)	// Handle vergleichen
    			{
    				// ------ Über welchem Element befindet sich die Maus
    				switch (i)
    				{
    				case 0:		// Radio CAN
    					pParent->m_strHint = "Select this option to use the CAN-bus interface for transmitting data";
    
    					// Bild Testweise
    					pParent->m_bmpHint.DeleteObject();
    					pParent->m_bmpHint.LoadBitmap(IDB_GIJON);
    					pParent->m_ctlPicHint.SetBitmap(pParent->m_bmpHint);
    					break;
    
    				case 1:		// Radio COM
    					pParent->m_strHint = "Select this option if you use the COM-Port for data transmission.";
    					break;
    
    				case 2:		// Radio Standard
    					pParent->m_strHint = "The ADMA uses CAN messages with a standard identifier (11 bits wide).";
    					break;
    
    				case 3:		// Radio Extension
    					pParent->m_strHint = "The ADMA uses CAN messages with an extended identifier (29 bits wide).";
    					break;
    
    //  normalerweise noch die restlichen......	
    
    				default:	// hier kommt man eigentlich nie rein --> wenn AnzElemente stimmt
    					// Default
    					pParent->m_strHint = "Um über eine Eingabe mehr zu erfahren, bitte mit der Maus über das entsprechende Steuerelement fahren";
    					break;
    				}
    			}			
    		}	
    		// Hauptdialog aktualisieren
    		pParent->UpdateData(FALSE);
    
    		// ComboBox schließt automatisch bei Aufruf der PreTranslateMessge im Parent 
    		// -> Hotkeys nur möglich wenn Focus NICHT auf ComboBox
    		if (pMsg->hwnd != GetDlgItem(IDC_COMBO_CAN_BAUDRATE)->m_hWnd)
    		{
    			// Die PreTranslateMessage von CKonfigurationDlg aufrufen
    			// -> hier werden die Hotkeys verwaltet
    			pParent->PreTranslateMessage(pMsg);
    		}
    
    	}
    	return CDialog::PreTranslateMessage(pMsg);
    }
    

    Das funktioniert so weit auch ganz gut. Hinweise und Bilder werden wie gewünscht angezeigt.

    ABER, bei längerem Verfahren der Maus über die Steuerelemente (Hints und Bilder verändern sich) verliert mein Dialog, bzw. Steuerelemente (Edits,...) ihre Farbe. Der ganze Dialog verhält sich sehr suspekt. Message-Boxen werden in großer Schrift dargestellt (ähnlich Windows 3.1) und so....!

    Kommentiere ich die PreTranslateMessage aus passiert dies nicht!
    Von daher denke ich das es hier zu einem Überlauf oder sonst etwas kommt? 😕
    Bin aber echt planlos wie ich dem Fehler auf die Schliche kommen kann?

    Vielleicht hat ja jemand von Euch eine Idee. Wäre klasse.

    Schon mal Danke.

    Gruss
    S.



  • Das liegt daran, dass Windows die Ressourcen ausgehen ( GDI-Handles / User-Handles ). Prüfe in deiner Anwendung ob alle Ressourcen, die in einen DC selektiert werden, vor der Freigabe des DC wieder in den ursprünglichen Zustand sind, und dass alle Objekte entsprechend Ihrer API wieder freigegeben werden:

    Bsp:

    CClientDC dc( this );
    
    CFont fTest;
    fTest.CreateFont( ... );
    
    // Unbedingt altes Objekt merken oder mit SaveDC arbeiten.
    CFont* oldfont = dc.SelectObject( &fTest );
    
    //.. Hier Code
    
    // vor dem Löschen bitte altes Objekt wieder in den DC selektieren,
    // damit keine Referenzen mehr auf fTest zeigen.
    dc.SelectObject( oldfont );
    
    // Jetzt font löschen. ( Dieser Schritt ist optional, wenn
    // das Objekt die Resource im Destruktor freigibt, schadet aber nix )
    dc.DeleteObject();
    

    Evtl. liegts an der Erstellung der Bitmaps in PreTranslateMessage.

    Du kannst die Verwendung der GDI und USER Handles über den Taskmanager oder
    den ProcessExplorer von Sysinternals ( www.sysinternals.com ) nachvollziehen.
    Bei deiner Anwendung werden mit der Zeit immer mehr Handles belegt aber keines mehr freigegeben. Windows hat z.B. ein Limit von ca. 10000 GDI Objekten pro Prozess. Wenn Windows die Handles ausgehen, werden die Elemente mit Standardschrift o.ä dargestellt.

    Von Microsoft gibts was freies mit dem man den "Verbrauch" von GDI Handles nachvollziehen kann:
    http://msdn.microsoft.com/msdnmag/issues/03/01/GDILeaks/default.aspx

    Um die Fehler zu finden, kann man z.B. Rational Purify oder Boundschecker einsetzen. Die sagen einem dann wo man vergessen hat, ein Resourcenhandle freizugeben.



  • Hallo tvdog,
    Danke für die schnelle Antwort. 👍
    Ist ja der Wahnsinn in was für Schwierigkeiten man sich als "Anfänger" bringen kann. Meine Güte, da habe ich ja noch was vor mir.

    Werde Deine Tipps mal versuchen in die Tat umzusetzen....hoffentlich klappts dann.

    Nochmal vielen Dank.

    Gruss
    S.


Anmelden zum Antworten