Komplexes Problem mit Buttons (MFC)



  • Hi Forum,

    im folgenden möchte ich ein mehr oder minder komplexes Problem im Bezug auf Buttons in einem Dialog schildern. Sollte ich mich undeutlich ausdrücken, so bitte ich um eine kurze Rückfrage, ich werde dann versuchen deutlicher zu werden.

    Nun zum Thema: Ich habe einen Dialog mit einigen (11 um genau zu sein) Bitmap-Buttons erzeugt. Jeder Button hat zwei Stati, grün und rot. Für jede der beiden Farben gibt es entsprechend vier Ressourcen-Bitmaps für den jeweiligen Zustand (up, down, focus, disabled).

    Um die Buttonzustände zu steuern ohne jedesmal irrwitzige Codezeilen zu wiederholen und somit die Wartbarkeit zu erhöhen, habe ich eine Art "Wrapper" geschrieben. Diese Klassen ermöglichen es unter anderem, jedem Button beliebig viele weitere Status-Informationen hinzuzufügen.

    Die Ansteuerung der Buttons im Dialog mittels des genannten Wrappers funktioniert einwandfrei; die Ressourcen werden korrekt angesprochen.

    Nun liegt die eigentliche Schwierigkeit meines Problems auch an einer ganz anderen Stelle: Die Buttons sollen abhängig voneinander aktiviert bzw. deaktiviert werden. Ein Beispiel: Button 2 soll nur dann aktiv sein, wenn Button 1 aktiv ist. Button 4 soll nur aktiv sein, wenn Buttons 7 und 8 aktiv sind. (etc.)

    Diese Problemstellung mag einfach klingen, ich habe damit aber schon zwei Arbeitstage ohne Aussicht auf Erfolg zugebracht.

    Anfangs wollte ich es mit einer Matrix lösen. Das sah dann wie folgt aus:

    bool m_ButtonDependency[n][m];
    
    // Button 2 abhängig von Button 1
    m_ButtonDependency[2][1] = true;
    // Button 3 abhängig von Button 2
    m_ButtonDependency[3][2] = true;
    

    Ich denke, das Prinzip sollte an dieser Stelle klar sein: Die Matrix wird nach jedem Druck auf irgend einen Button überprüft und danach werden - ihr entsprechend - gewisse Buttons aktiviert oder deaktiviert.

    Aber genau dieses komplizierte Auflisten von Matrix-Einträgen (siehe Codebeispiel) will ich nicht!! - Ich würde am liebsten einen rein objektorientierten Ansatz realisieren, aber daran scheitere ich (noch). Aber dazu ein paar Überlegungen:

    Ich habe o.g. Wrapper-Klasse CDynamicBitmapButtonControl erstellt; diese kapselt beliebig viele Buttons, die wiederum beliebig viele Zustände kapseln. Nun existiert in der Dialogklasse eine Instanz dieser Wrapper-Klasse, die alle Buttons im Dialog steuert.

    Um irgendwie die Abhängigkeiten unter den Buttons einzubinden, könnte man eine Methode für jeden Button einmal aufrufen, die die entsprechenden Bedingungen/Abhängigkeiten im Objekt ablegt (z.B. void SetConditions(c) o.ä.). Im Detail (c) steckt hier das Problem: Wie kann ich die Bedingung bzw. den Ausdruck als Parameter übergeben, sodass der Code immer noch leicht zu lesen ist. Soll heissen: Ich möchte keine kryptische Syntax, ideal wären Anweisungen wie folgt:

    pCDynamicBitmapButtonControl->GetButton(1)->SetConditions("B1 || B2 && B7");
    

    Ich habe das Argument im obigen Beispiel mit Absicht schon als String formatiert: Das war nämlich mein bisheriger Ansatz! Ich wollte einen Parser schreiben, der oben genannte Syntax versteht und umsetzt. Prinzipiell wahrscheinlich auch für mich lösbar, aber sicherlich nicht unter dem Aspekt der Skalierung: Die Wrapper-Klasse soll - das ist eine unabdingbare Voraussetzung - beliebig viele Buttons steuern können; daraus ergibt sich unmittelbar, dass der Ausdruck, den der Parser "umsetzen" muss, beliebig lang sein kann.

    Und genau daran bin ich die ganze Zeit gescheitert: Ich habe absolut keine Ahnung, wie ich beliebig viele Ausdrücke verarbeiten soll (sorry, vielleicht fehlt mir nur der Ansatz).

    Also... wenn Ihr bis hierher durchgehalten habt, dann schon mal danke. Wenn Ihr die eine oder andere Idee habt, das Vorhaben umzusetzen, dann wäre ich schon für einen kleinen Denkanstoss dankbar!



  • Hm, warum tust du nicht die einzelnen Buttons in eine Verketteliste ?
    Such mal nach STL::List
    damit kannst du dann alle buttons mit einander vergleichen und hast ihre zustände.

    Ps. die Matrix würde sich mit int bestimmt umsetzen lassen...

    Devil



  • Hi devil,

    wie ich sehe, habe ich mich nicht klar ausgedrückt. Also die Buttons werden in einer verketteten Liste gespeichert, habe eine eigene geschrieben. Das ist auch nicht das Problem, das mich beschäftigt.

    Das mit der Matrix interessiert mich schon eher. Wie meinst Du das mit int?! Sorry, aber offenbar steh' ich auf'm Schlauch...



  • Hm. Laut deinem Text ist dein Problem nur beliebig lange Strings zu parsen. Wieso ist das ein Problem?

    Noch was anderes:
    Wenn Button 2 nur aktiv sein darf, wenn Button 1 aktiv ist und man Button 1 deaktiviert, dann hast du ein Problem, wenn du die Kondition in Button 2 festhälst.



  • Naja, wie waäre es wenn du für jeden Button einfach nen BOOL erstellst und ihm dann sagst das wenn Butoon aktiviert sein soll er BOLL FALSE machen soll und alle die eben noch damit zu tun haben, ansonsten eben TRUE und damit aktiv sein sollen.



  • @xyz44:

    das wäre meines erachtens "hart-verdrahtung"! funktionieren tut es, klar, ich hatte meinen dialog auch schon so weit (zu testzwecken). aber ich verfolge eine saubere lösung (näheres siehe unten). ausserdem hast du eventuell eine kleinigkeit übersehen: wie willst du denn nun umsetzen, dass jedes bool-flag richtig gesetzt wird?? entweder verdrahtest du es hart (für jeden button einzeln: schlecht wartbar und unübersichtlich) oder du hast eine lösung mit einer sauberen schnittstelle, auf die ich noch warte 😉 immer raus damit, bin ja für jede kritik/anregung offen!

    @deus:

    dein einwand ist prinzipiell vollkommen richtig (denke ich). ich will ja die bedingungen/abhängigkeiten nicht direkt "am button selbst" ablegen: vielmehr würde ich dazu die schon genannte klasse CDynamicBitmapButtonControl verwenden, die ja wiederum _alle_ Buttons inne hat. ein zugriff auf jeden button einzeln wäre damit ebenso möglich als sie auch direkt zusammen anzusteuern.

    zum thema "string parsen": es handelt sich um ein zeitkritisches projekt, und ich kann mich jetzt nicht hier an meinen arbeitsplatz setzen und tagelang einen parser coden-- das mal zum einen. zum anderen soll aber die implementierung der abhängigkeitslogik nicht "hart codiert" erfolgen, d.h. sie soll schön variabel und objektorientiert sein (d.h. ohne irgendwelche c-workarounds).

    ich weiss, dass ich die latte damit hoch lege, aber das sind eben die spezifikationen, die ich nicht ändern kann. wenn mir trotzdem jemand helfen könnte, wäre das klasse!



  • @CueDee:
    Uh, du stellst Anforderungen. Ich lass es mir in der Schule mal durch den Kopf gehen, vielleicht fällt mir was ein ...



  • Ach ja, noch was: Mit deinem Stringbeispiel von oben wärs wohl nicht getan. Damit machst du die Buttons nur voneinander abhängig, hast aber keinen Schimmer, wie diese Abhängigkeit aussieht!



  • Hm, ich hab mir jetzt folgendes überlegt:
    Eine Bedingung wurd durch eine structur repräsentiert. In der struct steht dann die Buttonnummer, von der der button abhängig ist und die art der abhängigkeit.

    Jeder Button hat zwei Listen. Eine Liste enthält die abhängigkeiten (Liste 1) . Die zweite Liste (Liste 2) enthält zeiger auf abhängigkeiten.

    Bsp:
    Ich setze für Button 2 eine Abhängigkeit der Art X. Er ist von Button 1 abhängig.
    Jetzt wird in Liste 1 von Button 2 diese Abhängigkeit reingeschrieben, wieder als struct.
    In Liste 2 von Button 2 wird ncihts geschrieben.
    In Liste 1 von Button 1 wird ncihts geschrieben.
    In Liste 2 von Button 1 wird ein Zeiger auf das oben eingefügte Element (Button 2 Liste 1) hinterlegt.

    Wenn jetzt der status eines buttons geändert wird, dann wird zuerst anhand von Liste 1 geprüft, ob diese änderung überhaupt zulässig ist und dann alle buttons, die von diesem Button abhängig sind anhand von Liste 2 geändert.

    Keine Ahnung, ob das ne sinnvolle Lösung ist, ist mir in Ethik eingefallen 😉


Anmelden zum Antworten