Herunterdrücken von Schaltfläche abfangen



  • Hallo zusammen,

    ich habe mir im Resourcen-Editor eine Schaltfläche erstellt. Jetzt möchte ich gerne den Moment abfangen, an dem die Schaltfläche heruntergedrückt wird und den Moment, an dem die Schaltfläche wieder losgelassen wird.

    Das Loslassen der Schaltfläche kann ich einfach durch Hinzufügen der Behandlungsroutine von "BN_CLICKED" abfangen. Wie aber schaffe ich es, das Herunterdrücken abzufangen? Ich habe es mit der Nachricht WM_LBUTTONDOWN probiert, aber das hat nicht funktioniert, weil sich diese Nachricht nach meinem Verständnis auf mein Hauptfenster bezieht.

    Was muss ich tun, um das Herunterdrücken der Schaltfläche abzufangen?

    Grüße
    Steffen



  • was mir da so spontan einfällt, erstelle ne eigene klasse von CButton und nim dann LBUTTODOWN/UP um die nachrichten auszupussel.

    Wobei, hättest du geschrieben was du bezweckst, währe vielleicht ne andere lösung drin, aber ich weiss ja net was du bezweckst mit der aktion



  • Ich möchte beim Herunterdrücken der Schaltfläche eine Nachricht über die serielle Schnittstelle senden und beim Loslassen eine weitere.

    Hast Du da eine gute Idee, wie ich das anders bewerkstelligen könnte?





  • Aha, prima, so funktioniert's! Ich deklariere in meiner Dialogklasse meine abgeleitete Klasse und kann darin jetzt das Herunterdrücken und Loslassen abfangen.

    Allerdings möchte ich nun nicht in dieser Klasse die Bearbeitungsroutine für's Senden über die serielle Schnittstelle machen. Ich habe dafür bereits eine Funktion in einer anderen Klasse.

    Beispiel:
    Meine DialogKlasse, in der ich das Drücken der Schaltfläche bearbeiten möchte, heißt CMainProg. Dort ist meine neue abgeleitete Klasse CButtonAdvanced deklariert, die die Funktionen ::OnLButtonDown(...) und ::OnLButtonUp(...) enthält.

    Wie kann ich nun beim Aufruf von CButtonAdvanced::OnLButtonDown/Up(...) eine Memberfunktion von CMainProg aufrufen?

    Ich hatte folgendes gedacht:

    void CButtonAdvanced::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    	/************************/
    	/* Eigener Code: Beginn */
    	/************************/
    	// Beim Herunterdrücken der Schaltfläche die Klasse CMainProg benachrichtigen.
    	CMainProg::ButtonPressed(true);
    	/**********************/
    	/* Eigener Code: Ende */
    	/**********************/
    
    	CButton::OnLButtonDown(nFlags, point);
    }
    

    Das funktioniert aber nicht, weil er CMainProg nicht kennt.

    Was muss ich tun? Muss ich CMainProg bekannt machen? Falls ja, wie?



  • mehrere Optionen:

    1. eigens konstruierte Message Verschicken

    2. die Zielklasse direkt ansprechen, zb. über

    this->GetParent()
    

    - wenn deine Quellklasse ein Child davon ist - oder über eine eigens angelegte Member-Variable (OOP von feinsten)

    1. Header der Zielklasse in der Quellklasse einbinden, die benötigten Methoden public machen und mit dem Scope-Operator aufrufen (das ist unschön weil nicht objektorientiert)

    2. global sichtbaren Funktionspointer deklarieren und in der Zielklasse definieren, dann in der Quellklasse einfach aufrufen (bösartiger Hack, aber schöner als 3) )

    3. globale Message verschicken (nur Parent-Windows können diese empfangen!)

    4. IhrenbevorzugtenHackhierdazudenken 😃



  • Kannst Du mir Beispiel 2) näher erklären?

    CMainProg sieht bei mir so aus (Auszug):

    class CMainProg : public CDialog
    {
    // Konstruktion
    public:
    	CMainProg(CWnd* pParent = NULL);	// Standard-Konstruktor
    
    	// Dialogfelddaten
    	//{{AFX_DATA(CTest5Dlg)
    	enum { IDD = IDD_MAINPROG_DIALOG };
    	CButtonAdvanced	m_Button;		// Hier wird abgeleitete Klasse von CButton angelegt!
    	// ...
    	//}}AFX_DATA
    
    	// ...
    }
    

    In CButtonAdvanced habe ich jetzt folgendes ausprobiert:

    void CButtonAdvanced::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    	/************************/
    	/* Eigener Code: Beginn */
    	/************************/
    	// Beim Herunterdrücken der Schaltfläche die Klasse CMainProg benachrichtigen.
    	CWnd *pWnd;
    	pWnd=this->GetParent();
    	pWnd->ButtonPressed(true);
    	/**********************/
    	/* Eigener Code: Ende */
    	/**********************/
    
    	CButton::OnLButtonDown(nFlags, point);
    }
    

    Das funktioniert aber nicht, der Compiler sagt, "ButtonPressed" sei kein Element von CWnd. Die Funktion ist in CMainProg aber sehr wohl vorhanden. Also gehe ich davon aus, dass CWnd* einfach nicht auf CMainProg zeigt.

    Was mache ich falsch?

    Steffen

    P.s.: Der Weg über die Membervariable geht leider nicht, da ich den Zustand sofort abfangen und weiterbearbeiten muss.



  • Sorry, im Listing muss der Zeiger natürlich vom Typ CMainProg* anstelle von CWnd* sein. Allerdings sagt der Compiler mir nun, dass mir "GetParent()" ein CWnd* zurückgibt und der nicht auf CMainProg* gecastet werden kann...

    ...und nun?



  • void CButtonAdvanced::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    	/************************/
    	/* Eigener Code: Beginn */
    	/************************/
    	// Beim Herunterdrücken der Schaltfläche die Klasse CMainProg benachrichtigen.
    	CMainProg *pWnd;
    	pWnd=static_cast<CMainProg*>(GetParent());
    	pWnd->ButtonPressed(true);
    	/**********************/
    	/* Eigener Code: Ende */
    	/**********************/
    
    	CButton::OnLButtonDown(nFlags, point);
    }
    

    und das include auf deine hauptklasse net vergessen, muß gehen, ansonnsten
    mal Quelltext und Fehler Posten.



  • static_cast heißt also das Zauberwort. Kannte ich vorher noch nicht, ist aber genau das, was gefehlt hat! Jetzt klappt's!

    Vielen Dank für Eure Hilfe 🙂

    Steffen



  • öh ... ich will ja ned pingelig sein, aber einfach zu casten ist nicht nur unschön sondern auch fehlerhaft - unter bestimmten Vorraussetzungen wird dein Programm mit Fanfaren und Trompeten abstürzen.

    Man muss natürlich die eigentliche Klasse von CWnd ableiten ODER eine neue dieses Typs erstellen - alles andere ist mehr in Richtung "bösartiger Hack" und keineswegs zum Lernen oder gar für ein fertiges Programm gedacht.

    Lieber eine Klasse mehr im Paket als eine zu wenig und dafür Kompatibilität und Stabilität geopfert ... Ressourcen sind in rauen Mengen vorhanden, man muss schon lange nicht mehr die Bits zählen - solche Themen werden wenn überhaupt nur in grösseren Konzernen oder Forschungsinstituten interessant, und diese haben fast ausnahmslos sowieso ihre eigenen Coding Conventions

    static_cast heißt also das Zauberwort. Kannte ich vorher noch nicht, ist aber genau das, was gefehlt hat! Jetzt klappt's!

    Du kanntest static_cast nicht? Oha ... dann würde ich aber mal dringendst C++ lernen, und zwar bevor du dich an MFC ranwagst. Andernfalls wirst du im Laufe der Zeit grössere Probleme bekommen ...



  • static_cast kannte ich tatsächlich noch nicht. Ich komme aus der C-Ecke und da gibt es nur die "normalen" typecast.

    In den e-Books / Tutorials, über die ich mich in C++/MFC eingearbeitet habe ("C++ in 21 Tagen" und "Visual C++ in 21 Tagen") wurde static_cast nicht erwähnt. Ist er so grundlegend, dass ihn jeder kennt?



  • ja.

    das hier kann ich nur empfehlen, is zwar nur über C, behandelt aber auch die Unterschiede zu C++, deckt das allermeisste ab und ist zudem völlig kostenlos lesbar. Überhaupt sind eigentlich alle Bücher von Galileo nahezu uneingeschränkt zu empfehlen.



  • tha_specializt schrieb:

    öh ... ich will ja ned pingelig sein, aber einfach zu casten ist nicht nur unschön sondern auch fehlerhaft - unter bestimmten Vorraussetzungen wird dein Programm mit Fanfaren und Trompeten abstürzen.

    Man muss natürlich die eigentliche Klasse von CWnd ableiten ODER eine neue dieses Typs erstellen - alles andere ist mehr in Richtung "bösartiger Hack" und keineswegs zum Lernen oder gar für ein fertiges Programm gedacht.

    hast du schon mal Versucht als Parent eines Dialoges eine Klasse anzugeben die nicht von CWnd abgeleitet ist, geht nämlich nicht (oder nur mit bösen Hack), da wirst du einen bösen Fehler bekommen. das maximal was passieren kann is das kein Parent existiert, weil bei der erzeugung keiner angegeben wurde. Aber hier ging es ja nicht um Fehlerüberprüfung, ich geh davon aus das es das es jeder macht der mit Zeigern zu tun hat.



  • CTecS schrieb:

    hast du schon mal Versucht als Parent eines Dialoges eine Klasse anzugeben die nicht von CWnd abgeleitet ist, geht nämlich nicht (oder nur mit bösen Hack)

    Jo, und? Wie ich bereits sagte : Deswegen erstellt man eine neue Klasse oder baut die eigene um. So ist es von Microsoft gewollt, ergo Standard, so sieht es gut aus und bleibt stabil/sicher.

    CTecS schrieb:

    , da wirst du einen bösen Fehler bekommen. das maximal was passieren kann is das kein Parent existiert,

    Was?
    Oha ... also mein Übersetzer konnte es kurioserweise für mich dechiffrieren;
    Nö, da kann noch viel mehr passieren. Angefangen bei Nullpointer-Exceptions über Speicherzugriffsfehler bis hin zum totalen Systemabsturz weil gerade reservierte Speicherbereiche des Systems überschrieben werden und noch einiges mehr ... das gibt ganz böses Karma 😃

    CTecS schrieb:

    ich geh davon aus das es das es jeder macht der mit Zeigern zu tun hat.

    Da gehst du leider vom Falschen aus. Wenn man mit anderen Programmierern zusammenarbeitet hat so ne Aktion direkt mal Potential für Kloppe - ein Kollege wird - ohne dich ausgiebig zu kennen - deinen Code nicht verstehen, drauf los programmieren und kurz vor Abgabe wundert sich jeder dass die Software ständig abstürzt und/oder sonstige Macken hat.

    Bei MFC gilt : wer aus der Reihe tanzt und eigene Brötchen backen will muss sich mit dem geballten Fehlerpotential von Microsoft auseinandersetzen, deren Bibliotheken sind sehr stark auf bestimmte Programmierparadigmen ausgerichtet, da was verbiegen zu wollen erfordert entweder sehr viel Erfahrung oder sehr viel Mut 🙂

    Ein Kollege von mir kann das - der hat aber auch generell so einiges an zusätzlicher "Code-Last" weil er - für Normalsterbliche - unverständliche Fehlerquellen ausschliessen / abfangen muss.



  • tha_specializt schrieb:

    ... bis hin zum totalen Systemabsturz weil gerade reservierte Speicherbereiche des Systems überschrieben werden und noch einiges mehr ... das gibt ganz böses Karma 😃

    Wenn du dich mal mit Speichermanagement von Windows beschäftigen würdest, und dich mit MMU auskennen würdest, hättest du festgestellt das du auf Anwendungsebene nich auf Systemspeicher des Betriebssystemes schreiben darfst, das einzige wo du da rankommen würdest, ist als Treiber. Solche sachen sind seit einführung von MMU und Nutzung in Win NT und Aufwärts Geschichte. So meine Darstellung zum Thema Systemabstürze, aber du kannst ja mal ein Programm schreiben was nen Bluescrenn erzeugt und meinen Rechner zu neustart bewegt, aber bitte keinen Fake.

    in diesem Sinne, ne Systemabsturzfrei Woche



  • ohje .... jetzt werde ich auch schon beleidigt, natürlich inklusive Vermutungen und Unterstellung einer Inkompetenz; mit solchen Menschen kann man leider niemals kommunizieren - also viel Spass noch beim "Auskennen"



  • tha_specializt schrieb:

    ohje .... jetzt werde ich auch schon beleidigt, natürlich inklusive Vermutungen und Unterstellung einer Inkompetenz; mit solchen Menschen kann man leider niemals kommunizieren - also viel Spass noch beim "Auskennen"

    ich weiss ja net wo ich dich belkeidigt haben soll, ich wollte nur Darstellen das deine behauptung so einfach nicht stimmt und hab dir versucht die Gelegenheit zu geben diese zu wiederlegen. Wenn bei dir ne diskusion über ein thema schon ne beleidigung ist, na hallo, komm mal zurück auf die Erde


Log in to reply