リストコントロールの一行選択時、特定の列のアイテム、サブアイテムの色を変えないやり方


こだま  2011-03-26 23:21:59  No: 72497  IP: 192.*.*.*

いつも大変お世話になっております。

動作環境:VC2005,MFC

CListCtrlの一行選択設定時
特定のアイテム、サブアイテムは
色を変えないにはどうしたらよいでしょうか。

1.CListCtrl::SetExtendedStyle()でLVS_EX_FULLROWSELECTを設定
2.とある行を選択
3.対象の行のアイテム、サブアイテム全て
    が白抜き文字、青色背景色で選択される
    
    その時に、特定のアイテム、サブアイテムは
    元の文字色、背景色のままにしたい。
    
つまり、行選択されたとき
ある列だけは、文字色、背景色を変えたくないのです。

カスタムドローで設定しようとしましたが
うまくいきませんでした。

アドバイスいただけば幸いです。

編集 削除
眞鋳  2011-03-27 02:10:34  No: 72498  IP: 192.*.*.*

地味に真上にwindown乗せて文字を引っ張る・・・・バタ臭いですね
(でもその矩形に関しては結構情報は取れます)

エクセルを内部に入れてどうにかするというのもありますが。。。やったことないし、エクセルはかってにVer変えるし怖い存在。

MSの仕様なんですよね、メインアイテムは操作できるけど、サブまで
対応していないのが現実。
なぜ、その項目が背景を変えなければならないのですか?
そこの思想がはっきりしていないことには無駄な話になるんですけど。

すみませんその理由も一度考えた方がよい感じがしますが

編集 削除
こだま  2011-03-27 10:39:28  No: 72499  IP: 192.*.*.*

アドバイスありがとうございます。

やりたいことはいろいろあるのですが、
まずは、次のことができないかと思っています。

先頭列にチェックボックスを持った
リストコントロール(一行選択設定)を用意、
チェックボックスのところ以外は
一行選択できるようにしたい。

1.リストコントロールを用意します。
    例えば、列は3列設定するとします。

2.リストコントロールのカラム(列)を作ります。
    先頭列には、空欄にし
    それ以降2列目、3列目にはカラム情報を入れます。

3.リストコントロールにリストアイテム(行)を挿入します。
    先頭列(つまりアイテム)には何も入れません。
    それ以降2列目、3列目(つまりサブアイテム)に
    データを挿入します。

4.先頭列にチェックボックスをつけます。
    CListCtrl::SetExtendedStyle()でLVS_EX_CHECKBOXESを設定

5.例えば、チェックボックスをクリックすると
    先頭列以外は一行選択になる。

眞鋳さま

>地味に真上にwindown乗せて文字を引っ張る・・・・バタ臭いですね
>(でもその矩形に関しては結構情報は取れます)

このようなコントロールの場合には、
一行選択設定(LVS_EX_FULLROWSELECT)をせずに
オーナードロー(?)で地道にやった方がよいのでしょうか。

矩形領域の情報が取れると書かれましたが
方法をアドバイスを頂けると幸いです。

編集 削除
ホウジョウウサギ  2011-03-28 10:13:21  No: 72500  IP: 192.*.*.*

選択変更時に LVS_EX_FULLROWSELECT の設定を取ったり付けたりしてみてはどうでしょうか?
(↓のコードでは選択中の行をクリックしても動作してしまう等,ifの条件がダメダメみたいですけど…)

void CLCDlg::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    // TODO: ここにコントロール通知ハンドラ コードを追加します。
    *pResult = 0;

    if( !pNMLV->hdr.idFrom == IDC_LIST1 )return;
    if( (pNMLV->uChanged & LVIF_STATE)==0 )return;
    if(    (pNMLV->uOldState & LVIS_SELECTED)==0
        && (pNMLV->uNewState & LVIS_SELECTED) )
    {
        CListCtrl *pLC = (CListCtrl*)( GetDlgItem(IDC_LIST1) );
        if( pNMLV->iItem == 0 )
        {   //行0なら全体選択
            pLC->SetExtendedStyle( LVS_EX_FULLROWSELECT );
        }
        else
        {   //そうでないならLVS_EX_FULLROWSELECT設定をやめる
            pLC->SetExtendedStyle( 0 );
        }
    }
}

編集 削除
ひる  2011-03-28 14:02:07  No: 72501  IP: 192.*.*.*

> チェックボックスのところ以外は
> 一行選択できるようにしたい。

根本的な解決ではないかもしれませんが、
LVS_EX_BORDERSELECTを付けると画像部分は青くなりません。

先頭カラムに文字を入れないということはレポートスタイル前提でしょうし、
ユーザに先頭カラムの幅をいじられるのも想定外でしょうから、
うまく幅を設定すればそれっぽく見えるのではないでしょうか。

オーナ描画しない方法としてご参考まで。

編集 削除
こだま  2011-03-28 22:34:40  No: 72502  IP: 192.*.*.*

ありがとうございます。

ご指摘の内容を参考にして
修正対応します。

状況は追って報告いたします。

編集 削除
眞鋳  2011-03-28 22:45:05  No: 72503  IP: 192.*.*.*

>5.例えば、チェックボックスをクリックすると
>    先頭列以外は一行選択になる。
仕様なのですね、
CListCtrl クラス メンバでカラムの位置やら幅とか取得できますけど・・・

ここでどうでしょうかこんな手段は、
リストコントロールを2個並べて同期させるのはどうでしょうか
(多少の切れ目は出来るかもしれませんが、そこは調整とか・・・)
チェックボックス付きメインアイテムのリストと、その属性のリストを用意してみてはいかがでしょうか?
それなら属性のほうを一行選択でいけるのではないかと。

編集 削除
仲澤@失業者  2011-03-29 15:29:19  No: 72504  IP: 192.*.*.*

「LVS_OWNERDRAWFIXEDにして、全て自分で描画する」
が唯一の解決方法です。

編集 削除
眞鋳  2011-03-29 20:41:51  No: 72505  IP: 192.*.*.*

あれ、俺の勘違いかもしれなくて、すみません。

もしかしてチェックした行(横)で指定位置のカラム(縦)の
背景色とか文字色を変えるのですか?
セレクト行がという問題より?

それなら、オーナードローで幾らでも、行、カラムの操作簡単です、
解決してるのなら、放置してください、していないのでしたら
返信をお願いします、ソースレベルで存在しますので。

編集 削除
こだま  2011-03-29 22:41:36  No: 72506  IP: 192.*.*.*

いろいろありがとうございます。

まず、仕様が分かりづらかったので
もう一度記します。

・リストコントロールの先頭列(アイテム)には
  チェックボックスを
  2列目以降(サブアイテム)からは情報を入れます。
・このリストコントロールはチェックボックスをクリックすると
  選択状態になり、チェックボックスの列を除いた、
  対象行が一行選択されます。
  チェックボックス以外の場所をクリックしても
  一行選択できません。
・再度、チェックボックスをクリックすると
  非選択状態になり、チェックボックスの列を除いた
  対象行の一行選択が解除されます。
  チェックボックス以外の場所をクリックしても
  一行選択の解除はできません。

眞鋳さま、
オーナー描画の話がでてきましたのでお尋ねします。

・行カラムの操作は解決していません。
・それ以前に、先頭列にチェックボックス
  入れるやり方がわかっておりません。

アドバイスいただけると幸いです。

よろしくお願いいたします。

編集 削除
眞鋳  2011-03-30 00:04:26  No: 72507  IP: 192.*.*.*

単純にこぴぺするので、見づらいかもしれないが。(多少手を入れてるのでミスあるかも)

リストボックスにチェックボックスつけるのはListView_SetExtendedListViewStyle() を検索すれば出てくるよ。あとは
そこからLVS_EX_CHECKBOXESかな。


リストビューのオーナドローはこれでいけると思う、行列で文字と背景の色を変えられるよ。

  //{{AFX_MSG(CXXXXXXView)
  ・・・・・・・・・・・・・・・
  ・・・・・・・・・・・・・・・  
  //}}AFX_MSG
  afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
  DECLARE_MESSAGE_MAP()



BEGIN_MESSAGE_MAP(CXXXXXXView, CListView)
  //{{AFX_MSG_MAP(CXXXXXXView)
  ・・・・・・・・・・・・・・・
  ・・・・・・・・・・・・・・・  
  //}}AFX_MSG_MAP
  ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnNMCustomdraw)            //リストビュー色周り
END_MESSAGE_MAP()


void CXXXXXXView::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMCUSTOMDRAW pCDbase = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    LPNMLVCUSTOMDRAW lpCusDraw = (LPNMLVCUSTOMDRAW)pCDbase;

    // Draw message get
    if (lpCusDraw->nmcd.dwDrawStage == CDDS_PREPAINT ||
    lpCusDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT){
        // Custom draw use message set
        *pResult =  CDRF_NOTIFYSUBITEMDRAW;
        return;
    }

    // item message get
    if (lpCusDraw->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)) {
    // Row and Col no get
    int iRow = lpCusDraw->nmcd.dwItemSpec;
    int iCol = lpCusDraw->iSubItem;        //LPNMLVCUSTOMDRAW iSubItem 
    if(iCol != 0) {// not main item RGB(128,255,255);
      lpCusDraw->clrTextBk=RGB(128,255,255);
    }
    if(!(iRow%2)){div 2 ok ? RGB(255,0,0)
      lpCusDraw->clrText = RGB(255,0,0);
    }
    *pResult = CDRF_NEWFONT;  
    }
    *pResult = 0;
}

ただ、中身をきちんと理解してね、検索すればばきちんと出てくるから。
がんばれ。

編集 削除
こだま  2011-03-30 21:06:18  No: 72508  IP: 192.*.*.*

眞鋳さま

ありがとうございます。

残念ながら、オーナードローでは
LVS_EX_CHECKBOXESは使えないのです。

チェックボックスデータの固まり
OBM_CHECKBOXES
を独自にロードしなければいけないのですが
経験がなく、苦戦しております。

アドバイスいただけると幸いです。

編集 削除
仲澤@失業者  2011-03-31 14:32:26  No: 72509  IP: 192.*.*.*

リストコントロール(リストビュー)は意外に融通がききません。
ちょっと凝ったことをさせようとするとすぐに破綻します。
プレーンな状態でできる範囲のことをさせるか、
又はLVS_OWNERDRAWFIXEDを指定して、ボタンから何から全て
自前で描画するのが、近道だと考えます。
オーナードローで済めばそれでも良いのですが、今回の仕様は
その範疇に収まりきらない可能性が高いと考えます。

編集 削除
眞鋳  2011-03-31 20:26:06  No: 72510  IP: 192.*.*.*

オーナードローで行ってたのですね、チェックボックス以外はどうにかしたのですから、がんばってください。

ただ、キーボードの時どうするかも考慮して下さい。

すみません、私のはオーナドローというかカスタムでした。

編集 削除