ユーザーの利便性を高めるために、インターフェースには様々な便利な機能を組み込む必要がありますが、機能の中には非常に複雑なものもあります。しかし、小さな改良でも効率性と使いやすさの面で大きな効果を発揮することがあります。良い例がコンボボックスコントロールです。項目を選択するために、ユーザーに単語全体を入力させたり、長い項目リストをスクロールさせたりする必要はありません。ちょっとした工夫で、コンボボックスにリストされている単語を入力し始めるとすぐに項目が表示されるようにすることができます。
この記事では、 SendMessage API関数を使用してコンボボックスコントロールにこの機能を追加する方法を説明します。さらに、表示する項目に合わせてコントロールの幅が調整されるように設定します。
APIの概要
SendMessage関数は、ウィンドウ(コントロール)のWindows関数を直接呼び出すことで、そのウィンドウにメッセージを送信するために使用されます。ウィンドウの関数は実行が完了するまで制御を返さず、呼び出し元のルーチンに値を渡すことができます。この値の意味はメッセージによって異なります。SendMessage関数は、値を返すメッセージを送信する必要がある場合にのみ使用してください。
SendMessage関数は、ウィンドウハンドル、メッセージ番号、wParam、lParamの4つのパラメータを受け取り、long値を返します。SendMessageはウィンドウ関数を直接呼び出すため、ウィンドウ関数はSendMessage関数の結果として表示される値を返すことができます。
表Aはパラメータの詳細を示しています。
表A
パラメータ | タイプ | 説明 |
ハンド | 長さ | メッセージを受信するウィンドウのハンドル |
wメッセージ | 長さ | 送信するメッセージ |
wParam | 長さ | 追加情報を指定します。メッセージによって異なります。 |
lParam | 長さ | 追加情報を指定します。メッセージによって異なります。 |
SendMessageパラメータ
SendMessage API VB 宣言は次のようになります: 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
この機能は、Windows NT/2000/XP(Windows NT 3.1以降)、Windows 95/98/Me(Windows 95以降)で使用できます。
SendMessage を活用するSendMessage API を使用してコンボ ボックス コントロールにスマート検索を実装する
方法を示す簡単な VB プロジェクトを作成しましょう。
まず、VB を起動し、新しいプロジェクトを開始して、フォームの ScaleMode プロパティを 4 – 文字に設定します。
次に、フォームに2つのラベルを追加し、それぞれのCaptionプロパティを「Select Profession」と「Select City」に設定します。フォームに2つのコンボボックスを追加し、それぞれ「cboProfession」と「cboCity」と名付けます。それぞれのStyleプロパティを「Dropdown Combo」に設定し、両方のコンボボックスの幅を狭くします。この時点で、画面は図Aのようになるはずです。
図A |
![]() |
サンプルコンボボックス |
次に、フォームの宣言セクションに次のコードを追加します。Option
Explicit
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 Const CB_ERR = (-1)
Private Const CB_FINDSTRING = &H14C
Form_Load()イベントに次のコードを追加します:
Private Sub Form_Load()
Call FillCities 'fill combo box cboCity
Call FillProfessions 'fill combo box cboProfession
End Sub
cboCity_KeyPress()イベントに次のコードを追加します:
Private Sub cboCity_KeyPress(KeyAscii As Integer)
Call SelectItem(cboCity, KeyAscii)
End Sub
cboProfession_KeyPress()イベントに次のコードを追加します:
Private Sub cboProfession_KeyPress(KeyAscii As Integer)
Call SelectItem(cboProfession, KeyAscii)
End Sub
コードに次の 3 つの手順を追加します:
Private Sub SelectItem(cbo As ComboBox, KeyAscii As Integer)
Private Sub FillProfessions()
Private Sub FillCities()
リスト Aに示すコードをSelectItemに追加し、リスト Bに示すコードをFillProfessionsに追加し、リスト Cに示すコードをFillCitiesに追加します。
[Ctrl][F5] キーを押してプロジェクトを実行すると、画面は図 Bのようになります。
図B |
![]() |
出力例 |
SendMessage の動作
確認 機能をテストするには、一番上のコンボボックスをクリックし、bと入力します。コンボボックスに Banker というエントリが表示されます。行の先頭に戻り、cと入力します。CEO というエントリが表示されます。同じ手順で2番目のコンボボックスも実行できます。nと入力すると New Orleans というエントリが表示されますが、続けてNew yと入力すると、コンボボックスに New York が表示されます。
このサンプルでは、SendMessage API を使用して、ユーザーがコンボ ボックスから項目を選択できるようにし、項目が切り取られないように動的な幅調整を行いました。
この機能を実現するために、 KeyPressイベントを使用してスマート検索機能を実装し、入力された文字の ASCII 値が英数字であるかどうかを確認し、ユーザーがドル記号、プラス記号、マイナス記号、パーセント記号などの他の文字を入力できないようにしました。
ユーザーが入力した文字をsFindStringに保存し、 SendMessage API関数を呼び出してコンボボックスコントロール内でユーザーが入力した文字に一致する項目を検索します。項目が見つかった場合、CB_FINDSTRINGは一致する項目の番号を返し、コンボボックスコントロールにその項目を表示するように設定します。
また、フォームのScaleModeプロパティ(オブジェクトの測定単位を示す値を設定できるプロパティ)をCharacterに設定し、フォーム上のコンボボックスの幅がtwipではなく文字数で測定されるようにしました。次に、各コンボボックスで最も長い項目の文字数を計算し、その値を使用してコントロールのWidthプロパティを指定します。