テキストボックスのポップアップメニューを表示しないようにするには?

解決


あおいぬ  2002-09-13 21:26:04  No: 104958  IP: [192.*.*.*]

どうも一般的に言われている、MouseDownイベントに

If Button = vbRightButton Then
    Text1.Enabled = False
    Text1.Enabled = True
    Text1.SetFocus
End if

を書き込んでデフォルトのポップアップメニューを表示しない
やり方がうまくいかないんですが、何故でしょう?
色々調べてこの方法が一番簡単にできそうなのですが、
普通にポップアップメニューがでてきてしまいます。
何故だめなのか、教えていただけないでしょうか。

編集 削除
Say  2002-09-13 23:16:43  No: 104959  IP: [192.*.*.*]

システムは右ボタンの押下を検出すると
ターゲットWindowに対しWM_RBUTTONDOWNメッセージを発行します。

WM_RBUTTONDOWNメッセージを受けとったWindowは
ポップアップメニュー表示処理をしたあとで
MouseDownプロシージャを実行します。

つまり、MouseDownプロシージャでは遅すぎるわけです。
メッセージがWindowにわたされる前に
サブクラス化、またはメッセージフックで
つかまえて処理する必要があります。

編集 削除
たかみちえ  URL  2002-09-13 23:52:14  No: 104960  IP: [192.*.*.*]

> メッセージがWindowにわたされる前に
> サブクラス化、またはメッセージフックで
> つかまえて処理する必要があります。
  ・・・そんなに、面倒なことをしないといけなかったんでしたっけ…?

  たしかOCXのリッチテキストボックスなら、ポップアップ抑止しやすかったような…?

編集 削除
t@Ki  2002-09-14 04:22:09  No: 104961  IP: [192.*.*.*]

細かくデバックした結果、デフォルトのポップアップメニューは
MouseDownイベントの後に発生しています。
以前マイクロソフトの技術情報でEnabledをFalseにするとWindowに
対するWM_RBUTTONDOWNメッセージが処理されない、と書いてあったのですが
確かにFalseにするとMouseDownイベントの後にポップアップメニューの
表示処理までいきません。しかし、直後にTrueにするときちんと処理されて
しまいます。
いろいろページでも紹介されているこのやり方が何故できないのか
不可解で仕方がありません。
サブクラス化して途中でメッセージをフックしてこちらで用意した処理に
すり替える方法で確実にできると思うのですが、サブクラス化の設定、解除
のことをいろいろ考えると、アプリケーションを強制終了させたときなど
危険すぎると思うのですが、どうでしょうか。
この方法しかできないのでしょうか?
私の勉強不足でしたら申し訳ありません。

編集 削除
あおいぬ  2002-09-14 05:12:12  No: 104962  IP: [192.*.*.*]

Sayさん、たかみちえさん、t@Kiさんご回答有り難う御座います。
やはり、この方法ではできないということですか?
Sayさんとt@Kiさんのおっしゃっているやり方はAPIを使うということ
でしょうか?
なるべくAPI以外を避けたいのですが、もしこの方法しかないのでしたら
詳しくやり方を教えて頂けないでしょうか。
たかみちえさんのおっしゃっているリッチテキストボックスでの方法も
詳しく知りたいです。

編集 削除
Say  2002-09-14 16:13:50  No: 104963  IP: [192.*.*.*]

正確には、WM_RBUTTONUPメッセージを受け取った後
ポップアップメニュー表示しているようですね。

ということは、MouseDownイベントが発生してから、
右ボタンをUPするまでの間、EnabledをFalseにしておけば、
WM_RBUTTONUPを拾えなくなるので
ポップアップメニュー表示を抑止できます。

たとえばこんな感じ。

Private Sub Text1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbRightButton Then
    Text1.Enabled = False
    Timer1.Interval = 500
    Timer1.Enabled = True
End If
End Sub

Private Sub Timer1_Timer()
    Text1.Enabled = True
    Text1.SetFocus
    Timer1.Enabled = False
End Sub

ただし、この例だと0.5秒以上押して離されたら効果ありません。

編集 削除
たかみちえ  URL  2002-09-14 21:15:12  No: 104964  IP: [192.*.*.*]

Sayさんの言う方法なら、
MouseDownでEnabledをFalseにして、
MouseUpでTrueにすればどうでしょう?
マウスボタンを押しながらキーボードボタンを押す(押しても意味無いですけど)や、
ホイールマウスの真ん中ボタンを押すなど(どこでもホイールなどのソフトがあれば、非対応ソフトでもホイールが使えるし)のとき、
動かないかもしれませんけど。


> たかみちえさんのおっしゃっているリッチテキストボックスでの方法も
  うろ覚え(そればっか、MSDNでちゃんと確認なさい^^;)ですけど、
確かリッチエディットって、何もしないとポップアップメニューがそもそも出ないんじゃないでしたっけ…?

編集 削除
たかみちえ  URL  2002-09-14 21:16:13  No: 104965  IP: [192.*.*.*]

> リッチエディット
  リッチテキストと同義です。

編集 削除
Say  2002-09-14 22:52:37  No: 104966  IP: [192.*.*.*]

>MouseDownでEnabledをFalseにして、
>MouseUpでTrueにすればどうでしょう?

Timer使ってるのは
EnabledをFalseにすると
WM_RBUTTONUPを拾えなくなるので
MouseUpイベントもおきないからです。

ちなみに、API使って

If Button = vbRightButton Then
    Text2.Enabled = False
    Call Sleep(500)
    Text2.Enabled = True
End If

とやるのもうまくいきません。

ループで待つのはうまくいきますが、
単純にカウンタでループすると
マシンスピードの影響をうけますので、
ループ内でtimeGetTimeなどで経過時間を計算して
抜ける工夫が必要になります。

>確かリッチエディットって、何もしないとポップアップメニューがそもそも出ないんじゃないでしたっけ…?
RichTextBox コントロールなら、なにもせずそのまま使えばOKです。

編集 削除
あおいぬ  2002-09-17 11:37:03  No: 104967  IP: [192.*.*.*]

みなさん丁寧なご回答有り難うございました。
Timerをつかって実現することに成功しました。
こんどリッチテキストボックスも使ってみようと思います。
大変助かりました。有り難うございます。

編集 削除