TimeGetTime関数を用いてキーの押下・解放の取得をしたい

タグの編集
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/1 14:35:37
TimeGetTime関数を用いて矢印キー(↑・↓・←・→)の押下・解放の取得をしたいです。
キーの押下・解放の取得のためには、KeyUp,KeyDownを使うことは理解しています。
また、矢印キー(↑・↓・←・→)のそれぞれの区別に関して、
KeyDownイベントで
If e.KeyCode = Keys.Up Then//↑なら

しかし、TimeGetTime関数の中にKeyDownイベント(矢印キーの条件分岐)そしてKeyUp,KeyDownを
書くことができないことはわかりました。


どうやったら、TimeGetTime関数の中にKeyDownイベント(矢印キーの条件分岐)そしてKeyUp,KeyDownを使ってそれぞれの矢印キーの押下・解放の時間の取得ができますか?

もしよろしければ、具体的にプログラムを書いて下さるとうれしいです
投稿者 shu  (社会人) 投稿日時 2018/11/1 16:01:17
書かれていることは
やりたいことではなく手段だと思うのですが
実際にやりたいことはなんでしょう?
別の方法があるかもしれません。
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/1 16:27:45
返信ありがとうございます。
説明がうまくなくすいません

実際にしたいことは、
矢印キー(上、下、左、右)それぞれ複数回押した時のリズムを取って、
ファイルに保存したいです。。

返答のほどよろしくお願いしまふ
投稿者 YuO  (社会人) 投稿日時 2018/11/2 02:50:41
timeGetTimeは「呼び出した時の時刻値」を取得する,Windowsに用意された関数(API)です。
Keyティーちゃんさんが作成する関数ではありません。

このため,
> TimeGetTime関数の中に
というようなことはできません。
もちろん,Windows APIであるtimeGetTimeを使わずに自前で書くなら別ですが……。


やりたいことは,
「矢印キーが押された・離されたタイミングでの時刻値を取得したい」
なのですから,KeyDown/KeyUpイベントのハンドラ関数中でtimeGetTimeを呼び出せばよいかと思います。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/11/2 08:50:10
> TimeGetTime関数
timeGetTime 関数ですね。先頭小文字な API なのでご注意を。
https://msdn.microsoft.com/ja-jp/library/cc428795.aspx

で。

timeGetTime は「Windows が起動してからの経過時間」を返すだけで、
キー入力とは無関係だと思いますよ。

「現在、キーが押されているかどうか」を調べるのであれば、
System.Windows.Input 名前空間の Keyboard クラスが持つ
GetKeyStates メソッドで判定できます。このメソッドは文字通り、
GetKeyState API を内部で呼び出しています。

以下サンプル。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=88699


また、今現在のキーの状態を見るのではなく、キー入力バッファからの
読み取りが必要なのであれば、DirectInput を試してみるのも良いと思います。
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/2 15:34:13
YuOさん、魔界の仮面弁士さん優しく説明してくださり、URLまで送ってくださりありがとうございます。

URLをみてもあまり理解できず。

もし、矢印キー ↑の押下・解放の時間を取得したい場合どのようにプログラムを書けばいいのでしょうか。

何度も理解できず、すいません
返答お願いします
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/11/2 18:11:47
> 矢印キー ↑の押下・解放の時間を取得したい

「時刻」の取得ではなく、
「時間」の取得なのですね。

ということは、何ミリ秒間押し続けていたのかが記録できれば良いのかな。

Public Class Form1
    Private Declare Function timeGetTime Lib "winmm" Alias "timeGetTime" () As UInteger

    Private Allows As New Dictionary(Of Keys, UInteger?)() From {
        {Keys.Up, Nothing},
        {Keys.Down, Nothing},
        {Keys.Left, Nothing},
        {Keys.Right, Nothing}
    }
    Private startTime As Date, startTick As UInteger

    Public Sub New()
        InitializeComponent()
        Controls.Clear()
        startTime = Now
        startTick = timeGetTime()
        Debug.WriteLine("----測定開始----")
    End Sub

    Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
        If Allows.ContainsKey(e.KeyCode) Then
            Dim tm1 = Allows(e.KeyCode).Value
            Dim tm2 = timeGetTime()
            Dim currentTime As Date = startTime.AddMilliseconds(CDbl(tm2 - startTick))
            Dim pushedSpan = (tm2 - tm1) / 1000.0
            Allows(e.KeyCode) = Nothing

            Debug.WriteLine(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 離 {1,-6} ({2:N3}秒間)", currentTime, e.KeyCode, pushedSpan))
        End If
    End Sub

    Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        If Allows.ContainsKey(e.KeyCode) AndAlso Allows(e.KeyCode) Is Nothing Then
            Dim tm = timeGetTime()
            Dim currentTime As Date = startTime.AddMilliseconds(CDbl(tm - startTick))
            Allows(e.KeyCode) = tm

            Debug.WriteLine(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 押 {1,-6}", currentTime, e.KeyCode))
        End If
    End Sub
End Class
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/2 19:53:28
仮面弁士さん、プログラムを書いていただきありがとうございます。


ほんとに初心者でなにもわからないのですが、
Debug.WriteLine(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 離 {1,-6} ({2:N3}秒間)", currentTime, e.KeyCode, pushedSpan))

はどこで表示されているのですか?

分からなくて、
 MessageBox.Show(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 押 {1,-6}", currentTime, e.KeyCode))
としたんですけど、メッセージボックスでてきて、押下と解放の時間がでてこず
仮面弁士さんがプログラムした
Debug.WriteLine(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 離 {1,-6} ({2:N3}秒間)", currentTime, e.KeyCode, pushedSpan))
をつかっての表示を教えてください

デザイナーのほうでなにか加えるのですか
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/11/4 22:15:05
> 押下と解放の時間がでてこず
マウスやキーボード系のイベント通知をテストする際には
メッセージボックスを用いてデバッグすることは避けてください。

メッセージボックスが表示されることで、マウスやキーボード操作が
奪われてしまい、イベント実行が阻害される要因となるためです。


> Debug.WriteLine(String.Format("{0:yyyy\/MM\/dd HH\:mm\:ss.fff} 離 {1,-6} ({2:N3}秒間)", currentTime, e.KeyCode, pushedSpan))
> ↑
> はどこで表示されているのですか?

Visual Studio の [デバッグ]-[ウィンドウ] メニューの中にある
[イミディエイト] または [出力] で表示されるウィンドウのいずれかに表示されます。

どちらのウィンドウに表示されるかは、[ツール]-[オプション]設定の
 デバッグ ▹ 全般 ▹ ☑出力ウィンドウの文字をすべてイミディエイト ウィンドウにリダイレクトする
の設定によって異なります。


Debug.WriteLine については、ここの本家ページで少しだけ解説されています。

Visual Basic 中学校 > 初級講座 > 第7回 繰り返し処理 #リスト9
http://rucio.a.la9.jp/main/dotnet/shokyu/standard7.htm


イミディエイト ウィンドウの使い方については、こちらをご覧ください。

Visual Basic 中学校 > 初級講座 > 第41回 実行の一時停止とデバッグ
http://rucio.a.la9.jp/main/dotnet/shokyu/standard41.htm
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/5 11:07:52
>Visual Studio の [デバッグ]-[ウィンドウ] メニューの中にある
[イミディエイト] または [出力] で表示されるウィンドウのいずれかに表示されます。

どちらのウィンドウに表示されるかは、[ツール]-[オプション]設定の
 デバッグ ▹ 全般 ▹ ☑出力ウィンドウの文字をすべてイミディエイト ウィンドウにリダイレクトする
 の設定によって異なります。

イミディエイトと出力の2つ、ツールからの設定で出力ウィンドのチェックを入れた場合と入れていない場合でテストしてみたのですが、まったく表示されません。
私のVBの設定がおかしいのでしょうか

イミディエイトの場合、デバッグしても表示されず
出力の場合、'test3.vshost.exe' (CLR v4.0.30319: test3.vshost.exe): 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_ja_b77a5c561934e089\mscorlib.resources.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
スレッド 0x1d08 はコード 259 (0x103) で終了しました。
スレッド 0x16ec はコード 259 (0x103) で終了しました。
と表示されるだけです。

コードのForm1のデザインの方はなにもしていないのですが。

せっかく魔界弁士さんがプログラムまで書いていただいたのに表示がなかなかうまくいかず悩んでいます。
投稿者 Keyティーちゃん  (学生) 投稿日時 2018/11/6 01:20:26
shuさん、YuOさん、そして丁寧にプログラム、説明していただいた魔界の仮面弁士さん
ありがとうございました。

無事に解決しました。
ほんとにありがとうございました