Steuerelement in View



  • Hallo zusammen.

    Wie kann ich in meiner View ein Steuerelement unterbringen und auf dessen Events reagieren?

    Das Steuerelement sollte dynamisch angezeigt/versteckt werden können. Damit ihr euch mehr darunter vorstellen könnt, hier 2 Screenshots, die darstellen, was ich erreichen will:

    http://www.ras-kas.net/Pics/dtco01.jpg
    Zeigt das Diagramm ohne die Steuerelemente (normale Ansicht).

    http://www.ras-kas.net/Pics/dtco02.jpg
    Zeigt das Diagramm mit den gewünschten Steuerelementen (Modus zum verschieben der Diagramme gewählt).

    Meine Lösung sollte der gezeigten ziemlich ähnlich sein und es handelt sich auch bei mir um mehrere Diagramme/View.

    Wie kann ich nun solche Steuerelemente platzieren und auf Events reagieren und welche Elemente nimmt man da am besten?
    Konnte leider weder über die Suche noch über Google irgendwelche Hilfen finde.

    mfg,

    mike


  • Administrator

    Steuerelement Klassen

    In den jeweiligen Klassenbeschreibungen ist auch beschrieben, wie du diese Controlls selber erstellst.
    Um sie ein, bzw. auszublenden, verwendet die Funktion CWnd::ShowWindow(...), welche bei allen Steuerelementen dabei ist, da sie ja von CWnd abgeleitet sind. SW_SHOW zum anzeigen und SW_HIDE zum verstecken der Controls, der Funktion übergeben 😉

    Grüssli



  • Ok, werd mir das ganze nochmal genauer ansehen und mich bei etwaigen Fragen wieder hier melden 😉

    Danke erstmal.

    mfg



  • Soda, hab das anzeigen der Knöpfe nun hinbekommen, bin aber, wie versprochen, auf ein weiteres Problem gestoßen:

    Auf meiner View werden insgesamt 7 verschiedene Diagramme angezeigt (genaugenommen werden in der 1. möglichen Ansicht 4 und in der 2. Ansicht 3 Diagramme gezeigt, dh. die 7 Diagramme sind nie gleichzeitig sichtbar).

    Nun brauche ich die Button für jedes einzelne Diagramm, was ich folgendermaßen gelöst habe:

    Ich erzeuge 4 Button-Arrays, mit jeweils 7 Elementen. Im 1. Array sind die "Nach-Oben"-Button für jedes Diagramm gespeichert, im 2. die "Nach-Unten"-Button, usw.

    Das ganze sieht im Programm nach dem anzeigen der Button dann folgendermaßen aus:

    http://www.ras-kas.net/Pics/DTCOUpDowButtons.jpg

    Nun haben alle Button in Array 1 die ID "ID_BTN_UP", in Array 2 "ID_BTN_DOWN", damit ich nicht für jeden Button einen eigenen Event-Handler schreiben muss (wären ja dann 7 * 4 = 28).

    Die Events abonniere und behandle ich folgendermaßen:

    // Message-Map
    ON_COMMAND(ID_BTN_UP, &CDTCObserveView::OnButtonMoveUp)
    ON_COMMAND(ID_BTN_DOWN, &CDTCObserveView::OnButtonMoveDown)
    ON_COMMAND(ID_BTN_LEFT, &CDTCObserveView::OnButtonMoveLeft)
    ON_COMMAND(ID_BTN_RIGHT, &CDTCObserveView::OnButtonMoveRight)
    
    void xxx::OnButtonMoveUp()
    {...}
    
    void xxx::OnButtonMoveDown()
    {...}
    
    void xxx::OnButtonMoveLeft()
    {...}
    
    void xxx::OnButtonMoveRight()
    {...}
    

    Jetzt habe ich das Problem, dass ich im Event-Handler ja nicht mehr weiß, welcher Button gedrückt wurde (also auf welches Diagramm ich die Änderungen anwenden soll). Kann man dem Event-Handler irgendwie die ID des gedrückten Buttons als Übergabeparameter beibringen?

    Würde Momentan noch nichts bringen, da alle 7 "Nach-Oben"-Buttons die selbe ID "ID_BTN_UP" haben, aber das würde ich dann halt ändern.

    Komme aus der C#-Ecke und bin es von dort gewohnt, dass alle Events als Übergabeparameter ein Objekt Namens "sender" liefern...

    mfg

    mike

    ps.: Bitte nicht für die wahrscheinlich Grundlegenden Fragen steinigen. Kämpfe noch ein wenig mit der Umstellung von C# auf C++ und MFC 😉



  • Ja, wenn du mehreren Items die selbe ID gibst, lösen sie auch identische Kommandos aus. Du kannst aber den einzelnen Buttons auch aufeinanderfolgende IDs verpassen und sie dann über ON_COMMAND_RANGE() auf eine gemeinsame Handler-Methode umbiegen, die dann anhand ihres Parameters auswählt, welcher Button gedrückt wurde:

    ON_COMMAND_RANGE(ID_BTN_UP,ID_BTNUP+6,OnMoveUp)
    
    void xxx::OnMoveUp(UINT id)
    {
      //m_diagrams ist ein Array/vector von Diagrammen
      m_diagrams[id-ID_BTN_UP].move(up);
    }
    


  • Vielen dank für die rasche Hilfe.

    Hab natürlich noch eine weitere Frage:

    Wie kann ich nun geschickt die ID's vergeben? Bisher läuft das ja in einer Schleife:

    for (int i = 0; i < DIASETTINGSCNT; i++)
    		{
    		m_upButtons[i].Create("Up", WS_CHILD | WS_VISIBLE | BS_BITMAP, CRect(), this, ID_BTN_UP);
    		m_downButtons[i].Create("Down", WS_CHILD | WS_VISIBLE | BS_BITMAP, CRect(), this, ID_BTN_DOWN);
    		m_leftButtons[i].Create("Left", WS_CHILD | WS_VISIBLE | BS_BITMAP, CRect(), this, ID_BTN_LEFT);
    		m_rightButtons[i].Create("Right", WS_CHILD | WS_VISIBLE | BS_BITMAP, CRect(), this, ID_BTN_RIGHT);
    
    		m_upButtons[i].SetBitmap(m_upBtnBitmap);
    		m_downButtons[i].SetBitmap(m_downBtnBitmap);
    		m_leftButtons[i].SetBitmap(m_leftBtnBitmap);
    		m_rightButtons[i].SetBitmap(m_rightBtnBitmap);
    		}
    

    Kann ich das irgendwie beibehalten, dass die ID's durchnummeriert werden, oder muss ich da jetzt jede händisch vergeben?

    mfg



  • m_upButtons[i].Create("Up", WS_CHILD | WS_VISIBLE | BS_BITMAP, CRect(), this, ID_BTN_UP+i);
    ...
    

    (dabei mußt du nur darauf achten, daß die Teilbereiche sich nicht überschneiden - sprich: "#define ID_BTN_DOWN ID_BTN_UP+7" etc (zur Not manuell in der Ressource.h ändern)



  • Hm, so ganz verstehe ich das noch nicht:

    Warum ist die erste ID in deinem #define ID_BTN_DOWN und nicht ID_BTN_UP? Sorry, aber von der definition von Konstanten mit durchlaufenden Nummern hab ich (noch) keine Ahnung (wusst nichtmal, dass sowas geht ;))

    Hab jetzt mal folgende Variante versucht:

    Ressource.h:

    #define ID_BTN_UP ID_BTN_UP+7
    

    Leider funktioniert die folgende Anweisung dann nicht mehr:

    ON_COMMAND_RANGE(ID_BTN_UP, ID_BTN_UP+7,OnButtonMoveUp)
    

    Die Fehlermeldung ist: "'ID_BTN_UP': undeclared identifier"

    mfg



  • Schon klar, dass das pushen von Threads nicht gerne gesehen wird, aber nachdem dieser doch schon etwas älter ist und ich mir sicher bin, dass mir jemand hier helfen kann, wage ich es trotzdem 😉

    Wäre sehr nett, wenn mir noch jemand helfen kann und bitte nicht schlagen, wegen dem pushen...

    danke, mfg

    mike



  • Es bringt natürlich nichts, wenn du eine Konstante durch sich selber definierst. Den #define für deinen ersten Button-Block (ID_BUTTON_UP) solltest du besser so stehen lassen, wie er ursprünglich war (dürfte irgendwas mit ID_USER+x gewesen sein).



  • Also ich verstehe nur noch Bahnhof (wo kommt zB. die ID_USER jetzt her?)...

    Habs Momentan wieder so gelöst, dass ich einfach alle Button der Reihe nach in der Resource.h definiere:

    #define ID_BTN_UP1    101
    #define ID_BTN_UP2    102
    ...
    #define ID_BTN_UP4    104
    #define ID_BTN_DOWN1  105
    ...
    #define ID_BTN_DOWN4  108
    #define ID_BTN_LEFT1  109
    ...
    #define ID_BTN_LEFT4  112
    #define ID_BTN_RIGHT1 113
    ...
    #define ID_BTN_RIGHT4 116
    

    In der Message-Map sieht das so aus:

    ON_COMMAND_RANGE(ID_BTN_UP1, ID_BTN_UP1+3, &xxx::OnButtonMoveUp)
    ON_COMMAND_RANGE(ID_BTN_DOWN1,ID_BTN_DOWN1+3, &xxx::OnButtonMoveDown)
    ON_COMMAND_RANGE(ID_BTN_LEFT1,ID_BTN_LEFT1+3, &xxx::OnButtonMoveLeft)
    ON_COMMAND_RANGE(ID_BTN_RIGHT1,ID_BTN_RIGHT1+3,&xxx::OnButtonMoveRight)
    

    Und der Funktionskopf:

    void xxx::OnButtonMoveUp(UINT id)
    	{
    	int diaNr = id - 101; // - 101 weil die Up-Button mit 101 beginnen
        ...
        }
    

    Analog dazu sehen auch die Funktionen für ButtonDown, -Left und -Right aus (nur halt nicht mit -101 sondern halt -104, -108 und -112).

    Eigentlich wäre ich mit der Lösung ganz zufrieden, allerdings habe ich jetzt eine neue Problemstellung:

    Zur Laufzeit erzeuge ich ein Kontext-Menü mit variabler Anzahl von Einträgen (also zur Compile-Zeit nicht bekannt).
    Diesen neuen Einträgen muss ich natürlich auch eine ID verpassen, um den Klick im entsprechenden Event-Handler abzuarbeiten.

    Wie kann ich jetzt bewerkstelligen, dass alle Klicks auf die Einträge im selben Event-Handler landen und ich noch unterschieden kann, welcher Eintrag wirklich geklickt wurde (natürlich über die ID, aber ich weiß ja gar nicht, wie ich die ID's so dynamisch vergeben kann...)?

    mfg

    mike



  • @ID_USER: Ich war mir über die Vergabe der ID's nicht so ganz sicher (sorry), aber irgendwo vermerkt sich der Ressourcen-Editor, bei welcher ID er als nächstes weitermachen kann, wenn er statisch Elemente erzeugt. Und irgendwo steht auch der Bereich, ab dem du deine IDs von Hand anlegen darfst, ohne mit dem Ressourcen-Editor in Konflikt zu geraten.

    @Menü: Ich würde den einzelnen Items eine fortlaufende ID verpassen, beginnend bei einem vorher festgelegten ID_ITEM0 (das oberhalb aller anderen IDs liegen sollte). Anschließend fängst du über ON_COMMAND_RANGE(ID_ITEM0,INT_MAX,OnMenu) oder ON_COMMAND_RANGE(ID_ITEM0,ID_ITEM0+100,OnMenu) alle möglichen Menüpunkte ab und verarbeitest sie weiter - wenn tatsächlich ein Menüpunkt jenseits des aktuell höchsten Elements ankommt, kannst du ihn normalerweise ignorieren.

    PS: Wenn du schon die Konstanten hast, kannst du sie auch einsetzen:

    void xxx::OnButtonMoveUp(UINT id)
        {
        int diaNr = id - ID_BTN_UP; // - 101 weil die Up-Button mit 101 beginnen
        ...
        }
    

    (damit funktioniert dein Programm auch dann noch, wenn sich aus irgendeinem Grund deine IDs verschieben)



  • Ok, ich glaub jetzt hab ichs 😉 (zumindest so halbwegs).

    Bei meinen oben genannten Up-, Down-, Left- und Right-Button reicht jeweils die Definition der 1. ID (also ID_BTN_UP1, ID_BTN_DOWN1, ...). Funktioniert soweit.

    In den Funktionen hab ich auch wie von dir vorgeschlagen die ID's statt den statischen Zahlen eingefügt (auch klar, dass das Vorteilhaft ist).

    Auch die Sache mit meinen Menü-Einträgen sollte so klappen, allerdings hab ich da noch eine Frage:

    Ich muss ja der 1. ID (zB. ID_CONTEXT_MENUITEM1) eine Zahl zuweisen. Welche Zahl verwende ich da jetzt sinnvollerweise, damit ich zB. sichergehen kann, dass die nächsten 100 Zahlen frei bleiben (wie du bereits geschrieben hast, damit sich nichts mit dem Ressourcen-Editor überschneidet)?

    danke nochmal,

    mfg



  • Soda hab das ganze jetzt mal umgesetzt und es funktioniert auch soweit, also vielen dank zuerst mal an CStoll, der mir hier trotz meiner total Begriffsstutzigkeit weitergeholfen hat!

    Hab jetzt mal die ID 1100 benutzt, da danach länger mal nichts kommt. Mal schauen, ob das im weiteren Verlauf noch Probleme macht. Wenn ja weiß ich ja, wo ich suchen muss 😉

    mfg


Log in to reply