• ベストアンサー

ComboBoxについておしえてください

↓・↑とクリックを区別したいのですがどうすればよいのか 教えてください。 ↑をおすとKeyDownにいきClickにいきます。 ↑をおしたときにClickにいかないようにすることはできませんか? よろしくおねがいします。

質問者が選んだベストアンサー

  • ベストアンサー
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.5

サンプルを作ってみました。 必要なものは フォーム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 -----標準モジュール(ここまで)-----

その他の回答 (5)

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.6

すいません。さっきのエラーです。+書き忘れです。 書き忘れは、コンボボックスのスタイルがドロップダウンリスト限定だと言うことです。ドロップダウンコンボのままでは無意味です。 エラーはカーソルで選んでエンターを押してもクリックイベントが発生しません。。。もうちょっと研究が必要です。。。m(__)m

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.4

>  SendMessage Combo1, CB_SHOWDROPDOWN, 1, 0 の書き方が違います   SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, 1, 0 が正しい書き方です。 でもこのAPI、ドロップダウンリストの表示/非表示の切り替えをするだけで、仕様を満たさないのではないのでしょうか?

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.3

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

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.2

多分VBの標準機能では無理のような気がします。 あるといえば、 1.コンボボックスのプロセスを監視 2.キーダウンイベントにフラグを立てる 3.フラグによりテキストの変更を破棄させる といったような処理ですが、プロセス監視は結構ムズイですよ。 デバッグもしづらいし。。。

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.1

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

chiba-masaru
質問者

補足

やりたいことは、comboBoxでF4をおして内容を画面上に出力して クリックされたときは、Enterと同じように選択さらた内容をとりこみ 次の項目にいきたいのです。 また、↑・↓は青の帯びが上下するだけにしたいのですがどうすればいいですか またComboBoxには名称とコードをもたして ComboBox.Textには名称のみ表示したいのですが なかなかうまくいきません、これも何かいい方法はないのですか? 教えてください。

関連するQ&A