フォームを高速で連打したときイベントが発生しない(XP,VB6)
コマンドボタンを高速で連打したときとは、ちゃんとコマンドボタンのクリックイベントが発生するのに、フォームを高速で連打したときは、フォームのクリックイベントが発生しないことがあります(と言うか、反応が間に合わないようです)。
下のコードで試したら分かると思いますが、前者と後者では連打したときのリストボックスに項目が追加されていくスピードが違うと思います。同じ簡単な処理なのに、何故なのでしょうか?
どうにもならないことなのでしょうか。
フォームをいくら高速でクリックしても、ちゃんとクリックイベントが発生するようにするにはどうすればいいでしょうか? 何かいい方法がないものでしょうか。
どうか、ご教授のほどよろしくお願い致します。
Private Sub Command1_Click()
List1.AddItem "aaa"
End Sub
Private Sub Form_Click()
List1.AddItem "aaa"
End Sub
> 何故なのでしょうか?
フォームには DblClick イベントがありますが、
ボタンにはそのイベントが無いから、とか。
ご回答ありがとうございます。
> フォームには DblClick イベントがありますが、
> ボタンにはそのイベントが無いから、とか。
下のようにMouseDownイベントに置いても、クリックイベントに置いたときと同じ結果に・・・
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
List1.AddItem "aaa"
End Sub
実は、フォームに自分でボタンの絵を描画して独自コマンドボタンみたいなものを作ろうとしていたのですが、フォームのMouseDownイベントにボタンが凹む絵を描く処理を置き、MouseUpイベントにボタンが上がる絵を描く処理を置いて実現しようとしたのですが、ゆっくり押したときはうまくいくのですが連打したときにうまく凹んでくれないことがあったり、凹んだままになってしまったりで、困っていました。
速いクリックにも対応する独自ボタンを作るにはどうすればいいでしょうか?
サブクラス化してMouseDownイベント(WM_LBUTTONDOWNメッセージ)をフックしてみたのですがそれでも結果は同じでした。
よろしくお願い致します。
実際のプログラムを簡略化したものです。
Private Declare Function DrawEdge Lib "user32" (ByVal hDC As Long, qrc As RECT, ByVal edge As Long, ByVal grfFlags As Long) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Dim R As RECT
Private Sub Form_Load()
Form1.AutoRedraw = True
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
R.Left = 50
R.Top = 50
R.Right = 100
R.Bottom = 80
DrawEdge hDC, R, 10, 15
Form1.Refresh
End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
R.Left = 50
R.Top = 50
R.Right = 100
R.Bottom = 80
DrawEdge hDC, R, 5, 15
Form1.Refresh
End Sub
>サブクラス化してMouseDownイベント(WM_LBUTTONDOWNメッセージ)をフックしてみた
おつかれさま・・・
それよか、もっと基本に立ち返って
FormをClickした時、DoubleClickした時に、
何のイベントが、どゆ順番で発生するかを
確認することをオススメします・・・。
そこを理解しないと解決しないのではないでしょうか?
魔界の仮面弁士さまもそれを言いたいのだと思いますが・・・。
解決法をご存知なのですか?
是非教えてください!!
> それよか、もっと基本に立ち返って
> FormをClickした時、DoubleClickした時に、
> 何のイベントが、どゆ順番で発生するかを
> 確認することをオススメします・・・。
MouseDown > MouseUp > Click > DblClick
の順番で発生することがわかりましたが、それが何か意味があるのでしょうか?
えぇと、イベントの順番がどうこうという話ではなく、
「ダブルクリック イベントを認識するウィンドウだから問題がある」ので、
「ダブルクリックを認識しないウィンドウなら良いのかな」と
漠然と思っただけで……私自身は回答を持っているわけではないです。(汗
これが VB.NET なら、
MyBase.SetStyle(ControlStyles.StandardDoubleClick, False)
だけで解決できそうなのですが、VB6 の場合はどうしたものやら。
ダブルクリックイベントを必要としないのであれば
ダブルクリックイベントからクリックイベントを呼び出せは良いのでは?
Private Sub Form_DblClick()
Call Form_Click
Call Form_Click
End Sub
>Private Sub Form_DblClick()
> Call Form_Click
> Call Form_Click
>End Sub
>
はダメですよ。
Clickの後にDblClickが発生しているのでここでクリックの処理を2回分やってしまうと計3回分の処理をしてしまいます。(実質のクリックは2回)
> MouseDown > MouseUp > Click > DblClick
> の順番で発生することがわかりましたが、それが何か意味があるのでしょうか?
>
私の環境(使用環境Win2000SP4,XPSP2)では MouseDown > MouseUp > Click > DblClick > MouseUp となっていました。私はイベント順を見ることにより DblClick のところではMouseDown イベントが発生していないということを認識できたので意味は十分ありましたが。(DblClick でMouseDown と同等のコードを記載することによりそこそこの連打にも対応できているように見えましたよ。)
それとも環境の違いにより、発生するイベントが変わってくるんでしょうかね。
上記のイベント順を見ると最後に必ず MouseUp が来ているので凹みっぱなしになることはないと思うのですが。軽く実験したけどそのような現象は発生しなかったですね。万回とかテストするとイベントが潰れて発生するのかな?
ただ、イベントが潰れて通知されてこないと対処のしようが無いと思うので諦めるしかないかと。
>>Private Sub Form_DblClick()
>> Call Form_Click
>> Call Form_Click
>>End Sub
>>
>はダメですよ。
>Clickの後にDblClickが発生しているのでここでクリックの処理を2回分やってしまうと計3回分の処理をしてしまいます。(実質のクリックは2回)
すみません。
私はイベント順までは見ておらずccdさんの最初の質問にあったコードで
試しただけなのですが改めてコードを動かしてみたら確かに一回余分にaaa
が追加されていました。
私の環境は winXP SP2、VB6です。
ただ、先にクリックイベントが発生するなら、クリックイベントとダブルクリックイベント
双方にコードがあるとダブルクリックイベントだけを実行することが出来ないんですね。
Windows API方面からのアプローチとしては、やりやすいかどうかは
ともかくとして、VB6の場合は、
1,ボタンの元にはCommandButtonを用いる。(OptionBox、CheckBoxでも可)
2,上記のコントロールのStyleプロパティを1(vbButtonGraphical)にしておく。
3,コントロールをサブクラス化してWM_MOUSEHOVERに反応できるようにする。
TrackMouseEventも使うことになります。
4,そのコントロールを貼り付けたForm/PictureBox/Frame/UserControlも
サブクラス化し、WM_DRAWITEMに反応できるようにする。WM_DRAWITEM
を受け取ったら、そのボタンを状況に応じて適切に描画する。
というようになると思います。
Styleプロパティを1(tbrFlat)にしたToolBarコントロールで代用する方が、
楽ではないか、とも思います。
皆様、ありがとうございました。
APIのGetKeyStateでマウスの状態を調べる方法で、なんとか実現できました!! K.J.K.さんのご提示いただいた方法も、スキルがアップしてきたら挑戦したいと思います。途中、不心得な書き込みもありましたが、これで週末はいい花見ができそうです。
どうもありがとうございました。
ツイート | ![]() |