• ベストアンサー

リストビューで選択行の背景を変える

お世話になります。リストビューの選択行の背景色を変えたいと思い、カスタムドローを用い以下のようにしましたが、選択していない所も赤になってしまいます。 if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {  // 選択行の背景色を変更  if (lplvcd->nmcd.uItemState & CDIS_SELECTED) {   lplvcd->clrTextBk = RGB(255, 0, 0);   lplvcd->nmcd.uItemState &= ~CDIS_SELECTED;  } else {   lplvcd->clrTextBk = RGB(255, 255, 255);  }  return CDRF_NOTIFYSUBITEMDRAW; } デバッグモードで見ると、else以降の分は解釈されていないようです。 リストビューは g_hList = CreateWindowEx(0 , WC_LISTVIEW , 0 , WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOSORTHEADER | LVS_SHOWSELALWAYS, 1 , 1 , width , lv_height , g_hMain , (HMENU)1 , g_hInst , NULL); dwStyle = ListView_GetExtendedListViewStyle(g_hList); dwStyle |= LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES; ListView_SetExtendedListViewStyle(g_hList, dwStyle); ListView_SetBkColor(g_hList, RGB(240,240,240)); のようにしています。宜しくお願いします

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★『CDIS_FOCUS』定数を付けてみて下さい。 ・つまり >if ( lplvcd->nmcd.uItemState & CDIS_SELECTED ){  ↑  ここの部分を  int check = (CDIS_SELECTED | CDIS_FOCUS);    if ( (lplvcd->nmcd.uItemState & check) == check ){  とします。 ・リストビューやツリービューでは選択された場所を CDIS_SELECTED と CDIS_FOCUS 定数の  両方のビットが立っているときです。CDIS_SELECTED 定数だけでは判定するのに不十分です。  他にも LVNI_SELECTED、LVNI_FOCUSED 定数も同じ考えで2つ指定してから判定します。 ・以上。

masaota56
質問者

補足

ありがとうございます、できました。 ただ複数行選択の場合にフォーカスがある行しか反映されません。この場合はどうしたらいいでしょうか。 色々いじったのですが分かりませんでした・・・ //行毎の描画 if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {  // 選択行の背景色を変更  int check = (CDIS_SELECTED | CDIS_FOCUS);   if ((lplvcd->nmcd.uItemState & check) == check){    lplvcd->clrTextBk = RGB(0,0,0);    lplvcd->clrText = RGB(255,255,255);    lplvcd->nmcd.uItemState &= ~CDIS_SELECTED;   }   return CDRF_NEWFONT; }

その他の回答 (2)

  • iyomante
  • ベストアンサー率60% (14/23)
回答No.3

複数選択時にフォーカスのある行だけ反映されてしまうのは、 CDIS_FOCUS を追加してるからですよ。 LVS_SHOWSELALWAYS これはフォーカスがなくても選択状態を表示するオプションですですから、それを意図して組んでらっしゃるのだと思いますが。 その部分に関しては最初のソースが正しいと思います。 それでは。

masaota56
質問者

お礼

LVS_SHOWSELALWAYSをつけると希望の動作はできないのですね。 何度もありがとうございました。

  • iyomante
  • ベストアンサー率60% (14/23)
回答No.2

if (lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT) { return CDRF_NOTIFYITEMDRAW; } if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { if (lplvcd->nmcd.uItemState & CDIS_SELECTED) { lplvcd->clrTextBk = RGB(255, 0, 0); lplvcd->nmcd.uItemState &= ~CDIS_SELECTED; } else { lplvcd->clrTextBk = RGB(255, 255, 255); } return CDRF_NEWFONT; } これでいいんでは? CDDS_PREPAINT の場合の処理と CDRF_NEWFONT を返すようにする部分が、抜けていたのでは。

masaota56
質問者

お礼

すみません、補足の補足です。 CDRF_NEWFONTは最初つけていませんでした。今はつけています。

masaota56
質問者

補足

回答ありがとうございます。両方ともつけています。 どうもCDIS_SELECTEDのみだと選択していないものも検知してしまうようで、全てが赤になってしまいます。 当初の質問はNo.1さんの回答で解決したのですが、今度は複数選択時に苦戦しています。。。

関連するQ&A

  • リストビューのカスタムドローについて

    Windows XP SP3 + Visual Studio 2008 C++ で、リストビューを使用したダイアログベースのソフトを作っています。 リストビューには、ファイル名、ファイルサイズ、最終更新日時を「詳細」で表示させています。(よくあるファイル一覧です。) エクスプローラと同じように、ファイル名等のテキストを NTFS の圧縮ファイルは青 暗号化ファイルは緑 で表示させようと思い、カスタムドローを使用しています。 また、圧縮でもなく暗号化でもないファイルに対しては、ChooseFont() で選択された色 ( CHOOSEFONT 構造体の rgbColors ) を設定しています。 ChooseFont() で選択した色のうち、濃紺以外の色は問題なく表示されているのですが、なぜか、ChooseFont で濃紺 ( 0x00800000 ) を選択した場合だけ、第一列 ( ファイル名 ) のみ濃紺になり、第二列目以降 ( ファイルサイズ、最終更新日時 ) が、システム設定値 ( 黒 ) となります。 しかも、リストビューのスタイルを拡張スタイルの LVS_EX_FULLROWSELECT ( 行選択モード? ) にすると、濃紺の場合でも、第二列目以降も正常に表示されます。 コーディングは、カスタムドローの部分だけを抜粋すると以下のような感じになっています。 LPNMLVCUSTOMDRAW pnmlvcd; LVITEM lvi; DWORD dwAttributes; switch( message ) { case NM_CUSTOMDRAW:   pnmlvcd = ( LPNMLVCUSTOMDRAW )lParam;   switch( pnmlvcd->nmcd.dwDrawStage ) {   case CDDS_PREPAINT:     SetWindowLong( hwndMain, DWL_MSGRESULT, ( LONG )CDRF_NOTIFYITEMDRAW );     return( TRUE );   case CDDS_ITEMPREPAINT:     lvi.mask = LVIF_PARAM;     lvi.iSubItem = 0;     lvi.iItem = pnmlvcd->nmcd.dwItemSpec; // 描画しようとしている行のインデックス     if( ListView_GetItem( hwndList, &lvi ) ) {       // 属性を取得       // lvi.lParam はファイルの情報を格納した構造体 FILEITEM へのポインタです。       dwAttributes = ( ( PFILEITEM )lvi.lParam )->dwAttributes;       if( 通常ファイルの場合 ) {  // dwAttributes を使用して属性を判定         // ChooseFont で選択した色を設定         pnmlvcd->clrText = cfList.rgbColors;         SetWindowLong( hwndMain, DWL_MSGRESULT, ( LONG )CDRF_DODEFAULT );         return( TRUE );       } else if( 圧縮ファイルの場合 ) {  // dwAttributes を使用して属性を判定         // 青         pnmlvcd->clrText = RGB( 0, 0, 0xff );         SetWindowLong( hwndMain, DWL_MSGRESULT, ( LONG )CDRF_DODEFAULT );         return( TRUE );       } else if( 暗号化ファイルの場合 ) {  // dwAttributes を使用して属性を判定         // 緑         pnmlvcd->clrText = RGB( 0, 0xff, 0 );         SetWindowLong( hwndMain, DWL_MSGRESULT, ( LONG )CDRF_DODEFAULT );         return( TRUE );       }     }   }   break; hwndMain はダイアログのウィンドウハンドル、hwndList はリストビューのウィンドウハンドルです。 (見やすくするため、スペースに全角スペースを使用しています。また、属性の判定部分は実際には dwAttributes との、&、| を使用しています。) コーディング的には、ChooseFont() で何色が選択されようが知ったこっちゃないという感じなのですが・・・。 試しに、ChooseFont() で選択した色ではなく、RGB( 0, 0, 0x80 ) を指定しても同様の現象でした。 濃紺の場合でも、LVS_EX_FULLROWSELECT でなくても第二列目以降が正しい色で表示されるようにする方法はないでしょうか。 このリストビューは Drag & Drop のソース側の機能も実装していまして、その影響で、LVS_EX_FULLROWSELECT だと、Drag 操作による複数行選択の操作が難しくなるので、LVS_EX_FULLROWSELECT は避けたいと考えています。 あるいは、上記のコーディングで、何かおかしいんじゃないかという部分がありましたら教えていただけませんでしょうか。 よろしくお願いします。

  • VB6 API LISTVIEW(チェックボックス付き)にチェックを付けたい

    CreateWindowExでLISTVIEW(チェックボックス付きのレポートビュー)を作ったのですが、「山田花子」行にソースでチェックを付ける方法が分かりません。 Form1のソース ↓ Option Explicit Private Sub Form_Load() Dim lngRet As Long Dim lvcol As LV_COLUMN Dim rStyle As Long Dim item As LV_ITEM '-- リストビューの作成 hList = CreateWindowEx(WS_EX_CLIENTEDGE, _ WC_LISTVIEW, "", _ WS_CHILD Or WS_VISIBLE Or WS_BORDER Or _ WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or _ LVS_REPORT, _ 0&, 0&, Me.ScaleWidth / Screen.TwipsPerPixelX, 200&, _ Me.hwnd, _ 0&, _ App.HINSTANCE, _ ByVal 0&) '拡張スタイルを設定 rStyle = rStyle Or LVS_EX_FULLROWSELECT Or LVS_EX_GRIDLINES Or LVS_EX_CHECKBOXES SendMessageByNum hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0&, rStyle '-- カラムヘッダーの追加 With lvcol .mask = LVCF_FMT Or LVCF_WIDTH Or LVCF_TEXT Or LVCF_SUBITEM .fmt = LVCFMT_LEFT .cx = 100 .pszText = "名前" .iSubItem = 0 lngRet = ListView_InsertColumn(hList, 0&, lvcol) End With '-- リストアイテムの追加 With item .mask = LVIF_TEXT Or LVIF_IMAGE ' 1つめ .pszText = "山田 太郎" .iItem = 0 .iSubItem = 0 .iImage = 0 lngRet = ListView_InsertItem(hList, item) ' 2つめ .pszText = "山田 花子" .iItem = 1 .iSubItem = 0 .iImage = 1 lngRet = ListView_InsertItem(hList, item) End With End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) '-- リストビューを破棄 DestroyWindow hList End Sub 標準モジュールは補足に書きます

  • リストビューにフォーカスを設定するには

    開発環境はVC++6.0、SDK、Windows2000です。 CreateWindowEx( 0, WC_LISTVIEW, "", WS_CHILD | WS_VISIBLE | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL, 10, 10, 515, 271, hdwnd, (HMENU)100, hInstance, NULL); 上記APIでリストビューを表示しているのですが、表示直後には先頭ラインにフォーカスが設定されません。 当然表示された後にマウス操作にてラインをクリックするとフォーカスがあたるのですが、 表示された直後に指定行にフォーカスをあてたい場合にはどうすればよいでしょうか? ご存知の方ご教授お願いします。

  • リストビューに色はつかない?

    CreateWindowEx を使ったリストビュー(WC_LISTVIEW) についてなんですが、 マクロの、ListView_InsertItem (hList, &item) で、リストに追加しますよね。 その際、カラーはできないのでしょうか。 例えば、一行おきに色を変えるとか・・・ SetTextColor(hdc, RGB(0, 255, 0)) とか SendMessage(hList, WM_SETFONT, (WPARAM)hFont, 0) とかいろいろ 見たり試したりしたのですが、無理なんでしょうか。

  • LVS_EX_FULLROWSELECTが効かない

    LVS_EX_FULLROWSELECTをリストコントロールに指定して、一行選択をしたいのですが、なぜか効きません。なぜでしょうか? ソース---------------- BOOL CXXXXXX::OnInitDialog() { CPropertyPage::OnInitDialog(); ListView_SetExtendedListViewStyle( m_LIST.m_hWnd , LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_UNDERLINEHOT ); ・・・・・ } プロパティページ内にリストコントロールを貼り付けて使っています。 よろしくお願いします。

  • エクセルVBA リストビュー選択項目を別フォームへ

    皆さんこんにちは。 エクセル2013使用のVBA初心者です。 エクセルVBAのリストビューについて教えてください。 Userform1上にListview1とコマンドボタン1があります。 Listview1はSheet1を呼び込んだものが反映されており 左から駅名・顧客名・店舗名が記載されています。 Listview1でどれかを選択してコマンドボタン1を押したら Listview1で選択した項目の 駅名をUserform2のTextbox1に 顧客名を〃のTextbox2に 店舗名を〃のTextbox3に反映したいのですが リストビューの情報がネット上にも少なく コードをどのように書いたら良いか見当がつきません。 Userform2のPrivate Sub UserForm_Initialize()に TextBox1 = UserForm1.ListView1.FocusedItem.SubItems(0).Text を記載してみたものの、コンパイルエラーが出てしまいます。 (スイマセン、あまり意味が分かっていないで書きました) リストビューで選択した項目を別のユーザーフォームに 反映させるにはどうしたら良いでしょうか? どなたかヒントをいただけると助かります。

  • CreateWindowEx のウィンドウスタイルが反映されないのですが・・・

    CreateWindowEx のウィンドウスタイルが反映されないのですが・・・ VC++6.0 の SDK にて、ウィンドウを表示するプログラムを作成中なのですが、 スタイルが思うように反映されません。なぜなのでしょうか。 hList = CreateWindowEx( 0,      WC_LISTVIEW, "",       WS_CHILD | WS_VISIBLE |//猫でもわかる ~ によるうとデフォルトで必要らしい      WS_EX_CLIENTEDGE |   // 縁が沈んで見える境界線を持ちます。→ 持ちません      WS_EX_ACCEPTFILES |  // ドラッグ&ドロップを受けるとあるが、テキストをドロップしても×マーク      WS_EX_RIGHTSCROLLBAR | // 右スクロールバーが出るはずなのに・・・      LVS_REPORT,       // カラムのタイトル      0, 0, 0, 0,      hWnd,      (HMENU)LISTVW_HI_1,      hInst,      NULL);

  • リストビューの選択状態を取得するメッセージはありますか?

    リストビューが選択状態(1行が青色や灰色の背景になる状態)にあって、エディットボックスが空欄では無いときに、 あるボタンを有効にするという処理をしたいと思っています。 リストビューが選択されていることを教えてくれるメッセージがあれば、教えてください。よろしくお願いします。 環境:Win32 API, VC++6.0

  • ActiveBasic ListView 選択を移動させたい

    SendMessage関数を使って、ListViewの選択されているアイテムの場所を移動させたいのですが、 思うように動きません。 Dim lv As LVITEM With lv .iItem=PlayListNum[RandomFlag] .mask=LVIF_STATE .state=LVIS_SELECTED End With SendMessage(hList,LVM_SETITEM,0,VarPtr(lv)) ※hListには、ListViewのハンドルが格納されてあります。 ご存知の方、いらっしゃいましたら、やり方の方をご教授下さい。 Win XP AB 4.23.00

  • リストビューのスクロール

    お世話様です。 C#.NET(1.1)でプログラミングしています。 リストビューですが以下の設定を行っています。 CheckedBox=true View=List MultiSelect=true Scrollable=true ※カラム関係は何も設定してません。 この設定で、アイテムをどんどん追加していき、ListViewの最大高さまで アイテムが埋まると、水平スクロールが表示され2列目が表示されるのですが、これを垂直スクロールで下に追加という形をとりたいのですが、 どうしたらいいのかわからないです。 (なぜCheckListBoxにしないのかというのは、複数選択ができないからです。) ご存知の方、ご教授願います。(××)

専門家に質問してみよう