↓・↑とクリックを区別したいのですがどうすればよいのか
教えてください。

↑をおすとKeyDownにいきClickにいきます。

↑をおしたときにClickにいかないようにすることはできませんか?

よろしくおねがいします。

このQ&Aに関連する最新のQ&A

A 回答 (6件)

サンプルを作ってみました。


必要なものは
フォーム1
コンボボックス1
標準モジュール
です。


処理を説明します。
サブクラス化という処理をしています。
VBにはクリックやボタンダウンなどのイベントがありますが、全てWIndowsが送ってくる定数(メッセージ)を読み取り、その値によってイベントの内容が決まります。このプログラムはコンボボックスにくるWINDOWSからのメッセージをcomboProc関数にて監視し(これがサブクラス化)、カーソルのイベントだけコンボボックスのリスト部分が非表示のときには、メッセージをWINDOWSに返さないようにしています。もしリスト部分が表示されていても、WM_COMMANDという決定というメッセージを返さないようにしています。


サブクラス化の最中に強制終了をすると、VBが落ちます。必ず普通にフォームを閉じて終了しましょう。
常にこの関数が動いている状態なので、プログラム作成最終段階での組み込みをお奨めします。それまでは、[サブクラス化の開始][サブクラス化の終了]部分をコメントにしておくだけで、このプログラムは動きませんので安心してください。


-----フォーム1(ここから)-----
Private Sub Form_Load()
  With Me
    'ダミーのデータ
    With .Combo1
      .AddItem 1
      .AddItem 2
      .AddItem 3
      .AddItem 4
    End With
    
    'サブクラス化の開始
    pLngProc = SetWindowLong(.Combo1.hwnd, GWL_WNDPROC, AddressOf comboProc)
  End With
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  With Me
    'サブクラス化の終了
    Call SetWindowLong(.Combo1.hwnd, GWL_WNDPROC, pLngProc)
  End With
End Sub
-----フォーム1(ここまで)-----

-----標準モジュール(ここから)-----
Option Explicit

Public Const GWL_WNDPROC  As Long = (-4)
Private Const WM_COMMAND = &H111 'メニューが選択されたあるいはコントロールにイベントが発生した
Private Const WM_KEYDOWN = &H100 'キーボードのキーが押された
Private Const WM_KEYUP = &H101 'キーが解放された

Private Const CB_GETDROPPEDSTATE = &H157 'コンボボックスでリストボックス部が開いているかどうか調べる
Private Const CB_SHOWDROPDOWN = &H14F 'コンボボックスでドロップダウンリストを表示・非表示

Private Const KEY_UP  As Byte = &H1
Private Const KEY_DOWN As Byte = &H2

Public Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


'プロセス
Public pLngProc   As Long

'カーソル↑←を押されたとき、1バイト目にフラグを立てる
'カーソル↓→を押されたとき、2バイト目にフラグを立てる
Private bytKeyFlg  As Byte


Public Function comboProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  Select Case uMsg
    'キーダウン
    Case WM_KEYDOWN
      'wParamにはキーコードが入る
      Select Case wParam
        'カーソル↑←
        Case vbKeyUp, vbKeyLeft
          '1バイト目にフラグを立てる
          bytKeyFlg = bytKeyFlg Or KEY_UP
        'カーソル↓→
        Case vbKeyDown, vbKeyRight
          '2バイト目にフラグを立てる
          bytKeyFlg = bytKeyFlg Or KEY_DOWN
        'その他のキー
        Case Else
          '通常処理でメッセージを返す
          GoTo PGMEND
      End Select
      
      'コンボボックスのリスト部分が非表示のときは、メッセージを返さない
      If SendMessage(hwnd, CB_GETDROPPEDSTATE, ByVal 0&, ByVal 0&) = 0 Then
        GoTo PGMEXIT
      End If

    'キーアップ
    Case WM_KEYUP
      'wParamにはキーコードが入る
      Select Case wParam
        'カーソル↑←
        Case vbKeyUp, vbKeyLeft
          '1バイト目のフラグをおろす
          bytKeyFlg = bytKeyFlg And (Not KEY_UP)
        'カーソル↓→
        Case vbKeyDown, vbKeyRight
          '2バイト目のフラグをおろす
          bytKeyFlg = bytKeyFlg And (Not KEY_DOWN)
      End Select
    
    'クリックやEnter入力時の処理
    Case WM_COMMAND
      'カーソル↑←やカーソル↓→が移動するたびに、値を設定してしまうのを防ぐ
      If bytKeyFlg > 0 Then
        'カーソルキーのフラグがたっているので、メッセージを返さない
        GoTo PGMEXIT
      End If
      '強制的にDROPDOWNリストを閉じる
      Call SendMessage(hwnd, CB_SHOWDROPDOWN, 0&, ByVal 0&)
  End Select
PGMEND:
  comboProc = CallWindowProc(pLngProc, hwnd, uMsg, wParam, lParam)
PGMEXIT:
End Function
-----標準モジュール(ここまで)-----
    • good
    • 0

すいません。

さっきのエラーです。+書き忘れです。

書き忘れは、コンボボックスのスタイルがドロップダウンリスト限定だと言うことです。ドロップダウンコンボのままでは無意味です。

エラーはカーソルで選んでエンターを押してもクリックイベントが発生しません。。。もうちょっと研究が必要です。。。m(__)m
    • good
    • 0

>  SendMessage Combo1, CB_SHOWDROPDOWN, 1, 0


の書き方が違います
  SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, 1, 0
が正しい書き方です。

でもこのAPI、ドロップダウンリストの表示/非表示の切り替えをするだけで、仕様を満たさないのではないのでしょうか?
    • good
    • 0

Private Sub Combo1_KeyDown(KeyCode As Integer, Shift As Integer)



If (KeyCode = vbKeyDown Or KeyCode = vbKeyUp) Then
SendMessage Combo1, CB_SHOWDROPDOWN, 1, 0
End If
End Sub
    • good
    • 0

多分VBの標準機能では無理のような気がします。


あるといえば、
1.コンボボックスのプロセスを監視
2.キーダウンイベントにフラグを立てる
3.フラグによりテキストの変更を破棄させる

といったような処理ですが、プロセス監視は結構ムズイですよ。
デバッグもしづらいし。。。
    • good
    • 0

オブジェクトは何ですか?コマンドボタンですか?


↓・↑はカーソルキーですか?

何らかのオブジェクトの上でカーソルキーを押したら、クリックイベントが発生するのを回避したいという捕らえ方でよろしいですか?

この回答への補足

やりたいことは、comboBoxでF4をおして内容を画面上に出力して
クリックされたときは、Enterと同じように選択さらた内容をとりこみ
次の項目にいきたいのです。
また、↑・↓は青の帯びが上下するだけにしたいのですがどうすればいいですか

またComboBoxには名称とコードをもたして
ComboBox.Textには名称のみ表示したいのですが
なかなかうまくいきません、これも何かいい方法はないのですか?
教えてください。

補足日時:2001/11/02 16:36
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QMSFlexGridで↑や↓押下時の処理

現在VBの勉強をしております(WindowsXp、VB6.0)

MSFlexGridの行を選択すると、行のデータをテキストボックスへ表示する、といった処理を実装したんですが、キーボードの「↑」や「↓」押下時に、選択行は変わるんですが、クリックイベントでもフォーカスイベントでも処理を拾えません・・・。

まだ試してはいないんですが、keyDownイベントで、「↑」「↓」を判断し、更にグリッドにフォーカスが存在する場合に、1行上(または下)のデータをテキストボックスに表示する。
という処理をしないと不可能でしょうか?

どう考えても上記の方法はスマートでは無いなぁと思い、何か良い方法があれば教えていただきたく質問させていただきました。

よろしくお願いいたしますm(__)m

Aベストアンサー

Private Sub MSFlexGrid1_SelChange()
  Static intNowRow As Integer <----- 静的変数として現行行を記憶する変数を宣言
  Dim intNewRow As Integer  <----- カーソル移動後の行を格納する変数を宣言
  
  intNewRow = MSFlexGrid1.Row  <----- カーソル移動後の行を intNewRow に代入
  If intNewRow <> intNowRow Then <----- 記憶している現行行と新しい行の行番号を比較
    intNowRow = intNewRow <----- 新しい行の値をを現行行を記憶する intNowRow に代入
    MsgBox intNowRow <--------- MsgBox 関数で  intNowRow を表示。
  End If <----------------------- End If
End Sub

カーソル移動は上下だけでなく左右もあります。
そのために、カーソルが移動したからと言って新しい行へ移動したかどうかは不明です。
で、上下移動したかどうかを知るには新しい行番号と現行の行番号との比較が必要です。
新しい行番号と現行の行番号ろが異なる限りで<行のデータをテキストボックスへ表示する>を。
そこが MsgBox関数の位置に書くべきコードです。

Private Sub MSFlexGrid1_SelChange()
  Static intNowRow As Integer <----- 静的変数として現行行を記憶する変数を宣言
  Dim intNewRow As Integer  <----- カーソル移動後の行を格納する変数を宣言
  
  intNewRow = MSFlexGrid1.Row  <----- カーソル移動後の行を intNewRow に代入
  If intNewRow <> intNowRow Then <----- 記憶している現行行と新しい行の行番号を比較
    intNowRow = intNewRow <----- 新しい行の値をを現行行を記憶する intNowRow に代入
    MsgBox in...続きを読む

QKeydownイベントについて

VB6.0について質問です。
FormでKeydownイベントが動きません。
どのような原因が考えられますか?
コードは以下のように記述しています。

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case vbKeyF8
cmd_F8.Value = True
Case vbKeyF9
cmd_close.Value = True
End Select
End Sub

Aベストアンサー

formのkeyPreviewがfalseになっていませんか?

Qkeydown イベントについて

VB6なのですが、あるオブジェクトにフォーカスがある時には
キーダウンが出来るのですが、どこにもフォーカスがないときには、、
(強いて言うならフォームにフォーカス?)キーダウンイベントは
発生しないのでしょうか?
要は、カーソル、フォーカス、の位置に関係なく、「F1」を押したときに
ある動作をさせたいのです。
よろしくお願いします

Aベストアンサー

FormのKeyPreviewプロパティ=Trueにして
Form_Keydown イベントに記述しましょう。

if KeyCode = vbKeyF1 Then
  MsgBox "(゜ .゜)ノ"
End If

Q継承したFormでKeyDownイベントを一括処理するには?

VB 2005を使用しています
System.Windows.Forms.Formを継承したFormを使って
画面を作っています。

各画面のKeyDownイベントに同じ処理をいれたいのですが、
個々の画面に実装すると変更が発生した場合、
各画面ごとに修正するという事態を回避したいと思います。

そこで継承したForm内でKeyDownイベントを管理したいのですが
その様な方法はあるのでしょうか?
ある場合、どういったキーワードがあるのでしょうか

Aベストアンサー

お世話になります。

> 個々の画面に実装すると変更が発生した場合、
> 各画面ごとに修正するという事態を回避したいと思います。
ここだけ見ると、ひとつ親クラスを作ってやって
そこから各画面に対する派生クラスを作ってやれば良さそうな感じがします。

System.Windows.Forms.Form
 |_
   Base Form(ここで KeyDown の実装)
   |_ 各画面1
   |_ 各画面2
   |_ ...

QKeyDownイベントで数字以外は発生しません。なぜでしょうか。

KeyDownイベントで数字以外は発生しません。なぜでしょうか。
電卓を作っているのですが、キーボードからの対応をしているさなか大きな壁に当たりました。
フォームのKeyDownイベントでキーボードからの入力をキャッチする。
数字や演算、エンターキー。
フォームには、電卓を作るのに必要なボタンなどの配置はしてあります。
数字を表示する部分はLabel1にしています。
試験的に下記のソースで実験したところ、テンキーの数字以外、例えば演算キーをキーボードから入力すると、下記のソース通りならば、○算と表示されるはずです。しかし、なぜか数字と表示されます。
つまり、演算キーを押したにも関わらず、数字が入力されたとして処理されたということです。
なぜでしょうか。
そして、試験的にそれぞれが入力成功した時はLabelに表示されるようにしました。


Private Sub Form6_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
//↓エンターキーが押されたとき

If e.KeyCode = Keys.Enter Then
Label1.Text = "Enter"

//↓演算キー及び点が入力されたとき

ElseIf &H6A <= e.KeyCode <= &H6F Then
Select Case e.KeyCode
Case &H6A
Label1.Text = "乗算"
Case &H6B
Label1.Text = "加算"
Case &H6D
Label1.Text = "減算"
Case &H6E
Label1.Text = "小数点"
Case &H6F
Label1.Text = "除算"
End Select
End If

//↓delキーが押されたときの場合

If e.KeyCode = Keys.Delete Then
Label1.Text = "Del"
End If

// ↓は数字1から9までが対象に入ります。

If &H60 <= e.KeyCode <= &H69 Then
  Label1.Text = "数字"
End If
End Sub

keycode表はマイクロソフトのキーコード定数を見て作りました。
僕がお伺いしたいのは、これらすべてを正常に対応させたいわけです。
数字、演算キー、その他のキーボード入力が正常にできるようにしたいのですが、どうもうまくできません。
なせかずべて数字ほうに行ってしまいます。これでは話にならないので、対処法はありませんか?
環境は
Win7 Ultimate 64bit
Visual Studio 2010 (VB)
です。

何卒、よろしくお願い申し上げます。

KeyDownイベントで数字以外は発生しません。なぜでしょうか。
電卓を作っているのですが、キーボードからの対応をしているさなか大きな壁に当たりました。
フォームのKeyDownイベントでキーボードからの入力をキャッチする。
数字や演算、エンターキー。
フォームには、電卓を作るのに必要なボタンなどの配置はしてあります。
数字を表示する部分はLabel1にしています。
試験的に下記のソースで実験したところ、テンキーの数字以外、例えば演算キーをキーボードから入力すると、下記のソース通りならば、○算と表示...続きを読む

Aベストアンサー

IF 文を通過するかどうかの前に、受け取ったキーコードの値を確認しましょう。


このカテゴリの人気Q&Aランキング

おすすめ情報