コマンドボタンが押されているかを調べるには

解決


VB孝志  2007-10-06 06:49:15  No: 137706

VB6 SP6 でプログラムを作成しています。
コマンドボタンが押されているか、調べるには、どのようにすれば良いのでしょうか?

Value プロパティを Timer の中で調べるようにプログラムしてみたのですが、
ボタンを押してもValueプロパティがTrue になりません。
ご存知の方、宜しくお願いします。


特攻隊長まるるう  2007-10-06 19:10:19  No: 137707

ボタンの KeyDown イベントで vbKeySpace の時と、MouseDown イベントでフラグを立てて、
KeyUp イベントと MouseUp イベントでフラグを解除すると、
フラグの立ってる間がボタンが押されていると判断できるのでは?

>Value プロパティを Timer の中で調べるようにプログラムしてみたのですが
Command2 のクリックイベントで
    Command1.Value = True
とか書くと、Command1_Click が起こる。。。というような使い方をします。。。


特攻隊長まるるう  2007-10-06 20:01:12  No: 137708

Value プロパティのヘルプに
>ボタンが選択されているかいないかを示す値を設定します。値の取得も可能です。
と書いてあったので、テストしてみました。
[VB6.0 sp5]
Private Sub Command1_Click()
    Debug.Print Now & ":" & Command1.Value
End Sub

Private Sub Form_Load()
    Me.Timer1.Interval = 1000
End Sub

Private Sub Timer1_Timer()
    Debug.Print Now & ":" & Command1.Value & "[Timer]"
End Sub

>2007/07/06 10:49:26:True
>2007/07/06 10:49:26:False[Timer]
確かにクリックイベント内では True になっていますが、押しっぱなしにしても
True は継続されないようです。。。

・Microsoft Windows CE Toolkit for Visual Basic 6.0 
・Microsoft Windows CE Toolkit for Visual Basic 5.0 
ではフォーカスが当たっただけで True になるようですし。。。
http://support.microsoft.com/kb/180762/ja


VB孝志  2007-10-06 20:55:21  No: 137709

特攻隊長まるるうさん。

色々ありがとうございます。

今回やりたいのは、コマンドボタンが押されている間、
モータを回す(JOG動作)という事を行いたいのですが、
コマンドボタンを連打されると、なぜかMouseUpイベントが起きず、
モータが止まらないという現象が起きてしまいます。
(MouseDown イベントでモータを回す処理をし、MouseUpイベントでモータを止める処理
を行っています。)

そこで、TimerでコマンドボタンのValue を調べて押されていなかったら
モータを止める処理をしようと思ったのですが。。。

もう少し考えてみます。


特攻隊長まるるう  2007-10-06 22:18:17  No: 137710

>コマンドボタンを連打されると、なぜかMouseUpイベントが起きず、
そっちの原因を突き止めないと安定した動作にはならないのでは?
・DoEvents は入れていないですか?
・Enebled の変更をしてますか?
これらの命令は、よく使われている割に使用が難しく、適切な場所に
入れないとバグを生みます。
具体的なサンプルコードを示して質問したほうが良いのでは?


VB孝志  2007-10-07 00:48:56  No: 137711

特攻隊長まるるう様
ありがとうございます。

下記のようにコーディングしています。

Private Sub CmdXYDW_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

Debug.Print "押された"
        
    If Button = 2 Then Exit Sub
    if 処理中=1 then Exit Sub

    処理中=1
    
   Motor駆動処理
        |
        |
        |

End Sub

Private Sub CmdXYDW_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)

Debug.Print "Y_DW はなされた"

   Motor停止処理
        |

        |
        |

    処理中=0
    

End Sub

このプログラムだと、コマンドボタンが押されてモータ駆動の処理が
始まり、その途中で又、コマンドボタンが押されると又、モータ駆動処理
が始まってしまっているようです。

コマンドボタンが押された時、EnableをFalse にしてしまうと
MouseUp Eventが起きなくなってしまいます。

処理が終わるまで、コマンドボタンの入力を禁止する方法があるといいのですが。

宜しくお願いします。


通ってみた  2007-10-07 22:48:37  No: 137712

いっそCommandじゃなくてCheckにして、押しっぱなしではなくボタンの状態で判断しては如何でしょうか


我龍院  2007-10-09 18:04:58  No: 137713

Motor駆動処理に時間がかかる為、早押しした時MouseUpにすぐに処理が戻らないのでしょう。
2つ問題があって、一つは時間が掛かるMotor駆動処理の中にDoEventsを入れることが出来て、
Windowsに処理が戻せるかと言う点と、Motor駆動処理中にMouseUpがなされた時、処理を直ちに
終了できるかと言うことです。
いずれにしろこの点はブラックボックスとなっていて、アドバイスは出来ません。
Motor駆動処理がMotorOnなどというDll呼び出しになっている場合は、モーターのレスポンスが
悪いと言うことで、軽いJog動作は諦めるしかありません。


紅閃光  URL  2007-10-11 02:52:23  No: 137714

JOG動作と聞くとわたしの仕事でも聞く単語なので参考にでもなれば。
(VBでJOG動作のソフトは作ってはいないですけどね)

まず確認しておきたいのは、連打したときにMouseDownとMouseUpの数の回数が一致しない、ということですか?
それとも回数が一致しているのにモーターが停止しないということでしょうか?

もし後者であれば、Motor駆動処理(むしろ起動処理)が完了する前にMouseUpイベントがおきて、実質的にMotor停止処理が終わった後にMotor駆動処理が行われている可能性があるのではないでしょうか。

ひとつの案として、MouseUpイベントでStopFlagを立てることにしておき、
Motor駆動処理をStopFlagがTrueになるまでループするという方法はどうでしょうか。
ただし、MouseDownとMouseUpの数の回数が一致していることが前提となりますが。

Sub JOG+ボタンMouseUpイベント
    StopFlag = True
End Sub

Sub JOG+ボタンMouseDownイベント
    モーター起動処理

    Do Until StopFlag
        DoEvents
        Sleep(1)
    Loop

    モーター停止処理
    StopFlag = False
End Sub

また、同じモーターに対して+方向のJOG動作と−方向のJOG動作がある場合も同じような問題が出ることが考えられます。
(まぁ、複数のボタンをそんなにすばやく押し替えれる人もいないでしょうが)

ということも考慮して、もうひとつの案です。
(勝手にJOG動作に+と−があることにしてみたり)

Sub JOG+ボタンMouseDownイベント
    pJOGFlag = True
End Sub

Sub JOG+ボタンMouseUpイベント
    pJOGFlag = False
    StopFlag = True
End Sub

Sub JOG−ボタンMouseDownイベント
    mJOGFlag=True
End Sub

Sub JOG−ボタンMouseUpイベント
    mJOGFlag = False
    StopFlag = True
End Sub

Sub インターバルタイマーTimmerイベント
    Select Case True
        Case StopFlag
            モーター停止処理
            StopFlag = False
        Case pJOGFlag
            モーター正方向起動処理
            pJOGFlag = False
        Case mJOGFlag
            モーター負方向起動処理
            mJOGFlag = False
    End Select
End Sub

インターバルタイマーは0.1秒周期で事足りるでしょう。
(VBで0.05秒周期より短くするのは怖いです)
タイマーを常時動かしておくのが気分悪いというなら、JOG操作マスタボタンを追加して以下のようにするのもいいのでは。

Sub JOG操作マスタボタンClickイベント
    If JOG操作マスタ.BackColor <> vbButtonFace Then
        JOG操作マスタ.BackColor = vbButtonFace
        インターバルタイマー.Enabled = False 
        モーター停止処理            'もしものときの保険
    Else
        JOG操作マスタ.BackColor = vbRed
        インターバルタイマー.Enabled = True
    End If

    pJOGFlag = False
    mJOGFlag = False
    StopFlag = False
End Sub

ここにインチング動作やポジション移動動作が加わるとStopFlag以外のFlagをBoolean型以外にしたほうがいいかもしれませんけどね。

多少突っ込みどころもありますが、わたしならこうします。

なんにしろモーターがパソコンで直接制御されている場合もあれば、通信でやり取りする場合(ラグが多い)もあると思うので、モーターが動きっぱなしは危険ですよね。

「コマンドボタンが押されているかを調べる」ことができたとしても、連打対策は必要かと思います。

あ、ひとつ目の案でもAPIを使ってマウスボタン状態を取得し、マウスボタンが離されるまでループということでも十分かもしれませんね。

ちょっと筆が滑って書きすぎました><
(こんなつもりでは・・・)


ガッ  2007-10-11 08:25:34  No: 137715

むしろボタンのようなコントロールを自分で作ってしまうとか.
WindowsAPIのDrawFrameControlでそれっぽくかけますし.

それならサブクラス化でもいいか


VB孝志  2007-10-13 18:25:10  No: 137716

みなさま、本当に色々アドバイスありがとうございます。
すいません、出張ででてしまい、投稿が今日になってしまいました。

調べてみましたら、紅閃光さんのおっしゃる通り、Motor停止処理が終わった後にMotor駆動処理が行われている事がわかりました。

MouseDownとMouseUpの数の回数も一致していましたので、Motor駆動処理をStopFlagがTrueになるまでループするという方法でためしてみました。
見事、暴走は、なくなりました。

紅閃光さんはじめ、みなさま、本当にありがとうございました。
又、宜しくお願いします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加