Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

ermitteln welches STE als nächstes den Fokus hat

Begonnen von KonradR, November 03, 2024, 08:40:32

⏪ vorheriges - nächstes ⏩

KonradR

Hallo liebe Accessfreunde,

ich möchte ermitteln, welches Steuerelement als nächstes den Fokus bekommt. Klar, wenn ich eine Reihenfolge festlege, dann wird beim Betätigen der TAB-Taste das Steuerelement ausgewählt, das in der Reihenfolge festgelegt ist. Wenn ich jedoch mit der Maus auf ein anderes Steuerelement klicke, dann umgehe ich ja diese Reihenfolge. Wie kann ich für diesen Fall mit VBA vorsorgen und prüfen, ob das STE den Fokus hat, was in der Reihenfolge so vorgesehen ist oder ein anderes?

Ich sehe hir das Problem, dass wenn ich den Code zur Prüfung des STE, was gerade den Fokus hat, z.B. im After-Update-Ereignis von dem STE reinschreibe, was gerade den Fokus verliert, werde ich auch dessen Namen erhalten und nicht von dem STE, was gerade ausgewählt wird. Hier beißt sich für mich die Katze in den Schwanz. Habt ihr da eine Idee?

andyfau

Hallo Konrad,

hast Du schon mal versucht die Controls mit einer Schleife zu durchlaufen um die Eigenschaft
controlname.tabindex zu prüfen?

Beste Grüße
Andreas

PhilS

Zitat von: KonradR am November 03, 2024, 08:40:32Ich sehe hir das Problem, dass wenn ich den Code zur Prüfung des STE, was gerade den Fokus hat, z.B. im After-Update-Ereignis von dem STE reinschreibe, was gerade den Fokus verliert, werde ich auch dessen Namen erhalten und nicht von dem STE, was gerade ausgewählt wird. Hier beißt sich für mich die Katze in den Schwanz.
Wozu glaubst du das zu brauchen?
Ich vermute, dass es (mit Bordmitteln) nicht möglich ist, das Steuerelement zu ermitteln, was als nächstes den Focus bekommen wird, bevor Access tatsächlich versucht den Focus entsprechend zu verschieben.

Aber, nochmal, warum brauchst du das?
Die Validierung von eingegeben Daten macht man besser im BeforeUpdate-Ereignis. - Ich vermute, dass sich damit deiner Anforderung bereits erfüllen lässt.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Beaker s.a.

Hallo,

Der von Andreas angesprochene .TabIndex ist m.E. schon der richtige
Ansatz. Ich würde den in einer privaten Property im Form-Modul kapseln.
Beim Focuserhalt wird der aktuelle Index geprüft und entsprechend
gesetzt.

gruss ekkehard
Alles, was geschieht, geschieht.
Alles, was während seines Geschehens etwas anderes geschehen lässt, lässt etwas anderen geschehen.
Alles, was sich selbst im Zuge seines Geschehens erneut geschehen lässt, geschieht erneut.
Allerdings tut es das nicht unbedingt in chronologischer Reihenfolge.
(Douglas Adams)

PhilS


Zitat von: Beaker s.a. am November 03, 2024, 12:58:53Der von Andreas angesprochene .TabIndex ist m.E. schon der richtige
Ansatz.
Das glaube ich eher nicht.
Wie hilft das bzgl. der Situation mit der Maus, wie im OP geschrieben:
Zitat von: KonradR am November 03, 2024, 08:40:32Wenn ich jedoch mit der Maus auf ein anderes Steuerelement klicke, dann umgehe ich ja diese Reihenfolge. Wie kann ich für diesen Fall mit VBA vorsorgen [...]
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

knobbi38

Hallo Konrad,

du solltest das mal näher erläutern, wofür das gut sein soll. Es ist ja gerade ein Vorteil eines Formulars, daß beliebig darin herum gesprungen werden kann, alles andere wäre eine Gängelung des Anwenders.

Gruß
Knobbi38

KonradR

Zitat von: andyfau am November 03, 2024, 10:24:24hast Du schon mal versucht die Controls mit einer Schleife zu durchlaufen um die Eigenschaft

Danke für die Antwort. Und ja, mit dieser Vorgehensweise würde ich herausfinden, ob das STE, was als nächstes kommt nun den Fokus hat. Entscheidend für mich zu wissen ist, jedoch, hatte vorher ein ganz bestimmtes anderes STE den Fokus. Das bekomme ich mit dieser Vorgehensweise, glaube ich, nicht heraus.

KonradR

Zitat von: PhilS am November 03, 2024, 12:22:05Wozu glaubst du das zu brauchen?

Es geht einfach darum, dass ich in der Tab-Reihenfolge zwei aufeinanderfolgende Steuerelemente habe. Per SELECT-CASE-Anweisung habe ich folgendes festgelegt:
Private Sub txtZugabeMenge_Exit(Cancel As Integer)
    Select Case True
        Case IsNull(Me.txtZugabeMenge.Value) And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge und eine Zugabeinheit eingeben"
        Case IsNull(Me.txtZugabeMenge.Value) And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge eingeben"
        Case Me.txtZugabeMenge.Value = 0 And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge > 0 und eine Zugabeinheit eingeben"
        Case Me.txtZugabeMenge.Value = 0 And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge > 0 eingeben"
        Case Not IsNull(Me.txtZugabeMenge.Value) And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabeeinheit eingeben"
        Case Not IsNull(Me.txtZugabeMenge.Value) And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "SQL-String wird befüllt"
        Cancel = True
    End Select
End Sub

Wenn ich also vom STE txtZugabeMenge und einen Wert ausgefüllt habe und zum STE txtZugabeEinheit wechsle, dann erscheint immer die Meldung "Bitte eine Zugabeeinheit eingeben". Das ist etwas nervig, weil mir ja klar ist, dass ich noch was ausfüllen muss, wenn ich per TAB-Tast oder per Maus-Taste in das nächste STE wechsle und dort nun was ausfüllen will. Jetzt ist mir eingefallen, dass ich einfach die 5. Case Anweisung auskommentieren könnte. Das habe ich gemacht:
Private Sub txtZugabeMenge_Exit(Cancel As Integer)
    Select Case True
        Case IsNull(Me.txtZugabeMenge.Value) And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge und eine Zugabeinheit eingeben"
        Case IsNull(Me.txtZugabeMenge.Value) And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge eingeben"
        Case Me.txtZugabeMenge.Value = 0 And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge > 0 und eine Zugabeinheit eingeben"
        Case Me.txtZugabeMenge.Value = 0 And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabemenge > 0 eingeben"
'        Case Not IsNull(Me.txtZugabeMenge.Value) And IsNull(Me.txtZugabeEinheit.Value): MsgBox "Bitte eine Zugabeeinheit eingeben"
        Case Not IsNull(Me.txtZugabeMenge.Value) And Not IsNull(Me.txtZugabeEinheit.Value): MsgBox "SQL-String wird befüllt"
        Cancel = True
    End Select
End Sub

Und die Meldung verschwindet. War also doch einfacher als gedacht. Vielen Dank für eure Antworten. Es waren viele Inspirationen für mich dabei.

KonradR

Zitat von: Beaker s.a. am November 03, 2024, 12:58:53Der von Andreas angesprochene .TabIndex ist m.E. schon der richtige
Ansatz. Ich würde den in einer privaten Property im Form-Modul kapseln.
Beim Focuserhalt wird der aktuelle Index geprüft und entsprechend
gesetzt.

Das kann ich noch mal brauchen. Vielen Dank.

PhilS

Zitat von: KonradR am November 04, 2024, 06:12:08Es waren viele Inspirationen für mich dabei.
Dann möchte ich gerade noch eine weitere Inspiration nachschieben:

Dein aktueller Ansatz, eine Art Gültigkeitsprüfung im Exit-Event eines Steuerelements vorzunehmen, ist weder benutzerfreundlich noch zielführend.

Ein einzelnes Steuerelement für sich genommen, validiert man am besten im BeforeUpdate-Event des jeweiligen Steuerelementes. Den Datensatz als ganzes, also die Kombination aller Steuerelemente, validiert man am besten im BeforeUpdate-Event des Formulars. In beiden BeforeUpdate-Events kannst du über das Cancel Argument abbrechen und somit verhindern, dass der Benutzer eine ungültige Eingabe speichert.

Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Josef P.

Hallo!

Man könnte auch alle anderen Steuerelemente inaktiv setzen, wenn man den User in ein bestimmtes Steuerelement "locken" will.
z. B. nach Steuerelement "cbxIncoterms" bei "EXW" muss der Abholort eingetragen werden =>
Bei AfterUpdate/BeforUpdate werden alle anderen Steuerelemente inaktiv gesetzt und nur die Incoterm-Combobox und das Steuerelement für die Ortsangabe aktiviert.

Alternative (würde ich für obiges Beispiel machen):
Fokus automatisiert in die Ortangabe setzen und dort bei Verlassen prüfen, ob ein Wert vorhanden ist, wenn nicht, Msgbox mit Angebot einen Ort einzugeben oder den Incoterm zu wechseln.


Zitat... hatte vorher ein ganz bestimmtes anderes STE den Fokus.
Vielleicht hilft Screen.PreviousControl

Gruß
Josef




knobbi38

#11
Hallo Konrad,

ZitatDas ist etwas nervig, weil mir ja klar ist, dass ich noch was ausfüllen muss, wenn ich per TAB-Tast oder per Maus-Taste in das nächste STE wechsle und dort nun was ausfüllen will.
Es liegt ja bei dir, daß anders zu programmieren und ein entsprechendes Validierungsregelwerk aufzustellen.

In die Fokusbehandlung von Access sollte man nicht ohne Not eingreifen. Wie andere schon angemerkt haben, gehören Validierungen in die Before-Update Ereignisbehandlungsroutine, entweder in des Steuerelements oder des Formulars.

Über das Screen Objekt kannst du in Erfahrung bringen, welches Control vorher den Fokus besaß.

Gruß
Knobbi38

KonradR

Zitat von: PhilS am November 04, 2024, 08:40:45ist weder benutzerfreundlich

Danke für den Tipp. Kannst du noch genauer beschreiben, warum das benutzerunfreundlich ist, wenn der Datensatz leer ist? Denn wenn ich die Select-Case-Anweisung im BeforeUpdate-Event des jeweiligen Steuerelementes setze, wird sie ja dann dort und zu einem anderen Zeitpunkt ausgeführt. Oder ist sie an dieser benutzerfreundlicher, weil der Datensatz dann erst gar nicht gespeichert und später eventuell gelöscht oder die 0 editiert werden muss?

Zitat von: PhilS am November 04, 2024, 08:40:45Den Datensatz als ganzes, also die Kombination aller Steuerelemente, validiert man am besten im BeforeUpdate-Event des Formulars. In beiden BeforeUpdate-Events kannst du über das Cancel Argument abbrechen und somit verhindern, dass der Benutzer eine ungültige Eingabe speichert.
Viele Dank. Das ist das, was ich gesucht hatte. Das werde ich so umsetzen.

KonradR

#13
Zitat von: Josef P. am November 04, 2024, 08:57:37Man könnte auch alle anderen Steuerelemente inaktiv setzen, wenn man den User in ein bestimmtes Steuerelement "locken" will.
Das klingt auch interessant. Das ist ein Projekt für später. Jetzt mache ich erst mal die Variante, in der ich das aktive STE im Before-Update-Ereignis des Formulars prüfen.

Zitat von: Josef P. am November 04, 2024, 08:57:37Fokus automatisiert in die Ortangabe setzen und dort bei Verlassen prüfen, ob ein Wert vorhanden ist
Meinst du mit "Ortangabe" den Namen des STE's?

Zitat von: Josef P. am November 04, 2024, 08:57:37den Incoterm zu wechseln.
Meinst du mit Incoterm den Namen des STE's, dass dann den Fokus erhalten soll?

PhilS

Zitat von: KonradR am November 05, 2024, 06:02:57Kannst du noch genauer beschreiben, warum das benutzerunfreundlich ist,
Messageboxen sind ein einfaches Mittel für den Entwickler, um im Programmcode an der Stelle an der das Programm ein Problem entdeckt den Benutzer darüber zu informieren.

Für den Benutzer sind Messageboxen aber eine Unterbrechung seines gedanklichen und motorischen Ablaufs. Er muss seinen mentalen und motorischen Focus auf die Messagebox verschieben, um diese zu lesen und einen Button dort zu klicken.

Daher sollte man Messageboxen ausschließlich dann einsetzen, wenn es um einen Sachverhalt geht, den man dem Benutzer in genau diesem Moment mitteilen muss. Also, wenn etwas nicht weitergehen kann, ohne dass der Benutzer sich um ein Problem kümmert, oder wenn man dem Benutzer eine Information liefern möchte, auf die er (vermutlich) in diesem Moment wartet.

Dein ursprünglicher Ansatz mit den MsgBoxen im Exit-Event werden dem Benutzer angezeigt, wenn er nur durch die Steuerelemente navigiert. In diesem Moment also evtl. gar nicht den Anspruch hat, in dem aktuellen oder korrespondierendem Steuerelement etwas einzugeben.
Das BeforeUpdate-Event des Steuerelementes ist da besser geeignet, weil der Benutzer immerhin schon mal eine Änderung an dem Wert des Steuerelementes vorgenommen hat. - Auch hier könnte man überlegen, ob es nicht sinnvoller (benutzerfreundlicher) ist, wenn man das Problem anders kommuniziert, z.B. mit einer farblichen Markierung des/der Steuerelemente(s).
Erst im BeforeUpdate-Event des Formulars ist eine MsgBox (meistens) gerechtfertigt, weil das Programm keinen ungültigen/unvollständigen Datensatz speichern sollte.

Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor