レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API リスト ボックスの概要

Microsoft(R) Win32(R) アプリケーション プログラミング インターフェイス (API) では、 アプリケーションとユーザーの対話をサポートするためのダイアログ ボックスとコントロールを用意しています。「リスト ボックス」とは、 ユーザーが選択可能な項目のリストを示すコントロール ウィンドウです。リスト ボックスの項目には、 テキスト文字列やビットマップを使うことができます。リスト ボックスが小さすぎて項目を一度に表示しきれないときは、 リスト ボックスにスクロール バーを付加することもできます。

ユーザーは、 マウスかキーボードを使って、 リスト ボックス項目を選択、 取消できます。リスト ボックス項目を選択すると、 リスト ボックスの外観が変化します (通常は、 選択項目のオペレーティング システム メトリックスが示す色にテキストと背景の色が変更されます)。ユーザーが項目を選択したり取り消すと、 Windowsは、 リスト ボックスの親ウィンドウに通知メッセージを送ります。

リスト ボックスはオーバーラップ ウィンドウや子ウィンドウ、 ポップアップ ウィンドウでも使えますが、 リスト ボックスは主にダイアログ ボックスで使うことを目的として設計されています。ダイアログ ボックスの機能のほとんどは、 Windowsで定義済みです。ダイアログ ボックス以外のウィンドウでリスト ボックスを使うと、 一貫したユーザー インターフェイスを保つのが難しくなります。このため、 ダイアログ ボックス以外でリスト ボックスを実現するには、 ウィンドウのサブクラス化を使ってください。このトピックでは、 主にダイアログ ボックス内でのリスト ボックスの使用について説明しますが、 説明はそれ以外の親ウィンドウでのリスト ボックスの使用についてもあてはまります。ウィンドウのサブクラス化について、 詳しくはウィンドウ プロシージャの概要を参照してください。

ダイアログ ボックス プロシージャは、 リスト ボックスなどの子ウィンドウを初期化して監視しなければなりません。ダイアログ ボックス プロシージャは、 リスト ボックスにメッセージを送り、 リスト ボックスが送った通知メッセージを処理することによって、 リスト ボックスと通信します。ダイアログ ボックスについて詳しくは、 ダイアログ ボックスの概要を参照してください。

コントロールについての一般的な情報は、 コントロールの概要を参照してください。

次に示すトピックでは、 リスト ボックスについて説明しています。

リスト ボックスのスタイル

リスト ボックス関数

リスト ボックスからの通知メッセージ

リスト ボックスへのメッセージ

デフォルトのウィンドウ メッセージ処理

簡単なリスト ボックスの作成

単一選択リスト ボックスによるディレクトリ一覧の作成

複数選択リスト ボックスの作成

オーナー描画リスト ボックスの作成

リスト ボックス関数とメッセージ

 

 

リスト ボックスのスタイル

Win32 APIは、 単一選択 (デフォルトのスタイル) と複数選択の2つのスタイルのリスト ボックスを用意しています。「単一選択リスト ボックス」では、 ユーザーは一度に1つの項目しか選択できません。「複数選択リスト ボックス」では、 ユーザーは一度に複数の項目を選択できます。複数選択リスト ボックスには、 LBS_MULTIPLESELスタイルかLBS_EXTENDEDSELスタイルを指定します。

これ以外にも、 Win32 APIは、 リスト ボックスの外観や動作を制御するリスト ボックス スタイルやウィンドウ スタイルを多数用意しています。スタイルには、 リスト ボックス項目のソート方法、 複数列での配置、 アプリケーションによる描画などを指定するものがあります。通常、 リスト ボックスの寸法やスタイルは、 アプリケーションのリソースに追加するダイアログ ボックス テンプレートで定義します。ダイアログ ボックス テンプレートを作成してアプリケーションに追加する方法については、 アプリケーション開発ツールのマニュアルを参照してください。

リスト ボックスを作成するには、 LISTBOXクラスを指定してCreateWindow関数とCreateWindowEx関数を呼び出します。このとき、 適切なウィンドウ スタイル定数と次に示すリスト ボックス スタイル定数を指定します。

 

リスト ボックスのスタイル 説明

LBS_DISABLENOSCROLL スクロールが必要な程の項目がリスト ボックスにないときは、 垂直スクロール バーを使用不能にします。アプリケーションがこのスタイルを指定しなければ、 リスト ボックスの項目が少ないときはスクロール バーは表示されません。

LBS_EXTENDEDSEL Shiftキーとマウスや特別なキー操作を使って複数の項目を選択できるようにします。

LBS_HASSTRINGS 文字列で構成された項目がリスト ボックスに含まれていることを示します。文字列のメモリとアドレスはリスト ボックスが管理し、 アプリケーションはLB_GETTEXTメッセージを使って特定の項目のテキストを取得できます。デフォルトでは、 オーナー描画リスト ボックス以外のすべてのリスト ボックスにこのスタイルが設定されます。オーナー描画リスト ボックスは、 このスタイルを指定せずに作成することもできます。

LBS_MULTICOLUMN 水平スクロールする複数列リスト ボックスを示します。LB_SETCOLUMNWIDTHメッセージは、 列の幅を設定します。

LBS_MULTIPLESEL ユーザーが文字列をクリックまたはダブルクリックすると、 文字列の選択をオン、 オフします。ユーザーは、 文字列を好きなだけ選択できます。

LBS_NODATA すべてのデータはアプリケーションで割り当てる必要があることを示します。オーナー描画リスト ボックスには、 このスタイルを使わなければなりません。

LBS_NOINTEGRALHEIGHT リスト ボックスのサイズを、 アプリケーションがリスト ボックスを作成するときに指定したサイズにします。項目が部分的に表示されないように、 通常は、 Windowsがリスト ボックスのサイズを調整します。

LBS_NOITEMDATA 削除されました。

LBS_NOREDRAW リスト ボックスの内容を変更したときにリスト ボックスを更新しないことを指定します。このスタイルは、 WM_SETREDRAWメッセージを指定することによっていつでも変更できます。

LBS_NOTIFY ユーザーが文字列をクリックまたはダブルクリックしたときに、 親ウィンドウに入力メッセージを送ります。

LBS_OWNERDRAWFIXED リスト ボックスの内容をリスト ボックスのオーナーが描画し、 リスト ボックス内の項目がすべて同じ高さであることを示します。オーナー ウィンドウは、 リスト ボックスが作成されるとWM_MEASUREITEMメッセージを受け取り、 リスト ボックスの表示が変更されるときにはWM_DRAWITEMメッセージを受け取ります。

LBS_OWNERDRAWVARIABLE リスト ボックスの内容をリスト ボックスのオーナーが描画し、 リスト ボックス内の各項目の高さがそれぞれ異なることを示します。オーナー ウィンドウは、 コンボ ボックスが作成されるときにコンボ ボックスの各項目についてWM_MEASUREITEMメッセージを受け取り、 コンボ ボックスの表示が変更されたときはWM_DRAWITEMメッセージを受け取ります。

LBS_SORT リスト ボックス内の項目をアルファベット順にソートします。

LBS_STANDARD リスト ボックス内の文字列をアルファベット順に並べ替えます。ユーザーが文字列をクリック、 またはダブルクリックすると、 親ウィンドウが入力メッセージを受け取ります。このリスト ボックスの周囲には境界線があります。

LBS_USETABSTOPS 文字列を表示するときに、 タブ文字を認識して展開します。デフォルトのタブ位置は、 32ダイアログ ボックス単位です。ダイアログ ボックス単位は、 水平または垂直方向の距離です。1水平ダイアログ ボックス単位は、 現在のダイアログ ボックスのベース幅単位の1/4です。Windowsは、 現在のシステム フォントの高さと幅に基づいて、 これらの単位を計算します。GetDialogBaseUnits関数は、 現在のダイアログ ボックス ベース単位をピクセル数で表した値を返します。

 

LBS_WANTKEYBOARDINPUT 入力フォーカスを持つリスト ボックスでユーザーがキーを押したときに、 リスト ボックスのオーナーがWM_VKEYTOITEMメッセージを受け取ることを示します。これによって、 アプリケーションは、 キーボード入力に関する特別な処理を実行できます。

 

 

 

 

リスト ボックス関数

Win32 API、 リスト ボックス専用の2つの関数をサポートしています。DlgDirList関数は、 指定されたパスのファイルとディレクトリをリスト ボックスに設定します。DlgDirSelectEx関数は、 DlgDirListで初期化したリスト ボックスの現在の選択を取得します。これらの関数を利用することによって、 ユーザーは、 ファイルの名前や位置を入力せずにファイルをリスト ボックスから選択できます。

 

 

リスト ボックスからの通知メッセージ

リスト ボックスでイベントが発生すると、 リスト ボックスは、 オーナー ウィンドウのダイアログ ボックス プロシージャに通知メッセージを送ります。リスト ボックスが通知メッセージを送るのは、 ユーザーがリスト ボックス項目を選択、 ダブルクリック、 取消したときや、 リスト ボックスがキーボード フォーカスを取得したり失ったとき、 リスト ボックスに必要なメモリをオペレーティング システムが割り当てられなかったときです。通知メッセージはWM_COMMANDメッセージとして送られます。このメッセージのwParamパラメータの下位ワードはリスト ボックスの識別子、 wParamの上位ワードは通知コード、 lParamパラメータはコントロール ウィンドウのハンドルを示します。

移植上の問題: Microsoft(R) Windows NT(TM) では、 通知コードはlParamパラメータではなくwParamパラメータに設定されます。Windows 3.xアプリケーションをWin32ベースのアプリケーションに移植するときは、 通知メッセージを処理するコードを修正してください。

通知メッセージを処理するためのダイアログ ボックス プロシージャは不要です。デフォルトのウィンドウ プロシージャが通知メッセージを処理します。

アプリケーションは、 次に示すリスト ボックス通知メッセージを監視して処理してください。

 

通知コード 意味

LBN_DBLCLK ユーザーがリスト ボックスの項目をダブルクリックしました。

LBN_ERRSPACE リスト ボックスが要求を満足するためのメモリを割り当てることができません。

LBN_KILLFOCUS リスト ボックスがキーボード フォーカスを失いました。

LBN_SELCANCEL ユーザーがリスト ボックスの項目の選択を取り消しました。

LBN_SELCHANGE リスト ボックスの選択が変化しようとしています。

LBN_SETFOCUS リスト ボックスがキーボード フォーカスを取得しました。

 

 

 

 

リスト ボックスへのメッセージ

ダイアログ ボックス プロシージャは、 リスト ボックスにメッセージを送って、 リスト ボックス項目を追加、 削除、 問い合わせ、 変更できます。たとえば、 ダイアログ ボックス プロシージャは、 リスト ボックスにLB_ADDSTRINGメッセージを送って項目を追加し、 LB_GETSELメッセージを送って、 選択されている項目を調べることができます。このほかにも、 リスト ボックスのサイズや外観、 動作に関する情報を設定、 取得するメッセージがあります。たとえば、 LB_SETHORIZONTALEXTENTメッセージは、 リスト ボックスのスクロール可能幅を設定します。ダイアログ ボックス プロシージャは、 SendMessage関数かSendDlgItemMessage関数を使って、 リスト ボックスにメッセージを送ります。

通常、 リスト ボックス項目は、 リスト ボックス内での項目の位置を示すインデックス (整数) で参照されます。リスト ボックスの最初の項目のインデックスは0で、 以下順番に1ずつ増えていきます。

次の表は、 定義済みリスト ボックス プロシージャのリスト ボックス メッセージに対する動作を示しています。

 

メッセージ 応答

LB_ADDFILE DlgDirList関数で設定したディレクトリ リスト ボックスにファイルを挿入し、 挿入した項目のリスト ボックス インデックスを取得します。

LB_ADDSTRING リスト ボックスに文字列を追加し、 その項目のインデックスを返します。

LB_DELETESTRING リスト ボックスから文字列を削除し、 リスト中に残っている文字列の個数を返します。

LB_DIR ファイル名のリストをリスト ボックスに追加し、 最後に追加したファイル名のインデックスを返します。

LB_FINDSTRING リスト ボックス内で指定されたプリフィックスに最初に一致する文字列のインデックスを返します。

LB_FINDSTRINGEXACT 指定された文字列に一致する文字列のインデックスを返します。

LB_GETANCHORINDEX マウスで最後に選択された項目のインデックスを返します。

LB_GETCARETINDEX フォーカス長方形を持つ項目のインデックスを返します。

LB_GETCOUNT リスト ボックスの項目数を返します。

LB_GETCURSEL 単一選択リスト ボックスで現在選択されている項目のインデックスを返します。

LB_GETHORIZONTALEXTENT リスト ボックスのスクロール可能幅をピクセル単位で返します。

LB_GETITEMDATA 指定された項目に関連付けられている32ビット値を返します。

LB_GETITEMHEIGHT リスト ボックスの項目の高さをピクセル単位で返します。

LB_GETITEMRECT 指定されたリスト ボックス項目のクライアント座標を返します。

LB_GETLOCALE リスト ボックスのロケールを取得します。上位ワードが国別コードを示し、 下位ワードが言語識別子を示します。

LB_GETSEL リスト ボックス項目の選択状態を返します。

LB_GETSELCOUNT 複数選択リスト ボックスで選択されている項目の個数を返します。

LB_GETSELITEMS 複数選択リスト ボックスで選択されている項目のインデックスをすべて含む配列を作成し、 選択されている項目の総数を返します。

LB_GETTEXT 指定された項目に関連付けられている文字列とその文字列の長さを返します。

LB_GETTEXTLEN 指定された項目に関連付けられている文字列の長さを文字単位で返します。

LB_GETTOPINDEX リスト ボックスで最初に表示されている項目のインデックスを返します。

LB_INSERTSTRING リスト ボックスの特定のインデックスに文字列を挿入します。

LB_RESETCONTENT リスト ボックスから項目をすべて削除します。

LB_SELECTSTRING 指定されたプリフィックスに最初に一致する文字列を選択します。

LB_SELITEMRANGE リスト ボックスの指定された範囲の項目を選択します。

LB_SELITEMRANGEEX 指定された範囲の最初の項目のインデックスが範囲の最後の項目のインデックスよりも小さければ、 指定された範囲の項目を選択します。最初の項目のインデックスが最後の項目のインデックスよりも大きければ、 指定された範囲の選択を取り消します。

LB_SETANCHORINDEX マウスで最後に選択した項目を指定した項目に設定します。

LB_SETCARETINDEX 指定されたリスト ボックス項目にフォーカス長方形を設定します。

LB_SETCOLUMNWIDTH リスト ボックスのすべての列の幅をピクセル単位で設定します。

LB_SETCOUNT リスト ボックスの項目数を設定します。

LB_SETCURSEL 指定されたリスト ボックス項目を選択します。

LB_SETHORIZONTALEXTENT リスト ボックスのスクロール可能幅をピクセル単位で設定します。

LB_SETITEMDATA リスト ボックス項目に32ビット値を関連付けます。

LB_SETITEMHEIGHT リスト ボックスの項目の高さをピクセル単位で設定します。

LB_SETLOCALE リスト ボックスのロケールを設定し、 以前のロケール識別子を返します。

LB_SETSEL 複数選択リスト ボックスで項目を選択します。

LB_SETTABSTOPS 指定された配列が示すタブ ストップを設定します。

LB_SETTOPINDEX 指定された項目が表示範囲のいちばん上になるように、 リスト ボックスをスクロールします。

 

 

 

 

 

デフォルトのウィンドウ メッセージ処理

定義済みリスト ボックス ウィンドウ クラスのウィンドウ プロシージャは、 リスト ボックスが処理しないメッセージのデフォルト処理をすべて行います。メッセージに対してリスト ボックス プロシージャがFALSEを返すと、 定義済みウィンドウ プロシージャはメッセージをチェックし、 次の表に示すデフォルト動作を実行します。

 

メッセージ デフォルト動作

WM_CHAR ユーザーが入力した文字で始まる最初の項目に選択を移動します。リスト ボックスがLBS_OWNERDRAWスタイルを持っていれば、 何もしません。

短い間隔で入力された複数の文字はグループとして扱われ、 その文字グループで始まる最初の項目が選択されます。

WM_CREATE 空のリスト ボックスを作成します。

WM_DESTROY リスト ボックスを破棄し、 使われていたリソースをすべて解放します。

WM_DROPFILES ダイアログ ボックス プロシージャか親ウィンドウ プロセスにメッセージを渡します。

WM_ENABLE コントロールが表示されていれば、 長方形を無効にして、 文字列が灰色表示されるようにします。

WM_ERASEBKGND リスト ボックスの背景を消去します。リスト ボックスがLBS_OWNERDRAWスタイルを持っていれば、 背景を消去しません。

WM_GETDLGCODE DLGC_WANTARROWS | DLGC_WANTCHARSを返します。これは、 デフォルト リスト ボックス プロシージャが方向キーやWM_CHARメッセージを処理することを示します。

WM_GETFONT リスト ボックスの現在のフォントのハンドルを返します。

WM_HSCROLL リスト ボックスを水平にスクロールします。

WM_KEYDOWN スクロール用仮想キーを処理します。仮想キーは、 キャレットの移動先の項目のインデックスです。選択を変更しません。

WM_KILLFOCUS キャレットを非表示にして破棄します。リスト ボックスのオーナーにLBN_KILLFOCUSメッセージを送ります。

WM_LBUTTONDBLCLK リスト ボックスのクライアント領域でマウスを追跡します。これによって、 ユーザーがリスト ボックスのクライアント領域の外でマウス ボタンを離したときは、 選択が取り消されます。

WM_LBUTTONDOWN リスト ボックスのクライアント領域でマウスを追跡します。これによって、 ユーザーがリスト ボックスのクライアント領域の外でマウス ボタンを離したときは、 選択が取り消されます。

WM_LBUTTONUP リスト ボックスのクライアント領域でマウスを追跡します。これによって、 ユーザーがリスト ボックスのクライアント領域の外でマウス ボタンを離したときは、 選択が取り消されます。

WM_MOUSEMOVE リスト ボックスのクライアント領域でマウスを追跡します。これによって、 ユーザーがリスト ボックスのクライアント領域の外でマウス ボタンを離したときは、 選択が取り消されます。

WM_PAINT リスト ボックスのデバイス コンテキスト ハンドルを使って、 サブクラス化された描画操作を実行します。

WM_SETFOCUS キャレットを表示して、 リスト ボックスのオーナーにLBN_SETFOCUSメッセージを送ります。

WM_SETFONT リスト ボックスに新しいフォントを設定します。

WM_SETREDRAW wParamの値に応じて、 再描画フラグをセットまたはクリアします。

WM_SIZE リスト ボックスを項目数の整数倍にサイズ変更します。

WM_VSCROLL リスト ボックスを垂直にスクロールします。

 

 

定義済みリスト ボックス プロシージャは、 上記以外のメッセージをDefWindowProc関数に渡してデフォルト処理を行わせます。

 

 

リスト ボックスの使用

次のトピックからは、 以下に挙げたタスクを実行する方法を説明します。

 

簡単なリスト ボックスの作成

単一選択リスト ボックスによるディレクトリ一覧の作成

複数選択リスト ボックスによるディレクトリ一覧の作成

オーナー描画リスト ボックスの作成

 

 

簡単なリスト ボックスの作成

次のコード例は、 簡単なリスト ボックスを作成し、 ソフトボール チームのメンバの名前を設定する方法を示しています。リスト内で名前が選択されると、 そのプレーヤに関する詳細な情報をダイアログ ボックスに表示します。ダイアログ ボックスを次の図に示します。

リスト ボックスは、 LBS_STANDARDスタイル (LBS_SORTLBS_NOTIFYWS_VSCROLLWS_BORDERの組み合わせ) を持っています。このコードは、 WM_INITDIALOGメッセージを処理するときにダイアログ ボックスを初期化します。リスト ボックス内の各名前について、 リスト ボックスにLB_ADDSTRINGメッセージを送ります。また、 LBN_SELCHANGE通知を処理することによって、 選択の変更を追跡します。

 

#define BUFFER MAX_PATH

#define NAMELENGTH 15
#define POSITIONLENGTH 20
#define TEAMSIZE 15

typedef struct {
TCHAR tchName[NAMELENGTH];
TCHAR tchPosition[POSITIONLENGTH];
int nGamesPlayed;
int nInningsPlayed;
double xBattingAverage;
TCHAR tchFoodName[NAMELENGTH];
} Player;

Player Roster[] = {
{"Pete", "shortstop", 26, 90, .608, "Rutabaga"},
{"Suzanna", "catcher", 16, 53, .286, "Toast"},
{"Jack", "pitcher", 27, 110, .542, "Animal Crackers"},
{"Karen", "second base", 26, 140, .238, "Pez"},
{"Dave", "first base", 28, 138, .508, "Suds"},
{"Wendy", "third base", 25, 154, .493, "Ham"},
{"Matt", "shortstop", 24, 112, .579, "Oats"},
{"Jenny", "right field", 22, 101, .509, "Mashed Potatoes"},
{"Seth", "left-center field", 20, 76, .407, "Otter Pop"},
{"Kathie", "left field", 26, 127, .353, "Baba Ganouj"},
{"Colin", "pitcher", 26, 96, .456, "Lefse"},
{"Penny", "right field", 24, 112, .393, "Zotz"},
{"Art", "left-center field", 17, 56, .375, "Cannelloni"},
{"Cindy", "second base", 13, 58, .207, "Tequila"},
{"David", "center field", 18, 101, .612, "Bok Choy"}
};

/*
* FUNCTION: DlgTeamProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: Dialog box for "BFG Softball Statistics"
*/

BOOL APIENTRY DlgTeamProc(
HWND hDlg, /* window handle of dialog box */
UINT message, /* type of message */
UINT wParam, /* message-specific information */
LONG lParam) /* message-specific information */
{

TCHAR tchName[NAMELENGTH];
TCHAR tchBuffer[BUFFER];
int nItem;
int i;


switch (message) {

case WM_INITDIALOG:

/* Initialize the list box (fill it with player names). */

for (i = 0; i < TEAMSIZE; i++) {
SendMessage(GetDlgItem(hDlg, IDL_SOFTBALL),
LB_ADDSTRING, 0, (LPARAM) Roster[i].tchName);
}

SetFocus(GetDlgItem(hDlg, IDL_SOFTBALL));

return FALSE;

case WM_COMMAND:

switch (LOWORD(wParam)) {

case IDL_SOFTBALL:

switch (HIWORD(wParam)) {

case LBN_SELCHANGE:

/* Display the selected player's statistics. */

nItem = SendMessage(GetDlgItem(hDlg, IDL_SOFTBALL),
LB_GETCURSEL, 0, 0);

SendMessage(GetDlgItem(hDlg, IDL_SOFTBALL),
LB_GETTEXT, nItem, (LPARAM) tchName);

for (i = 0; strcmp(tchName, Roster[i].tchName); i++);

SetDlgItemText(hDlg, IDS_POS, Roster[i].tchPosition);
SetDlgItemText(hDlg, IDS_GAME,
_itoa(Roster[i].nGamesPlayed, tchBuffer, 10));
SetDlgItemText(hDlg, IDS_INN,
_itoa(Roster[i].nInningsPlayed, tchBuffer, 10));
SetDlgItemText(hDlg, IDS_BA,
_gcvt(Roster[i].xBattingAverage, 3, tchBuffer));
SetDlgItemText(hDlg, IDS_FOOD,
Roster[i].tchFoodName);

return TRUE;
}
break;

case IDOK:
case IDCANCEL:

/* Destroy the dialog box. */

EndDialog(hDlg, TRUE);
return TRUE;

default:
return FALSE;

}

default:
return FALSE;

}
}

 

 

単一選択リスト ボックスによるディレクトリ一覧の作成

次のコード例は、 現在のディレクトリの内容をリスト ボックスに表示し、 ユーザーがファイルを1つずつ削除できるようにする方法を示しています。

このリスト ボックスでは、 標準リスト ボックス スタイルのほかに、 LBS_MULTICOLUMNスタイルとLBS_HSCROLLスタイルを指定しています。DlgDirList関数を使って、 現在のディレクトリのすべてのファイルの名前をリスト ボックスに設定しています。ユーザーが[Delete]ボタンを選択したら、 DlgDirSelectEx関数を使って、 選択されているファイルの名前を取得します。DeleteFile関数を使ってファイルを削除し、 LB_DELETESTRINGメッセージを送ってディレクトリ リスト ボックスを更新します。

 

#define BUFFER MAX_PATH

/*
* FUNCTION: DlgDelFileProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: "Delete File" dialog box
*/

BOOL APIENTRY DlgDelFileProc(
HWND hDlg, /* window handle of dialog box */
UINT message, /* type of message */
UINT wParam, /* message-specific information */
LONG lParam)
{

DWORD cchCurDir;
LPTSTR lpszCurDir;
LPTSTR lpszFileToDelete;
int nItem;
int nTotal;
TCHAR tchBuffer[BUFFER];
BOOL fResult;

switch (message) {

case WM_INITDIALOG:

/*
* Initialize the list box by filling it with files from
* the current directory.
*/

lpszCurDir = tchBuffer;
GetCurrentDirectory(cchCurDir, lpszCurDir);
DlgDirList(hDlg, lpszCurDir, IDL_FILES, IDS_PATHTOFILL, 0);

SetFocus(GetDlgItem(hDlg, IDL_FILES));

return FALSE;

case WM_COMMAND:

switch (LOWORD(wParam)) {

case IDOK:

/*
* When the user presses the DEL (IDOK) button,
* delete the selected file.
*/

lpszFileToDelete = tchBuffer;

DlgDirSelectEx(hDlg, lpszFileToDelete, MAX_PATH,
IDL_FILES);
fResult = DeleteFile(lpszFileToDelete);
if (!fResult) {
MessageBox(hDlg, "Could not delete file.",
NULL, MB_OK);
} else {

nItem = SendMessage(GetDlgItem(hDlg, IDL_FILES),
LB_GETCURSEL, 0, 0);

nTotal = SendMessage(GetDlgItem(hDlg, IDL_FILES),
LB_DELETESTRING, nItem, 0);

/* Update the list box. */

if (nTotal > nItem) {
SendMessage(GetDlgItem(hDlg, IDL_FILES),
LB_SETCURSEL, nItem, 0);
} else {
SendMessage(GetDlgItem(hDlg, IDL_FILES),
LB_SETCURSEL, nTotal, 0);
}

}
return TRUE;

case IDCANCEL:

/* Destroy the dialog box. */

EndDialog(hDlg, TRUE);
return TRUE;

default:
return FALSE;

}

default:
return FALSE;

}
}

 

 

複数選択リスト ボックスの作成

次に示すコード例は、 上記の例で使われているのと同じダイアログ ボックスを初期化して表示します。しかし、 このコードでは、 LBS_MULTIPLESELスタイルを使って、 ユーザーが一度に複数のファイルを選択できるようにしています。ユーザーが[Delete]ボタンを選択したら、 LB_GETSELCOUNTメッセージを送って選択されているファイルの個数を取得し、 LB_GETSELITEMSメッセージを送って選択されているリスト ボックス項目の配列を取得します。ファイルを削除したら、 LB_DELETESTRINGメッセージを送って、 そのファイルに対応する項目をリスト ボックスから削除します。

 

#define BUFFER MAX_PATH

#define BIGBUFF 8192

/*
* FUNCTION: DlgDelFilesProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: "Delete files" dialog box
*/

BOOL APIENTRY DlgDelFilesProc(
HWND hDlg, /* window handle of dialog box */
UINT message, /* type of message */
UINT wParam, /* message-specific information */
LONG lParam)
{

DWORD cchCurDir;
LPTSTR lpszCurDir;
LPTSTR lpszFileToDelete;
int nSelItems;
int nSelItemsInBuffer;
TCHAR tchBuffer[BUFFER];
TCHAR tchMsgBuff[BUFFER];
int nBuffer[BIGBUFF];
int i;
BOOL fResult;
HWND hListBox;

switch (message) {

case WM_INITDIALOG:

/*
* Initialize the list box by filling it with files from
* the current directory.
*/

lpszCurDir = tchBuffer;
GetCurrentDirectory(cchCurDir, lpszCurDir);
DlgDirList(hDlg, lpszCurDir, IDL_FILES, IDS_PATHTOFILL, 0);

SetFocus(GetDlgItem(hDlg, IDL_FILES));

return FALSE;

case WM_COMMAND:

switch (LOWORD(wParam)) {

case IDOK:

/*
* When the user presses the Delete (IDOK) button,
* delete all the selected files.
*/

lpszFileToDelete = tchBuffer;

hListBox = GetDlgItem(hDlg, IDL_FILES);

nSelItems = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0);

nSelItemsInBuffer = SendMessage(hListBox, LB_GETSELITEMS,
512, (LPARAM) nBuffer);

if (nSelItems > nSelItemsInBuffer) {
MessageBox(hDlg, "Too many items selected.",
NULL, MB_OK);
} else {

for (i = nSelItemsInBuffer - 1; i > -1; i--) {

SendMessage(hListBox, LB_GETTEXT, nBuffer[i],
(LPARAM) lpszFileToDelete);

fResult = DeleteFile(lpszFileToDelete);
if (!fResult) {
sprintf(tchMsgBuff,
"Could not delete file: %s GetLastError = %u",
(LPARAM) lpszFileToDelete);
ErrorHandler(tchMsgBuff); /* app-defined */
} else {
SendMessage(hListBox, LB_DELETESTRING,
nBuffer[i], 0);
}
}

SendMessage(hListBox, LB_SETCARETINDEX, 0, 0);

}
return TRUE;

case IDCANCEL:

/* Destroy the dialog box. */

EndDialog(hDlg, TRUE);
return TRUE;

default:
return FALSE;

}

default:
return FALSE;

}
}

 

 

オーナー描画リスト ボックスの作成

次のコード例では、 オーナー描画項目を5つ含むリスト ボックスの描き方を示します。項目のうち、 4つは描画用の道具で、 1つはフォークです。各リスト項目はビットマップとして表示され、 オブジェクトの名前がその後ろに表示されます。ユーザーはほかの項目と似ていない項目をボタンで選ぶよう促されます。フォークを選択してボタンを押すと、 「You're right!」というメッセージが表示され、 ダイアログ ボックスはクローズします。フォーク以外の項目を選択してボタンを押すと、 「Try again!」というメッセージが表示されます。

このリスト ボックスは、 標準リスト ボックス スタイルのほかに、 LBS_OWNERDRAWスタイルとLBS_HASSTRINGSスタイルを持っています。LB_ADDSTRINGメッセージを送ってリスト ボックスにテキストを設定し、 LB_SETITEMDATAメッセージを送って各リスト ボックス項目にビットマップを関連付けます。また、 WM_MEASUREITEMメッセージを処理して各リスト ボックス項目の高さを設定し、 WM_DRAWITEMメッセージを処理して各項目のテキストとビットマップを描画します。

 

#define XBITMAP 80
#define YBITMAP 20

#define BUFFER MAX_PATH

HBITMAP hbmpPencil, hbmpCrayon, hbmpMarker, hbmpPen, hbmpFork;
HBITMAP hbmpPicture, hbmpOld;

/*
* FUNCTION: DlgDrawProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: "One of these things..." dialog box
*/

DWORD APIENTRY DlgDrawProc(
HWND hDlg, /* window handle of dialog box */
UINT message, /* type of message */
UINT wParam, /* message-specific information */
LONG lParam)
{

int nItem;
TCHAR tchBuffer[BUFFER];
HWND hListBox;
TEXTMETRIC tm;
int y;
HDC hdcMem;
LPMEASUREITEMSTRUCT lpmis;
LPDRAWITEMSTRUCT lpdis;
RECT rcBitmap;

switch (message) {

case WM_INITDIALOG:

/* Load bitmaps. */

hbmpPencil = LoadBitmap(hinst, MAKEINTRESOURCE(700));
hbmpCrayon = LoadBitmap(hinst, MAKEINTRESOURCE(701));
hbmpMarker = LoadBitmap(hinst, MAKEINTRESOURCE(702));
hbmpPen = LoadBitmap(hinst, MAKEINTRESOURCE(703));
hbmpFork = LoadBitmap(hinst, MAKEINTRESOURCE(704));

/* Retrieve list box handle. */

hListBox = GetDlgItem(hDlg, IDL_STUFF);

/*
* Initialize the list box text and associate a bitmap
* with each list box item.
*/

nItem = SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM) "pencil");
SendMessage(hListBox, LB_SETITEMDATA, nItem,
(LPARAM) hbmpPencil);

nItem = SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM) "crayon");
SendMessage(hListBox, LB_SETITEMDATA, nItem,
(LPARAM) hbmpCrayon);

nItem = SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM) "marker");
SendMessage(hListBox, LB_SETITEMDATA, nItem,
(LPARAM) hbmpMarker);

nItem = SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM) "pen");
SendMessage(hListBox, LB_SETITEMDATA, nItem,
(LPARAM) hbmpPen);

nItem = SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM) "fork");
SendMessage(hListBox, LB_SETITEMDATA, nItem,
(LPARAM) hbmpFork);

SetFocus(hListBox);

SendMessage(hListBox, LB_SETCURSEL, 0, 0);

return TRUE;

case WM_MEASUREITEM:

lpmis = (LPMEASUREITEMSTRUCT) lParam;

/* Set the height of the list box items. */

lpmis->itemHeight = 20;

return TRUE;

case WM_DRAWITEM:

lpdis = (LPDRAWITEMSTRUCT) lParam;

/* If there are no list box items, skip this message. */

if (lpdis->itemID == -1) {
break;
}

/*
* Draw the bitmap and text for the list box item. Draw a
* rectangle around the bitmap if it is selected.
*/

switch (lpdis->itemAction) {

case ODA_SELECT:
case ODA_DRAWENTIRE:

/* Display the bitmap associated with the item. */

hbmpPicture = (HBITMAP) SendMessage(lpdis->hwndItem,
LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);

hdcMem = CreateCompatibleDC(lpdis->hDC);
hbmpOld = SelectObject(hdcMem, hbmpPicture);

BitBlt(lpdis->hDC,
lpdis->rcItem.left, lpdis->rcItem.top,
lpdis->rcItem.right - lpdis->rcItem.left,
lpdis->rcItem.bottom - lpdis->rcItem.top,
hdcMem, 0, 0, SRCCOPY);

/* Display the text associated with the item. */

SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
(LPARAM) tchBuffer);

GetTextMetrics(lpdis->hDC, &tm);

y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
tm.tmHeight) / 2;

TextOut(lpdis->hDC,
XBITMAP + 6,
y,
tchBuffer,
strlen(tchBuffer));

SelectObject(hdcMem, hbmpOld);

DeleteDC(hdcMem);

/* Is the item selected? */

if (lpdis->itemState & ODS_SELECTED) {

/* Set RECT coordinates to surround only the bitmap. */

rcBitmap.left = lpdis->rcItem.left;
rcBitmap.top = lpdis->rcItem.top;
rcBitmap.right = lpdis->rcItem.left + XBITMAP;
rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;

/* Draw a rectangle around bitmap to indicate the selection. */

DrawFocusRect(lpdis->hDC, &rcBitmap);

}

break;

case ODA_FOCUS:

/*
* Do not process focus changes. The focus caret (outline
* rectangle) indicates the selection. The Which one? (IDOK)
* button indicates the final selection.
*/

break;
}

return TRUE;

case WM_COMMAND:

switch (LOWORD(wParam)) {

case IDOK:

/* Get the selected item's text. */

nItem = SendMessage(GetDlgItem(hDlg, IDL_STUFF),
LB_GETCURSEL, 0, (LPARAM) 0);
SendMessage(GetDlgItem(hDlg, IDL_STUFF), LB_GETTEXT,
nItem, (LPARAM) tchBuffer);

/*
* If the item is not the correct answer, tell the
* user to try again.
*
* If the item is the correct answer, congratulate
* the user and destroy the dialog box.
*/

if (strcmp(tchBuffer, "fork")) {
MessageBox(hDlg, "Try again!", "Oops.", MB_OK);
return FALSE;
} else {
MessageBox(hDlg, "You're right!", "Congratulations.",
MB_OK);

/* Fall through. */

}

case IDCANCEL:

/* Destroy the dialog box. */

EndDialog(hDlg, TRUE);
return TRUE;

default:

return FALSE;

}

case WM_DESTROY:

/* Free any resources used by the bitmaps. */

DeleteObject(hbmpPencil);
DeleteObject(hbmpCrayon);
DeleteObject(hbmpMarker);
DeleteObject(hbmpPen);
DeleteObject(hbmpFork);

return TRUE;

default:
return FALSE;

}
return FALSE;
}

 

 

リスト ボックス関数とメッセージ

リスト ボックスに関する関数とメッセージを次に示します。

 

関数

DlgDirList

DlgDirSelectEx

 

メッセージ

LB_ADDFILE

LB_ADDSTRING

LB_DELETESTRING

LB_DIR

LB_FINDSTRING

LB_FINDSTRINGEXACT

LB_GETANCHORINDEX

LB_GETCARETINDEX

LB_GETCOUNT

LB_GETCURSEL

LB_GETHORIZONTALEXTENT

LB_GETITEMDATA

LB_GETITEMHEIGHT

LB_GETITEMRECT

LB_GETLOCALE

LB_GETSEL

LB_GETSELCOUNT

LB_GETSELITEMS

LB_GETTEXT

LB_GETTEXTLEN

LB_GETTOPINDEX

LB_INSERTSTRING

LB_RESETCONTENT

LB_SELECTSTRING

LB_SELITEMRANGE

LB_SELITEMRANGEEX

LB_SETANCHORINDEX

LB_SETCARETINDEX

LB_SETCOLUMNWIDTH

LB_SETCOUNT

LB_SETCURSEL

LB_SETHORIZONTALEXTENT

LB_SETITEMDATA

LB_SETITEMHEIGHT

LB_SETLOCALE

LB_SETSEL

LB_SETTABSTOPS

LB_SETTOPINDEX

LBN_DBLCLK

LBN_ERRSPACE

LBN_KILLFOCUS

LBN_SELCANCEL

LBN_SELCHANGE

LBN_SETFOCUS

WM_CHARTOITEM

WM_DELETEITEM

WM_VKEYTOITEM

 

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします
inserted by FC2 system