初投稿になります。
まったりぃずです。よろしくお願いいたします。
質問はタイトルの通りです。
実行環境はVB6.0を想定しています。
処理イメージとしては、
・キーボードのボタン(例えばF11)が
押されている間だけ時間をカウントしていく。
・時間はフォームに一つテキストボックスを作成しそこに表示する。
・【難点】アクティブウィンドウに依存しない作りにする。
(作成したフォームに依存した作りなら簡単なのですが..)
以上です。
ご指導のほどよろしくお願いいたします。(^^;
F11の押下を拾いたいだけなら、
グローバルホットキーを使ってください。(難易度低)
任意のキーを拾いたいなら
グローバルキーフックしてください。(難易度中)
腕に自信があるなら、DDKでキー監視ドライバを作って、
直接I/Oを監視することも可能かと。(難易度高)
>Sayさん
ご回答ありがとうございます^^
ホットキーという言葉を知らなかったため
調べてみました。
これは便利ですね、たしかにこれを使えば
押された時に時間をカウントし始めることができそうです。
しかし、私の言葉が足りなかったかもしれませんが
これではボタンが離された時にカウントを止めるということが
できなそうです@@;
何か方法がございますでしょうか?
非常に短い押下時間を無視してよければ、
GetKeyState(API)をループで回したり、
タイマーで使ったりすればできるんじゃないかな?
他の方法(最終的に有料のOcxを使えって事になってるけど)
http://www.int21.co.jp/pcdn/vb/noriolib/vbmag/9905/gui/
>ぴろあきさん
ご回答ありがとうございます(^^
>非常に短い押下時間を無視してよければ、
>GetKeyState(API)をループで回したり、
>タイマーで使ったりすればできるんじゃないかな?
出来そうですね。
しかし、短い時間を無視・・というのは
「ボタンを押す→イベント開始」くらいの本当に短い時間にしたいのです。
そして、他APとの併用を考えているのでこちらのタイマーカウントに
あまりCPUを食べてほしくもありません^^;
>他の方法
これ以外に方法はないでしょうか?;;
よろしくお願いいたします。
>任意のキーを拾いたいなら
>グローバルキーフックしてください。(難易度中)
>腕に自信があるなら、DDKでキー監視ドライバを作って、
>直接I/Oを監視することも可能かと。(難易度高)
これに対する考えは?
>sasaさん
ご指摘ありがとうございます。
>Sayさん
返答遅れてすいません。
>任意のキーを拾いたいなら
>グローバルキーフックしてください。(難易度中)
こちらも難易度低と同様に、
ボタンが離された時のイベントを拾えないという認識です。
間違っているでしょうか?
>腕に自信があるなら、DDKでキー監視ドライバを作って、
>直接I/Oを監視することも可能かと。(難易度高)
DDKは現状全く知識が無い&難しいとのことなので
放置してしまってました@@; すいません。。
これから調べてみたいと思います。でも
この方法ならボタンが離されたことも監視できそうですね^^
どしどしご意見ご指摘よろしくお願いいたします。
グローバルフックはウィンドウメッセージを監視する事ができるので
キーダウン、キーアップの動作は拾えますよ。
適当にググッてヒットしたURLを貼っておきます
http://hp.vector.co.jp/authors/VA016117/hook.html
フックDLLにせよドライバにせよVBでは作れません。
VC++やMASMなどを使ってください。
ねんのため。
どこまでの精度を求めるかですよね。
タイマーのIntervalを10msec程度に設定して、
タイマーイベント内でGetKeyStateを使えば、
CPUもそれ程くわないだろうと思います。
ちなみに私の環境ではCPU使用率10%以下でした。
また、10msec以内の時間で、ボタンを押して離すという動作は、
人間には結構難しいです。
サンプルを作成して試してみればわかりますが、
かなり狙って短くボタンを押しても、検出する事ができます。
Private Sub Form_Load()
Timer1.Interval = 10
End Sub
Private Sub Timer1_Timer()
If (GetKeyState(&H7A) < 0) Then
MsgBox "F11キー押下"
End If
End Sub
残る問題は、時間カウントの精度ですが、
20msec程度のズレはありなのか、どうなのか・・・
>ちなみに私の環境ではCPU使用率10%以下でした。
1%以下の間違いです。すみません・・・
#Win2K,CPU350MHz
#タスクマネージャーでプロセス毎のCPU使用率をチェックした場合
ついでに補足すれば、
20msecなんて、
下まで押されているキーが、上にあがるまで程度の時間です。
何に使用するか知りませんが、問題にならないと私は思います。
作ってみました。
Private Declare Function GetKeyState Lib "User32.dll" (ByVal Key As Integer) As Long
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Private Sub Form_Load()
Timer1.Interval = 10
End Sub
Private Sub Timer1_Timer()
Static timeFlag As Boolean
Static startTime As Long
Static endTime As Long
If (GetKeyState(&H7A) < 0) Then
If timeFlag = False Then
startTime = timeGetTime
End If
timeFlag = True
Exit Sub
End If
If timeFlag Then
endTime = timeGetTime
MsgBox endTime - startTime & " mSec押下"
End If
timeFlag = False
End Sub
細かいけど、
Exit SubのところはElseでつなげた方がいいね。
> Exit Sub
>End If
>If timeFlag Then
> endTime = timeGetTime
> MsgBox endTime - startTime & " mSec押下"
>End If
>timeFlag = False
↓
Else
If timeFlag Then
endTime = timeGetTime
MsgBox endTime - startTime & " mSec押下"
End If
timeFlag = False
End If
>ぴろあきさん
レスが遅れて申し訳ありませんでした。。
サンプルコードまで作って頂いて、ありがとうございます><
試してみたところそれほど不自由には感じませんでした(^^
この案をベースとして活用していこうと思います!
しかし、技術者(ひよこですが。。)として
広い知識を身につけるべくしてSayさんから
ご指導頂いた内容も勉強して実装してみたいと思います(^^
お世話になったみなさま、心から感謝申し上げます。
そして少しでも読んで頂いたかたもありがとうございました^^
もう見ていないかもだけど、
ループで回してもCPU使用率1%以下でしたよ。
Private Declare Function GetKeyState Lib "User32.dll" (ByVal Key As Integer) As Long
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim StopFlag As Boolean
Private Sub Form_Load()
Show
Call TimeCount
End Sub
Private Sub TimeCount()
Static timeFlag As Boolean
Static startTime As Long
Static endTime As Long
Do
If (GetKeyState(&H7A) < 0) Then
If timeFlag = False Then
startTime = timeGetTime
End If
timeFlag = True
Else
If timeFlag Then
endTime = timeGetTime
MsgBox endTime - startTime & " mSec押下"
End If
timeFlag = False
End If
DoEvents
Call Sleep(1)
DoEvents
Loop Until StopFlag
End Sub
Private Sub Form_Unload(Cancel As Integer)
StopFlag = True
End Sub