TComboBox-Objekt soll DropDown ausführen bei KeyUp mit Key == VK_RETURN, realisierbar? [gelöst]



  • Hallo Gemeinschaft,

    meine Frage ist schnell gestellt. Ich habe eine Ereignis-Methode ComboBoxKeyUp, die auf Tastatureingaben reagiert, wenn die ComboBox ausgewählt ist. Nun möchte ich, dass die ComboBox aufklappt sobald der Anwender "Enter" drückt. Habe leider Nichts ähnliches im Forum gefunden. Versucht habe ich, ComboBox->AutoDropDown auf true zu setzen, worauf die Liste auch kurz down dropt... leider geht sie sofort wieder zu - ich vermute, weil kein Eintrag in der Liste existiert, der mit "Enter" beginnt... Wie sollte das auch gehen... ?!
    Hat jemand einen Hinweis, wie ich die Liste down dropen und offen halten kann, sobald "Enter" gedrückt wird?

    MfG



  • Machs in der OnKeyPress, statt in der OnKeyUp...



  • Joe_M. schrieb:

    Machs in der OnKeyPress, statt in der OnKeyUp...

    Was soll ich dort machen? Ich habe doch keine Ahnung, wie ich aus dem Quelltext heraus die Liste der ComboBox öffnen kann!?! Deswegen fragte ich ja:

    Kolumbus schrieb:

    ... Hat jemand einen Hinweis, wie ich die Liste down dropen [...] kann, sobald "Enter" gedrückt wird?

    Kannst du vielleicht etwas mehr dazu beschreiben?

    Schönes WE schonmal 🙂



  • Ok, sorry, ich dachte, du hättest es prinzipiell schon gelöst und nur in das falsche Ereignis geschrieben...

    So sollte es funktionieren:

    if (Key == VK_RETURN)
    {
       Key = 0; // damit keine weitere Behandlung statt findet
       ComboBox->DroppedDown = true;
    }
    

    Schönes Wochenende!



  • Vielen Dank! 🙂

    Ich hab' grad nochmal in die Hilfe geschaut... eigentlich hätte ich das auch alleine finden können... 🙄 Manchmal bin ich echt betriebsblind. 😞

    MfG



  • So, nachdem DropDown nun aus dem Quellcode heraus gesetzt werden kann, funktioniert das Öffnen der Liste mittels Return-Taste. Nun soll allerdings die Liste wieder geschlossen werden, wenn Return ein weiteres Mal gedrückt wird... Kann nicht das Problem sein, dachte ich...

    void __fastcall TFormXYZ::ComboBoxKeyUp(TObject *Sender, WORD &Key,
    	  TShiftState Shift)
    {
    	if(Key == VK_RETURN){
    		if(Shift.Contains(ssShift))
    			//...
    		else{
    			Key= NULL;
    			TComboBox* vCmbBx= static_cast<TComboBox*>(Sender);
    			if(vCmbBx->DroppedDown == false)
    				vCmbBx->DroppedDown= true;
    			else
    				vCmbBx->DroppedDown= false;
    		}
    	}
    }
    

    ... da habe ich wiedereinmal falsch gedacht: Mit diesem Code, wird - bei ausgeklappter Liste - die Liste geschlossen, um gleich darauf wieder geöffnet zu werden. AutoCloseUp steht dabei auf false. Das ist mir ein Rätsel! 😕

    Nun dachte ich mir, dass vielleicht der Tastendruck 2mal verarbeitet wird, obwohl ich Key= NULL; (Key= 0; hatte ich auch schon) setze. Also habe ich die HelpType-Eigenschaft der ComboBox sozusagen als "Flag" genutzt. Damit überprüfe ich, ob die Box ausgeklappt werden muss, oder keine weitere Aktion (Box wird ja automatisch eingeklappt) durchzuführen ist:

    void __fastcall TFormXYZ::ComboBoxKeyUp(TObject *Sender, WORD &Key,
    	  TShiftState Shift)
    {
    	if(Key == VK_RETURN){
    		if(Shift.Contains(ssShift))
                        //...
    		else{
    			TComboBox* vCmbBx= static_cast<TComboBox*>(Sender);
    			if(vCmbBx->HelpType == htContext){
    				vCmbBx->HelpType= htKeyword;
    				vCmbBx->DroppedDown= true;
    			}
    			else
    				vCmbBx->HelpType= htContext;
    		}
    	}
    }
    

    Frage 1: Kann mir jemand erklären, warum sich die ComboBox in Verbindung mit dem 1. Codebeispiel so komisch verhält?

    Frage 2: Ist mein Vorgehen aus Codebeispiel 2 (vor dem Hintergrund dass ich für die ComboBox keine Hilfe vorgesehen habe) legitim?

    MfG



  • Nimm besser OnKeyPress, dann funktioniert das wie gewünscht. Frag mich nicht warum, aber OnKeyUp und OnKeyDown zeigen manschmal ein recht seltsames Verhalten...

    Du könstest Dir auch das if-Gedingse sparen (zumindest in der ersten Variante):

    vCmbBx->DroppedDown = !vCmbBx->DroppedDown;
    


  • Joe_M. schrieb:

    Nimm besser OnKeyPress, dann funktioniert das wie gewünscht.

    Dann kann ich aber TShiftState nicht mehr abfragen!?!

    Joe_M. schrieb:

    Frag mich nicht warum, aber OnKeyUp und OnKeyDown zeigen manschmal ein recht seltsames Verhalten...

    Vielleicht ist das des Rätsels Lösung:

    BDS2006-Hilfe schrieb:

    Eine Anwendung erhält für alle Tasten, die vom Anwender gedrückt werden, Windows-WM_KEYDOWN-Botschaften. Diese Botschaften lösen das Erignis OnKeyDown indirekt aus. Wenn Sie Key auf 0 setzen, verhindern Sie dadurch nur eine weitere Verarbeitung dieser Botschaft. Für Tasten, die Zeichen erzeugen, erzeugt Windows auch WM_CHAR-Botschaften. Zu dem Zeitpunkt, an dem Ihr OnKeyDown-Ereignis ausgelöst wird, befindet sich die WM_CHAR-Botschaft für die Taste bereits in der Botschaftswarteschlange. Das Setzen von Key auf 0 stoppt die Botschaft nicht, daher wird das Ereignis OnKeyPress ausgelöst. Sie müssen Key auf #0, setzen, um zu verhindern, dass das Steuerelement die WM_CHAR-Botschaft abfängt.

    Diese Art des Organisierens von Tastenverarbeitungen hat Vorteile. Quelltext, der sich nur mit Zeichen, einschließlich Zeichen wie #13 Zeilenschaltung, #3 für Strg+C usw., befasst, sollte in das Ereignis OnKeyPress aufgenommen werden. Quelltext, der sich mit Tasten befasst, die keine Zeichen erzeugen, sollte in das Ereignis OnKeyDown aufgenommen werden.

    Wie setze ich denn Key auf #0?

    Key= #0;
    

    erzeugt [C++ Fehler] XYZ.cpp(132): E2206 Ungültiges char-Zeichen '#' (0x23)...?

    Joe_M. schrieb:

    Du könstest Dir auch das if-Gedingse sparen [...]

    Yes, ich weiß, Danke. 🙂



  • Hallo

    Key = 0;
    

    Das # ist ein Fragment aus der Delphi-Syntax.

    bis bald
    akari



  • Hmmm, das hatten wir schon (siehe meinen vorletzten Post), trotzdem Danke für die Antwort.

    Wenn ich Alles hier zusammenfasse, muss ich wohl beide Ereignisse (OnKeyDown UND OnKeyPress) nutzen, um die gewünschte Funktionalität zu erreichen:
    * OnKeyDown: Shift + Enter = nächstes Steuerelement
    * OnKeyPress: Enter = Öffnen / Schliessen der DropDown-Liste

    Ich teste es mal so.



  • Das hier funktioniert keinesfalls:

    void __fastcall TFormXYZ::ComboBoxKeyDown(TObject *Sender, WORD &Key,
    	  TShiftState Shift)
    {
    	if(Key == VK_RETURN && Shift.Contains(ssShift)){
    		Key= 0;
    		TWinControl* NextCompo= NULL;
    		NextCompo= FindNextControl(ActiveControl, true, true, false);
    		NextCompo->SetFocus();
    	}
    	// der Focus wird auf die nächste Komponente gesetzt, ABER: die DropDown-Liste der ComboBox öffnet sich trotz Key= 0
    }
    
    void __fastcall TFormXYZ::ComboBoxKeyPress(TObject *Sender, char &Key)
    {
    	Key= 0;
    	TComboBox* vCmbBx= static_cast<TComboBox*>(Sender);
    	vCmbBx->DroppedDown= !vCmbBx->DroppedDown;
    	// die DropDown-Liste öffnet sich, ABER: wenn sie eigentlich geschlossen werden sollte, öffnet sie sich sofort wieder
    }
    

    Bisher ist und bleibt die Einzige funktionierende Version mein 2. Codebeispiel aus meinem 4. Post hier...



  • Die Problematik liegt ganz einfach in 2 Dingen:
    1. dass die TComboBox-Komponente auf die Enter-Taste schon von allein reagiert, sobald die DropDown-Liste eingezeigt wird, was nirgendwo bisher von mir nachzulesen war, aber eindeutig reproduziert werden kann.
    2. setzt man im OnKeyDown Key= 0, wird die WM_CHAR-Botschaft trotzdem an die ComboBox weitergeleitet.

    Und schon steht man da und rätselt...



  • Hmpf... Das ist ja ein Murks... Ich bekomme es aucb nicht ohne Zwischenvariable hin.

    Ich hab die Tag-Eigenschaft verwendet. Jetzt weiß ich zumindest, wofür die gut ist. 😉 Das Setzen von Key = 0 bringt irgendwie rein gar nichts, kann man also auch getrost weglassen.

    void __fastcall TForm1::ComboBox1KeyUp(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if (Key == VK_RETURN)
    	{
    		ComboBox1->DroppedDown = !ComboBox1->Tag;
    	}
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ComboBox1KeyDown(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if (Key == VK_RETURN)
    	{
    		ComboBox1->Tag = ComboBox1->DroppedDown;
    	}
    }
    //---------------------------------------------------------------------------
    

    Einzige andere Möglichkeit, die ich noch sehen würde, wäre die WM_CHAR-Botschaft abzufangen.



  • Joe_M. schrieb:

    [...]Ich hab die Tag-Eigenschaft verwendet. Jetzt weiß ich zumindest, wofür die gut ist. 😉 [...]

    Ich verwende diese Eigenschaft desöfteren. Z.B. habe ich in einer Anwendung ein Formular mit zahlreichen CheckBox-Komponenten und dazugehörigen ComboBox-Komponenten (zur Entwurfszeit auf dem Formular platziert). Nun soll eine ComboBox aktiviert werden, wenn ihre CheckBox gesetzt wurde. Damit der Code übersichtlich bleibt, soll das Ganze in nur einer Methode für alle CheckBox-Kompo's erfolgen. Also gebe ich jeder CheckBox ihrer zugehörigen ComboBox dasselbe Tag. In der Methode caste ich den Sender (CheckBox), hole mir den Tag-Wert, durchlaufe dann in einer Schleife alle Form-Komponenten und versuche sie als ComboBox zu casten. Gelingt der cast, kann ich die Tags vergleichen und wenn sie gleich sind, kann ich die ComboBox aktivieren. Fertig.

    Joe_M. schrieb:

    [...] Das Setzen von Key = 0 bringt irgendwie rein gar nichts, kann man also auch getrost weglassen. [...]

    Das meine ich! Ich vermute deshalb immernoch, dass der folgende Satz aus der Hilfe nicht einfach mit akari's Erklärung (Zitat: Das # ist ein Fragment aus der Delphi-Syntax.) abgetan ist:

    BDS2006-Hilfe schrieb:

    [...] Das Setzen von Key auf 0 stoppt die Botschaft nicht [...]. Sie müssen Key auf #0, setzen, um zu verhindern, dass das Steuerelement die WM_CHAR-Botschaft abfängt.

    Joe_M. schrieb:

    [...]

    void __fastcall TForm1::ComboBox1KeyUp(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if (Key == VK_RETURN)
    	{
    		ComboBox1->DroppedDown = !ComboBox1->Tag;
    	}
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ComboBox1KeyDown(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if (Key == VK_RETURN)
    	{
    		ComboBox1->Tag = ComboBox1->DroppedDown;
    	}
    }
    //---------------------------------------------------------------------------
    

    Warum nicht so:

    void __fastcall TForm1::ComboBox1KeyUp(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if(Key == VK_RETURN) ComboBox1->DroppedDown= !ComboBox1->Tag;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ComboBox1KeyDown(TObject *Sender, WORD &Key,
    		TShiftState Shift)
    {
    	if(Key == VK_RETURN) ComboBox1->Tag= ComboBox1->DroppedDown;
    }
    //---------------------------------------------------------------------------
    

    ???
    Wenn man sich schon für übersichtlichen Code einsetzt... 😉

    Joe_M. schrieb:

    [...]Einzige andere Möglichkeit, die ich noch sehen würde, wäre die WM_CHAR-Botschaft abzufangen.

    Ja, das würde gehen... das wäre aber das berühmte "mit Kanonen auf Spatzen schiessen". 🙂



  • Kolumbus schrieb:

    Warum nicht so:???
    ...
    Wenn man sich schon für übersichtlichen Code einsetzt... 😉

    Na ja, da waren noch ein paar mehr Anweisungen zum Testen drin... Außerdem würde ich höchstenfalls die Klammern weglassen, aber nicht den Vergleich und die Anweisung in die gleiche Zeile schreiben. Reine Geschmackssache...



  • Ja genau, das macht ja Jeder, wie es ihm am Besten passt.


Anmelden zum Antworten