Steuerung von Fußschalter oder Joystick
Um Ereignisse zu erfassen die von einem Fußschalter oder einem Joystick ausgelöst werden, kann man sich der Methoden von DirectX bedienen. Im vorliegenden Beispiel wird die Version DirectX8 verwendet, d.H. Sie benötigen einen gültigen Verweis auf die „DirectX 8 für Visual Basic Type Library“. Dazu benötigen Sie die registrierte Datei dx8vb.dll auf Ihrem Computer.
Nach dem nun der Verweis gesetzt wurde kann mit der Deklaration der Objekte begonnen werden. Dazu verwende ich die Early-Binding Variante um die DirectX-Konstanten verwenden zu können:
Im Deklarationsteil des Formulars:
Private Const BufferSize As Long = 10 Private DX As DirectX8 Private DI As DirectInput8 Private DIEnum As DirectInputEnumDevices8 Private DIDevice As DirectInputDevice8 Private hEvent As Long Implements DirectXEvent8
Im Load-Ereignis werden die Objekte dann Instanziert:
Set DX = New DirectX8 Set DI = DX.DirectInputCreate Set DIEnum = DI.GetDIDevices(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY) ' kein Gerät gefunden dann Abbruch If DIEnum.GetCount = 0 Then Exit Sub
Die Verwendeten Konstanten beim Zugriff auf die Geräte können hier nachgelesen werden:
DirectInput8::EnumDevices
In einer For-Schleife können jetzt alle gefundenen Geräte ausgelesen werden. Dabei helfen uns die beiden Methoden der DirectInputDeviceInstance-Klasse GetProductName und GetDevType um das richtige Gerät zu identifizieren, denn hier werden z.B. auch Tastatur und Maus aufgelistet.
For j = 1 To DIEnum.GetCount Debug.Print DIEnum.GetItem(j).GetProductName Debug.Print DIEnum.GetItem(j).GetDevType ' 66068 -> Fußschalter (Herga); 65812 -> Handschalter Gameport über Rockfire USB If DIEnum.GetItem(j).GetDevType = 66068 Or DIEnum.GetItem(j).GetDevType = 65812 Or DIEnum.GetItem(j).GetDevType = 66069 Then ' etc. Set DevInst = DIEnum.GetItem(j) Set DIDevice = DI.CreateDevice(DevInst.GetGuidInstance) End If Next j
Man muss also zuerst einmal das korrekte Gerät identifizieren, daher einmal durchlaufen lassen und im Direktfenster sich ansehen was die Debug.Print-Befehle geschrieben haben.
Nachdem man jetzt die richtige Geräteinstanz in DIDevice stehen hat, kann man nun das Top-Level verhalten der Access-Anwendung einstellen. Dazu benötigen wir als ersten Parameter das Handle der Access-Anwendung. Im 2. Parameter stehen verschiedene Flags die das Verhalten bestimmen.
Call DIDevice.SetCooperativeLevel(Application.hWndAccessApp, _ DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE)
Die Flags im 2. Parameter sind hier nachzulesen: DirectInput8::SetCooperativeLevel
Jetzt fehlen noch Angaben zur Speichergröße, und vorallem es muss ein Event-Handler erstellt werden um auf JoyStick- oder Fußschalter-Ereignisse zu reagieren.
Für letzteres haben wir ja die Variable hEvent deklariert.
diProp.lHow = DIPH_DEVICE diProp.lObj = 0 diProp.lData = BufferSize Call DIDevice.SetProperty("DIPROP_BUFFERSIZE", diProp)
Und hier der Code für das Event:
hEvent = DX.CreateEvent(Me) DIDevice.SetEventNotification hEvent
So, jetzt müssen wir nur noch mitteilen dass wir das Gerät benutzen wollen:
DIDevice.Acquire
Und dann wars das im Form_Load Ereignis. Im Prinzip funktioniert es bereits, doch wir haben noch keinen Eventhandler implementiert. Das wollen wir jetzt nachholen.
Im Eventhandler erhalten wir als übergebenen Parameter den eventid. Diesen benötigen wir eigentlich nur um zu prüfen ob auch das richtige Gerät das Ereignis ausgelöst hat.
Das auszuwertende Ereignis erhalten wir über die Methode GetDeviceData des Geräteobjektes, dessen erster Parameter ein Array ist welches nach dem Aufruf die vorhandenen Events beinhaltet.
Doch jetzt erst mal Code:
Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long) If Not (eventid = hEvent) Then Exit Sub Dim DevData(1 To BufferSize) As DIDEVICEOBJECTDATA Dim nEvents As Long Dim i As Long nEvents = DIDevice.GetDeviceData(DevData, DIGDD_DEFAULT) For i = 1 To nEvents If DevData(i).lData > 0 Then Select Case DevData(i).lOfs
Im Array DevData stehen also die gesuchten Events, und über die Eigenschaft DevData(i).lOfs werden diese als Zahlencode sichtbar.
Hier helfen auch wieder DirectX Konstanten. Mögliche Werte für „Select Case“ sind:
DIMOFS_X: Bewegung auf der X-Achse
DIMOFS_Y: Bewegung auf der Y-Achse
48: JoyStick Feuer Button 1
49: JoyStick Button 2
50: JoyStick Button 3
51: JoyStick Button 4
32: JoyStick kleiner x/y Steuerknopf
Um jetzt herauszubekommen ob ich mich auf der X-Achse nach links oder rechts bewege, liest man die lData Eigenschaft aus: DevData(i).lData
Das gleiche gilt auch für die Y-Achse. Der Eigenschaftswert lData hat ein Maximum von etwa 65000 in beiden Achsen. Um nun in einem Formular ein Steuerelement zu bewegen muss lData zuerst einmal auf die Formulargröße heruntergerechnet werden. Ich habe das so gelöst indem ich ein Rechteck (spielfeld) gezeichnet habe in dem sich das Objekt (ball) bewegen darf.
So ergibt sich der Faktor (jeweils in X und Y Achse):
faktorX = (Me.spielfeld.Width - Me.ball.Width) / 65000 faktorY = (Me.spielfeld.Height - Me.ball.Height) / 65000
Das Steuerelement (bei mir ein Fußball als Bild) lässt sich dann ganz einfach steuern:
Case DIMOFS_X Me.ball.Left = Me.spielfeld.Left + CLng(faktorX * DevData(i).lData) Case DIMOFS_Y Me.ball.Top = Me.spielfeld.Top + CLng(faktorY * DevData(i).lData)
So das wars auch schon mit dem Ausflug in die DirectX Welt. Beachtet dass mit anderen, insbesondere mit neueren Versionen von DirectX der Code nicht funktioniert.
Schaut euch die Beispiel-Datenbank an, ich habe dort noch ein paar Gimmicks eingebaut wie Schießen, Links und Rechts angeschnitten schießen etc.
Die Beispieldatenbank findet ihr im Downloadbereich.
Es gibt dazu auch von mir ein kleines Video auf Youtube:
bis dahin
2014 Andreas Vogt