リストコントロ-ルのセル選択を実装(3)

ここからセルに対してクリックされた状態での動きを説明致します、なを前のペ-ジにコ-ドを追加して行きます。ドキュメントクラスに追加された構造体はドキュメントクラスが構築された時に一度だけ初期化を行ないますがその後は絶えず現在のリストコントロ-ルの状態を保持します、又リストコントロ-ルの表示デ-タ等はスタティック領域に耐えず確保されています、なのでこのフォ-ムビュ-が破棄された後に再度構築された場合には破棄された時点の表示内容を再現する事が出来ます。ビュ-が切り替わるアプリケ-ションでは必ず必要になる基本機能ですから手順を覚えて下さい。

Vew切り替え処理で多発する例外

多くの方がアプリケ-ションを完成した時点でリリ-スバ-ジョンへ移行しようと考えます、しかしこの時点でVew切り替えで多発する例外処理で失敗し泥沼にはまります、これらは基本を理解していない場合に発生します。デバック期間ではデバッガ-が強力にアプリケ-ションを保護してくれる為に問題が無いように見えてしまいますがリリ-スバ-ジョンではデバッガ-が外れて保護機能が無くなりロケ-ションはリンカ-が全て行いますのでメモリ-管理が正常に機能しなくなりこれがアプリケ-ションを不安定にさせシステムダウンに繋がるのです。


過去情報<-現在情報<-新情報を設定

このイベントはリストコントロ-ルのセルがクリックされると呼び出されて来ます、そこで前回の選択セル情報を過去情報に移動して今回選択されたセル情報を現在の選択情報に設定し保持する関数です。


セル情報保持 構造体

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct CLICK_AFTER{
     int nmId;
     int nitem;
     int subItem;
     int OldnmId;
     int Oldnitem;
     int OldsubItem;
     BOOL Click;
     BOOL Delate;
     BOOL DbleClick;
     BOOL RightClick;
}s_ClickAfter;


クリック.イベントハンドラ―

/////////////////////////////////////////////////////////////////////////////
////////////////////リストボックスコントロ-ル///////////////////////////////
/////////////////////// クリック ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void RightFormVew::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
CControlPracticeDoc* pDoc = GetDocument();

//=======================================-
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
NMLVDISPINFO *pdi=(NMLVDISPINFO*)pNMHDR;
if (pNMLV->iItem<0) return; *pResult = 0;
CString sval=_T("");
//=======================================-

sval.Format(_T("%s"),CtlistControl1.GetItemText(pNMLV->iItem,0)) ;//セル内容を確認する
pDoc->ms_ClickAfter.Oldnitem  =pDoc->ms_ClickAfter.nitem  ;//セル番号を過去へ移動
pDoc->ms_ClickAfter.OldsubItem=pDoc->ms_ClickAfter.subItem;//セル番号を過去へ移動
pDoc->ms_ClickAfter.OldnmId   =pDoc->ms_ClickAfter.nmId   ;//過去のLIST_ID番号を過去へ
//=======================================-
pDoc->ms_ClickAfter.Click=true    ;
pDoc->ms_ClickAfter.nmId=IDC_LIST1;
pDoc->ms_ClickAfter.nitem=pNMLV->iItem     ;//選択されたセル番号
pDoc->ms_ClickAfter.subItem=pNMLV->iSubItem;//選択されたセル番号
//=======================================-
CtlistControl1.Invalidate(FALSE);           //再表示を行います

}


セレクトされた状態です


追加された関数内のコ-ド

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void RightFormVew::List1RowListControl(CDC* pDC,int nItem)
{
CControlPracticeDoc* pDoc = GetDocument();

//=========================================================
COLORREF clrTextSave =pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
COLORREF clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
//==================ブラシの初期化=========================    
CBrush cbrA,cbrB;
//RGB(255,241,0)  RGB(243,152,0) RGB(233,83,131) 
//RGB(143,195,31) RGB(0,153,217) RGB(237,109,70) 
cbrA.CreateSolidBrush(RGB(233, 83,131));
cbrB.CreateSolidBrush(RGB(255,255,255));
//=========================================================
CPen      pen;
CPen* pOldPen;
pen.CreatePen(PS_SOLID,1,LINE_COLOR);
pOldPen=pDC->SelectObject(&pen);
//=========================================================
CRect rcAllLabels;
CtlistControl1.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
//=========================================================
CRect lRect,rc;
pDC->SetTextColor(RGB(0,0,0));
//=========================================================
int topIndex=CtlistControl1.GetTopIndex();            //表示の先頭nItem
int nLast = topIndex+CtlistControl1.GetCountPerPage();//表示の後端nItem

//======================列幅は3個です======================
for(int i=0; i<3; i++){
        //=====================================
        pDC->SelectObject(&pen);    
        //=====================================
        CtlistControl1.GetSubItemRect(nItem,i,LVIR_BOUNDS,lRect);
        //================縦線===============
        pDC->MoveTo(lRect.left,lRect.top)    ;
        pDC->LineTo(lRect.left,lRect.bottom) ;
        //================横線===============
        pDC->MoveTo(lRect.left ,lRect.bottom);
        pDC->LineTo(lRect.right,lRect.bottom);
        //================文字を表示します==========
        lRect.right=CtlistControl1.GetColumnWidth(i);
        lRect.top+=1; lRect.bottom-=1;
        pDC->SetTextColor(RGB(0,0,0));
        //==========================================
        if((pDoc->ms_ClickAfter.nitem==nItem)&&(pDoc->ms_ClickAfter.Click==TRUE)){
                    if(pDoc->ms_ClickAfter.subItem==i) pDC->FillRect(lRect,&cbrA);//反転
                    }
        if((pDoc->ms_ClickAfter.Oldnitem==nItem)&&(pDoc->ms_ClickAfter.OldsubItem==i)){
                    pDC->FillRect(lRect,&cbrB) ;//非反転
                    }
        CString vt=_T("");
        vt.Format(_T("文字列=%s"),CtlistControl1.GetItemText(nItem,i));    
        pDC->DrawText(vt,-1,lRect,DT_LEFT | DT_SINGLELINE | DT_VCENTER);
        }

}

上記コ-ドで緑色の文字列が新しく追加されています、上記はリストコントロ-ルのインバリドにより上記の「CtlistControl1.Invalidate(FALSE); //再表示を行います」でハンドラが強制的に呼びだされて来ます。

次はセルに文字列を入力出来る様にします


リストコントロ-ルのセル選択を実装(2)            リストコントロ-ル・セルに文字列を設定