1

フォーラムで次のクラス コードを見つけました。ゲームパッド (上、下、左、右) ではうまく機能しますが、ボタンのすべてのコードが欠落しています。空欄を埋められる人はいますか?

これは機能します:

Private Sub joystick1_Up() Handles joystick1.Up
    moveUp()
End Sub

これはしません:

Private Sub joystick1_buttonPressed() Handles joystick1.buttonPressed
    MsgBox(joystick1.btnValue)
End Sub

「buttonPressed」イベントがなく、書き方がわからないためです。

そして、ここにクラスがあります:

Imports System.ComponentModel
Imports System.Runtime.InteropServices


Public Class joystick
    Inherits NativeWindow

    Private parent As Form
    Private Const MM_JOY1MOVE As Integer = &H3A0

    ' Public Event Move(ByVal joystickPosition As Point)
    Public btnValue As String
    Public Event Up()
    Public Event Down()
    Public Event Left()
    Public Event Right()

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure JoyPosition
        <FieldOffset(0)> _
        Public Raw As IntPtr
        <FieldOffset(0)> _
        Public XPos As UShort
        <FieldOffset(2)> _
        Public YPos As UShort
    End Structure

    Private Class NativeMethods

        Private Sub New()
        End Sub

        ' This is a "Stub" function - it has no code in its body.
        ' There is a similarly named function inside a dll that comes with windows called
        ' winmm.dll. 
        ' The .Net framework will route calls to this function, through to the dll file.
        <DllImport("winmm", CallingConvention:=CallingConvention.Winapi, EntryPoint:="joySetCapture", SetLastError:=True)> _
        Public Shared Function JoySetCapture(ByVal hwnd As IntPtr, ByVal uJoyID As Integer, ByVal uPeriod As Integer, <MarshalAs(UnmanagedType.Bool)> ByVal changed As Boolean) As Integer
        End Function

    End Class

    Public Sub New(ByVal parent As Form, ByVal joyId As Integer)
        AddHandler parent.HandleCreated, AddressOf Me.OnHandleCreated
        AddHandler parent.HandleDestroyed, AddressOf Me.OnHandleDestroyed
        AssignHandle(parent.Handle)
        Me.parent = parent
        Dim result As Integer = NativeMethods.JoySetCapture(Me.Handle, joyId, 100, True)
    End Sub

    Private Sub OnHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
        AssignHandle(DirectCast(sender, Form).Handle)
    End Sub

    Private Sub OnHandleDestroyed(ByVal sender As Object, ByVal e As EventArgs)
        ReleaseHandle()
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = MM_JOY1MOVE Then
            ' Joystick co-ords.
            ' (0,0) (32768,0) (65535, 0) 
            '
            '
            '
            ' (0, 32768) (32768, 32768) (65535, 32768)
            '
            '
            '
            '
            ' (0, 65535) (32768, 65535) (65535, 65535)
            '

            Dim p As JoyPosition
            p.Raw = m.LParam
            ' RaiseEvent Move(New Point(p.XPos, p.YPos))
            If p.XPos > 16384 AndAlso p.XPos < 49152 Then
                ' X is near the centre line.
                If p.YPos < 6000 Then
                    ' Y is near the top.
                    RaiseEvent Up()
                ElseIf p.YPos > 59536 Then
                    ' Y is near the bottom.
                    RaiseEvent Down()
                End If
            Else
                If p.YPos > 16384 AndAlso p.YPos < 49152 Then
                    ' Y is near the centre line
                    If p.XPos < 6000 Then
                        ' X is near the left.
                        RaiseEvent Left()
                    ElseIf p.XPos > 59536 Then
                        ' X is near the right
                        RaiseEvent Right()
                    End If
                End If
            End If
        End If
        If btnValue <> m.WParam.ToString Then
            btnValue = m.WParam.ToString
        End If
        MyBase.WndProc(m)
    End Sub

End Class
4

1 に答える 1

2

古い winmm を使用する代わりに、代わりに XInput を使用します (または、可能であれば XNA を使用します)。

これを行うにはいくつかの方法があります。1 つのステップは、MSDN フォーラムのこの質問で概説されているように、XInput dll を直接使用することです。それでもかなり醜いです。おそらく、これを行うための「より簡単な」方法は、SlimDXSharpDXなどのラッパーライブラリを使用することです。

SlimDX または SharpDX を介して XInput を使用する利点の 1 つは、Windows 8 用の Windows ストア アプリ内でも機能することです:)。

これは、SharpDX の GamePad サンプルのスニペットです。

C#

var controllers = new[] { new Controller(UserIndex.One), new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four) };

// Get 1st controller available 
Controller controller = null; 
foreach (var selectControler in controllers) 
{ 
    if (selectControler.IsConnected) 
    { 
        controller = selectControler; 
        break; 
    }
}

VB

Dim controllers As New List(Of Controller)
controllers.Add(New Controller(UserIndex.One))
controllers.Add(New Controller(UserIndex.Two))
controllers.Add(New Controller(UserIndex.Three))
controllers.Add(New Controller(UserIndex.Four))

Dim controller as Controller = Nothing; 
For Each selectController In controllers
    If selectController.IsConnected Then
        controller = selectController
        Exit For
    End If
Next

次に、次を使用して状態を取得できます。

var state = controller.GetState();

XInput はより多くのポーリング モデルを使用していることに気付くでしょう。そのため、これを検出するには、ボタンの押下をときどきチェックする必要があります。継続的にポーリングする必要がある場合は、おそらくこれを行うために新しいタスクをスピンアップできます。

于 2012-12-07T00:32:05.783 に答える