技術ノート:リストボックスの項目を右クリックで選択する
ダイアログボックス上に置かれたリストボックスは 左クリックなら項目が切り替わるし、 ダイアログにWM_COMMANDメッセージも来る。
しかし右クリックをしても無反応なのだ。 場合にもよるが、右クリックメニューで項目を削除したいときなど 右クリックにも反応して欲しいことがある。
Windowsでも壁紙を選ぶリストボックスは ちゃんと右クリックで項目選択できる。
ネットでやり方を探ってみると ダイアログへ行くマウスの情報をフックするとか、 クリックしたときのマウスの座標を リストボックスの1項目分の高さで割って 上から何番目の項目を選んだか見極めるとか、 割と面倒で無理やりな方法が紹介されている。
しかし、リストボックスはスクロールされている可能性もあるし、 項目を選択するだけでそこまで手間をかけたくない。
で、いろいろ調べて割とシンプルな方法を見つけた。
ダイアログ上で右クリックするとWM_CONTEXTMENUメッセージが来る。 そのときwParamには マウスカーソル直下にあるウィンドウのハンドルが入る。
そのハンドルがリストボックスのハンドルかどうかを調べれば リストボックスが右クリックされたことを確認できる。
case WM_CONTEXTMENU: //ダイアログ上で右クリックがされた if((HWND)wParam==GetDlgItem(hDlg,IDC_PHOTOLIST)){ //IDC_PHOTOLIST(リストボックス)がクリックされた } break;
さらに自分でマウスの座標から どの項目がクリックされたか算出しなくても LBItemFromPt関数が用意されている。 マウスの座標を渡せば、マウスの直下にある項目の インデックスを返してくれる。
WM_CONTEXTMENUメッセージでは lParamの上位と下位にマウス座標が入っているので それを取り出して渡せばよい。
POINT pt; pt.x=LOWORD(lParam); pt.y=HIWORD(lParam);
int SelNo; SelNo=LBItemFromPt((HWND)wParam,pt,FALSE);
さきほどの部分と組み合わせれば
case WM_CONTEXTMENU: //ダイアログ上で右クリックがされた HWND hwndTmp; hwndTmp=(HWND)wParam; if(hwndTmp==GetDlgItem(hDlg,IDC_PHOTOLIST)){ POINT pt; pt.x=LOWORD(lParam); pt.y=HIWORD(lParam);
int SelNo; SelNo=LBItemFromPt(hwndTmp,pt,FALSE);
if(SelNo>=0){ //クリックされた項目を選択する SendMessage(GetDlgItem(hDlg,IDC_PHOTOLIST), LB_SETCURSEL,SelNo,0); } } break;
という感じになる。
ネット上で発見した方法よりもだいぶシンプルな解決法とは思う。 デスクトップ写真立てのVer.1.10からは 登録した写真を右クリックメニューで削除できるようになっているが、 それを実現するためだけに結構な苦労と時間をかけた。
|