Formular verliert Fokus

Moderator: ModerationP

Formular verliert Fokus

Beitragvon ClausM » 23. Aug 2021, 12:49

Hallo,

ich habe einen Kalender erstellt, der bis zum Schließen den Fokus behalten soll.
Egal welche Parameter ich setzte, bzw. wie ich das Formular aufrufe, es klappt nicht.
Meine Vermutung, es liegt an einem selbst definierten Ereignis (DatumSelektiert).
Ich habe einmal eine Testdatenbank erstellt, vielleicht hat einer von euch eine Idee.

LG
Claus
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
ClausM
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 125
Registriert: 16. Mär 2019, 10:28

Re: Formular verliert Fokus

Beitragvon Gast » 23. Aug 2021, 14:07

Ich kann Deine Testdatenbank nicht einsehen, Du könntest aber nach dem Ereignis den Fokus wieder auf das Formular lenken:
Code: Alles auswählen
docmd.selectobject acform, "FormName"
docmd.gotocontrol "ControlName"
Gast
 

Re: Formular verliert Fokus

Beitragvon Bitsqueezer » 23. Aug 2021, 19:31

Hallo,

es war nicht ganz einfach, die Ursache zu finden.

Das Problem ist, daß die Controls im Kalenderformular die Eigenschaft "Ist Hyperlink" auf "Ja" eingestellt haben. Damit versucht Access offenbar, den Inhalt als Hyperlink zu interpretieren und wechselt dann zum Anwendungsfenster.

Also einfach Hyperlink auf Nein stellen - dann bleibt der Fokus, wo er war.

Wenn Du schon einen Event definiert hast, warum öffnest Du das Formular dann mit "acDialog", läßt per Eventprozedur eine modulglobale Variable setzen, um sie nach dem Schließen des Kalenderformulares daraus zu entnehmen und die Textbox zu füllen? Viel verquerer geht's nicht...:)

Einfach die Eventprozedur in frmStart verwenden, um die Textbox zu füllen, denn genau das ist eventgesteuerte Programmierung. Nicht der Click-Event des Kalenderbuttons soll auf das Ergebnis warten, indem "acDialog" die Codeausführung totlegt. Der Kalenderbutton soll den Kalender aufrufen, nicht mehr, das ist sein Job. Der Kalender gibt über den Event das Ergebnis an frmStart zurück und die Eventfunktion "DatumSelektiert" setzt dann das Ergebnis.

DoCmd.OpenForm reduziert sich dann auf den Namen und die OpenArgs-Übergabe. Wenn Du willst, kannst Du die Eigenschaft "Modal" im Kalender hinzufügen, dann bleibt der Fokus dort, bis der Kalender geschlossen wird.

Gruß

Christian
Bitsqueezer
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 8462
Registriert: 21. Jun 2007, 12:17

Re: Formular verliert Fokus

Beitragvon ClausM » 24. Aug 2021, 10:45

Hallo Christian,

vielen Dank für Deine Antwort.
Hat soweit funktioniert.

Wenn Du schon einen Event definiert hast, warum öffnest Du das Formular dann mit "acDialog"

Ich habe gedacht, genau für so ein Konstellation ist "acDialog" vorgesehen. Die Eigenschaften Modal und PopUp werden auf Ja gesetzt und die Verarbeitung hält an.
Oder habe ich das falsch verstanden?

läßt per Eventprozedur eine modulglobale Variable setzen, um sie nach dem Schließen des Kalenderformulares daraus zu entnehmen und die Textbox zu füllen

Stimmt in diesem Beispiel, es werden manchmal aber auch mehrere Daten, z. B. Bis- und Von-Datum, abgefragt.

Der Kalenderbutton soll den Kalender aufrufen, nicht mehr, das ist sein Job. Der Kalender gibt über den Event das Ergebnis an frmStart zurück und die Eventfunktion "DatumSelektiert" setzt dann das Ergebnis.

Habe ich umgestellt.

LG
Claus
ClausM
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 125
Registriert: 16. Mär 2019, 10:28

Re: Formular verliert Fokus

Beitragvon Bitsqueezer » 24. Aug 2021, 15:56

Hallo,

Ich habe gedacht, genau für so ein Konstellation ist "acDialog" vorgesehen. Die Eigenschaften Modal und PopUp werden auf Ja gesetzt und die Verarbeitung hält an.
Oder habe ich das falsch verstanden?


Das hast Du völlig richtig verstanden, aber macht hier keinen Sinn, da Dein Kalenderformular (=Kalenderklassenmodul) ja einen sauberen Event liefert, so daß Dein Kalenderbutton nur das Formular aufrufen muß und sich danach nicht mehr darum kümmern muß. Egal also auch, wenn der Benutzer "Abbrechen" klickt, denn Dein Code würde ja dann immer noch versuchen, die Modulvariable in das Textfeld zu übernehmen.

Das ist ja genau das Schöne an Events: Dein Formular reagiert nur dann, wenn ein Event gestartet wurde. Und die Entscheidung darüber wird vom Kalenderformular bestimmt. Das sagt: Löse den Event aus, wenn auch wirklich ein Datum ausgewählt wurde. Wenn "Abbrechen" geklickt wurde - dann nicht.

Somit passiert im aufrufenden Formular auch nur dann etwas, wenn es zu dem Event gekommen ist.

Für eine "Von"/"Bis"-Auswahl kannst Du einfach zwei Events definieren, entsprechend kann Dein Kalender dann ein Von-Datum und ein Bis-Datum per Event zurückliefern.

So sind beide Formulare komplett entkoppelt. Dein Button-Code muß nicht wissen, was nach dem Schließen des Kalenders passiert. Und der Kalender muß nicht wissen, ob und wer auf den Event reagiert. Er sendet nur die Nachricht, DASS etwas passiert ist (und welcher Wert dabei herauskam) und kann dann geschlossen werden. So könnten theoretisch über den gleichen Event auch x Formulare das ausgewählte Datum erhalten - oder gar keins. Du kannst also auch den Kalender alleine aufrufen und ein Datum auswählen, ohne daß es zu einem Fehler kommt.

Gruß

Christian
Bitsqueezer
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 8462
Registriert: 21. Jun 2007, 12:17

Re: Formular verliert Fokus

Beitragvon ClausM » 25. Aug 2021, 13:03

Hallo Christian,

jetzt komme ich doch noch einmal auf das Öffnen mit "acDialog" zurück.
Wenn ich, anders als im Beispiel, die Dokumentenregisterkarten anzeigen lasse, dann muss ich doch das Formular mit "acDialog" öffnen?


Für eine "Von"/"Bis"-Auswahl kannst Du einfach zwei Events definieren, entsprechend kann Dein Kalender dann ein Von-Datum und ein Bis-Datum per Event zurückliefern.

Wie würdest Du das machen?
Ich habe das jetzt einfach über den Titel im Formular gelöst.
Code: Alles auswählen
Sub cmdOk()
Select Case Left(Caption, 3)
  Case "Bis"
    RaiseEvent DatumBisSelektiert(MdatAuswahlDatum)
  Case "Von"
    RaiseEvent DatumVonSelektiert(MdatAuswahlDatum)
  Case Else
    RaiseEvent DatumSelektiert(MdatAuswahlDatum)
End Select
DoCmd.Close acForm, Name
End Sub



Der Kalender wird zum Teil über verschiedene Buttons in einem Formular angesprochen und der Code soll ja in der Eventfunktion (DatumSelektiert) stehen, wie unterscheide ich dann die "Aufrufer", Modulvariable?


Der Kalender wird auch in einem UFO verwendet, allerdings habe ich den Code ins HFO verfrachtet, weil ich den Verweis auf das UFO nicht hin bekommen habe.
So klappt es.
Code: Alles auswählen
  Set Forms("HFO").PcalKalender = Me

Funktioniert das überhaupt und wie kann ich auf das UFO verweisen?
Mit "." oder "!", in eckigen Klammern oder ohne, es kommt immer die Meldung, dass das Formular nicht gefunden wird.
Code: Alles auswählen
Set Forms("HFO!Control-UFO!UFO").PcalKalender = Me


LG
Claus
ClausM
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 125
Registriert: 16. Mär 2019, 10:28

Re: Formular verliert Fokus

Beitragvon Bitsqueezer » 25. Aug 2021, 14:14

Hallo,

Wenn ich, anders als im Beispiel, die Dokumentenregisterkarten anzeigen lasse, dann muss ich doch das Formular mit "acDialog" öffnen?


"die Dokumentenregisterkarten" - was soll ich mir darunter vorstellen, wo es ja nicht im Beispiel enthalten war?
Aber die Antwort lautet: Nein. Weil die immer Nein lautet. In einer eventgesteuerten Programmierung hat acDialog nichts zu suchen.

Wie würdest Du das machen?
Ich habe das jetzt einfach über den Titel im Formular gelöst.


Ich würde eine Eigenschaft im Kalenderformular erstellen (Property oder Public Variable), die definiert, was Du auswählen willst. Das gleiche übrigens auch für die Parameter, die Du hier per OpenArgs übergibst. Denn wenn man kein acDialog verwendet, kann man die Eigenschaften des dann geöffneten Kalenderformulares nach DoCmd.OpenForm noch einstellen, da der Code ja dann weiterläuft bis zum Ende der Click-Sub.

Entsprechend kannst Du bei einem Event "DatumSelektiert" bleiben und übergibst als zweiten Parameter den Wert der Property (Name z.B. "Auswahlart"). Dann brauchst Du nur einen Event, der muß dann bei Klick auf "OK" auch nur als zweiten Parameter "Me.Auswahlart" übergeben.
(Eleganter noch, wenn Du eine Public Enum für die Auswahlart einbaust und die Enum als Datentyp angibst.)

In der Eventprozedur kannst Du dann sowas machen:
Code: Alles auswählen
Private Sub PcalKalender_DatumSelektiert(ByVal datValue As Date, ByVal AuswahlArt As Enm_Auswahlart)
    Select Case AuswahlArt
        Case Enm_Auswahlart.Von
            Me.txtDatumVon = datValue
        Case Enm_Auswahlart.Bis
            Me.txtDatumBis = datValue
        Case Enm_Auswahlart.Einzeldatum
            Me.txtDatum = datValue
    End Select
End Sub


Der Kalender wird zum Teil über verschiedene Buttons in einem Formular angesprochen und der Code soll ja in der Eventfunktion (DatumSelektiert) stehen, wie unterscheide ich dann die "Aufrufer", Modulvariable?


Nein, genauso wie oben. Property im Kalender definieren, einen Wert übergeben und im Event einen weiteren Parameter zurückgeben, der dann in der Eventprozedur unterschieden werden kann.

Ein Problem in Deinem Code ist auch das:
Code: Alles auswählen
Set Forms(Split(OpenArgs, "|")(1)).PcalKalender = Me


Das widerspricht der Objektentkopplung, weil Du aktiv auf ein anderes Formular als das Kalenderformular zuzugreifen versuchst. Du verhinderst einen Fehler hier nur, indem Du OpenArgs abfragst, ob es gesetzt wurde oder nicht.

Stattdessen solltest Du die Zuweisung da machen, wo sie benötigt wird: Im aufrufenden Formular. Entsprechend vergiß mal DoCmd.OpenForms, das verwendet man für solche Zwecke nicht. Stattdessen verwendest Du die objektorientierte Variante, da Du ja ohnehin schon eine modulglobale Variable "PcalKalender" hast, die völlig richtig als spezifisches Klassenmodul "Form_dfrm_Kalender" deklariert ist.

Also muß der Code zum Öffnen des Kalenders lauten:
Code: Alles auswählen
Private Sub cmdKalenderVon_Click()
    Set PcalKalender = New Form_dfrm_Kalender
    With PcalKalender
        .AuswahlArt = Enm_Auswahlart.Von
        .AusgabeIn = Me.ctl_DatumVon
        .Visible = True
    End With
End Sub


Im Unterschied zu DoCmd.OpenForm kannst Du hier VOR dem Öffnen des Formulares (also genauer: bevor es sichtbar wird) bereits die Parameter definieren.

Es gibt immer unterschiedliche Wege nach Rom, hier wurde jetzt einfach die Referenz auf das Control an das Kalenderformular übergeben. Und wenn man das so macht, dann braucht man die Auswahlart gar nicht mehr zu bestimmen oder zurückzugeben, außer Du möchtest abhängig davon unterschiedliche Titel oder Beschriftungen oder Hinweistexte etc. im Kalender definieren.

Da die Referenz auf das Control dem Kalenderformular nun bekannt ist, könnte es bei Klick auf OK einfach selbst den Wert in das Control schreiben. Nachteil der Methode ist, daß der Kalender wieder abhängig von einem Aufruf ist, der ein Control definiert hat. Daher kann man auch einfach die Auswahlart (die Enum) um eine entsprechende Menge Einträge erweitern. Wenn Du etwa sagst, daß Du ein Feld "Bestelldatum", "Änderungsdatum", "Lieferdatum" hast, dann könntest Du dafür jeweils Einträge in die Enum des Kalenders schreiben und mit Select Case dann im Formular (wie oben gezeigt) unterscheiden, wo das Datum hingeschrieben werden soll. Hätte aber den Nachteil, daß Du für JEDE Art von Datum je einen Eintrag brauchst und die Einträge ständig erweitern müßtest.

Es wäre daher eine andere denkbare Lösung, einfach eine Integerzahl an "AusgabeIn" zu übergeben und dem Event als dritten Parameter hinzufügen. Dann kann wiederum im Formular die Zahl ausgewertet werden und in das betreffende Datumsfeld geschrieben werden. Im Formular kann man dazu dann auch wieder eine Enum deklarieren, die hier Private wäre. Heißt: Das Kalenderformular bekommt eine Zahl 1 für Bestelldatum, 2 für Änderungsdatum und 3 für Lieferdatum - aber nur von DIESEM Formular. Und nur DIESES Formular wertet die Zahl im Kalenderevent wieder aus, mit oder ohne Enum, und weiß selbst, wofür 1,2,3 hier steht. Ein anderes Formular hat vielleicht stattdessen 2,7,15 übergeben und bekommt eben auch nur 2,7,15 zurück und weiß, wofür welche Zahl steht. Damit bist Du maximal flexibel, brauchst nur einen Event und kannst den Kalender beliebig verwenden. Und dem Kalender ist es egal, was mit dem selektierten Datum geschieht.

Mit der objektorientierten Methode funktioniert es dann auch problemlos im UFO, weil eben nun nicht mehr das Kalenderformular die Objektvariable setzt, sondern der UFO-Code selbst.

Die Adressierung eines UFOs wäre übrigens:
Code: Alles auswählen
Set Forms("HFO").UFOContainerControl.Form.PcalKalender = Me


Was aber keinen Sinn macht, denn wenn das UFO noch ein UFO enthält, stehst Du wieder im Regen. Mit anderen Worten: Kalender nix zugreifen auf Aufrufer. Nie.

Gruß

Christian
Bitsqueezer
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 8462
Registriert: 21. Jun 2007, 12:17

Re: Formular verliert Fokus

Beitragvon ClausM » 26. Aug 2021, 13:27

Hallo Christian,

vielen, vielen Dank für Deine Unterstützung, ohne Dich hätte ich das nicht geschafft.
Habe soweit alles umgesetzt, mit 3 Parametern und Enumeration, und es läuft alles.

D A N K E!!!

LG
Claus
ClausM
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 125
Registriert: 16. Mär 2019, 10:28

Re: Formular verliert Fokus

Beitragvon Bitsqueezer » 26. Aug 2021, 17:06

Hallo Claus,

immer gern... :)
Freut mich, wenn's läuft. Und umgesetzt hast Du es ja selbst...

Gruß

Christian
Bitsqueezer
Im Profil kannst Du frei den Rang ändern
 
Beiträge: 8462
Registriert: 21. Jun 2007, 12:17


Zurück zu Access Forum (provisorisch)

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 18 Gäste