[MFC] ListCtrl
==========================================
1. 특정 ROW 포커스 주기
2. 특정 ROW로 가기
3. 헤더 컬럼수 얻어오기
4. 컬럼의 너비를 이쁘게 주기
5. 한줄 쭉 선택되게 하기, 그리드 라인 주기
6. 선택한 아이템(ROW)를 지우기
7. 두 아이템을 스왑 하기
8. 기존에 선택되어있는 것을 해체하기
9. List Control의 0번째 컬럼 사이즈 변경하지 못 하도록 프로그래밍
10. List Control 에 다른 Control 넣기
11. List Control 행크기 늘리기
12. List Control 에서 시스템 아이콘 사용하기
1. 특정 ROW 포커스 주기
---------------------------------------------------
리스트 컨트롤에서 어떤 특정 Row를 선택하게 하고 싶을때
( 이때 선택뿐아니라 포커스도 가야 한다.
포커스가 간다는 의미는 다음에 키다운을 하면 바로 부드럽게
다음 아이템을 가리키도록 하는 것이다 )
ListView_SetItemState (pListCtrl->GetSafeHwnd(), // handle to listview
10, // index to listview item
LVIS_FOCUSED | LVIS_SELECTED, // item state
0x000F); //mask
위와 같이 코딩하면 된다.
2. 특정 ROW로 가기
---------------------------------------------------
만일 원하는 Row를 스크롤을 하던 어떻게 하든 화면에 보이게
하고 싶을때
pListCtrl->EnsureVisible(15, TRUE);
이렇게 하면 된다.
3. 헤더 컬럼수 얻어오기
---------------------------------------------------
헤더 컬럼의 갯수를 알고 싶을때
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
또는 pList->GetHeaderCtrl()을 통해서 얻어올수 도 있다.
4. 컬럼의 너비를 이쁘게 주기
---------------------------------------------------
공백없이 잘 채워 준다.
부모 다이얼로그의 OnSize에서
void CAttrListDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if( IsWindow( z_AttrList.m_hWnd ))
{
z_AttrList.MoveWindow( 0, 0, cx, cy );
z_AttrList.SetColumnWidth(1 , LVSCW_AUTOSIZE_USEHEADER);
}
}
5. 한줄 쭉 선택되게 하기, 그리드 라인 주기
---------------------------------------------------
z_AttrList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
6. 선택한 아이템(ROW)를 지우기
---------------------------------------------------
CDWordArray m_anDragIndexes; // 선택한 아이템을 기억하는
배열
int CAttrList::fnRemoveItem()
{
m_anDragIndexes.RemoveAll();
POSITION pos = GetFirstSelectedItemPosition();
while (pos)
{
m_anDragIndexes.Add(GetNextSelectedItem(pos));
}
int nSize = m_anDragIndexes.GetSize();
int nRet = -1;
if( nSize )
nRet = m_anDragIndexes[0];
while( nSize-- )
DeleteItem( m_anDragIndexes[nSize] );
m_anDragIndexes.RemoveAll();
return nRet;
}
7. 두 아이템을 스왑 하기
---------------------------------------------------
void CAttrList::fnSwapItem( int nItem1, int nItem2 )
{
int hi = nItem2;
int lo = nItem1;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi;
CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
int nColCount =pHeaderCtrl->GetItemCount();
rowText.SetSize( nColCount );
int i;
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
lvitemhi = lvitemlo;
lvitemhi.iItem = hi;
GetItem( &lvitemlo );
GetItem( &lvitemhi );
for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i));
lvitemhi.iItem = lo;
SetItem( &lvitemhi );
for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]);
lvitemlo.iItem = hi;
SetItem( &lvitemlo );
}
8.기존에 선택되어있는 것을 해체하기
-----------------------------------
int nOldItem = GetSelectionMark();
if( nOldItem > 0 )
SetItemState( nOldItem , 0, LVIS_SELECTED);
void SetCurSel(int nIndex, BOOL bIsTrue)
{
SetItemState(nIndex, bIsTrue ? LVIS_SELECTED | LVIS_FOCUSED : 0, LVIS_SELECTED | LVIS_FOCUSED);
}
9. List Control의 0번째 컬럼 사이즈 변경하지 못 하도록 프로그래밍
----------------------------------------------------------------------
BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
/*
//사이즈가 80 이하 안되게 만든다.
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
if((pHDN->hdr.code == HDN_ITEMCHANGINGW || pHDN->hdr.code == HDN_ITEMCHANGINGA)
&& pHDN->pitem->cxy < 80)
{
*pResult = TRUE; // disable change
return TRUE; // Processed message
}*/
/* // 컬럼 사이즈 변경 못하게 만든다.
// 모든 칼럼.
switch (((NMHDR*)lParam)->code)
{
case HDN_BEGINTRACKW:
case HDN_BEGINTRACKA:
*pResult = TRUE; // disable tracking
return TRUE; // Processed message
default: break;
}
// 특정 칼럼.
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
if((pHDN->hdr.code == HDN_BEGINTRACKW || pHDN->hdr.code == HDN_BEGINTRACKA)
&& pHDN->iItem == 0) // Prevent only first (col# 0) from resizing
{
*pResult = TRUE; // disable tracking
return TRUE; // Processed message
}*/
return CListCtrl::OnNotify(wParam, lParam, pResult);
}
10. List Control 에 다른 Control 넣기
----------------------------------------------------------------------
1. 요약
특정 Column에서 다른 Control 을 띄우는 방법 설명. 여기서 사용한 방법은 현재 Cursor가 있는 위치를 파악한후 그 위치에 적당한 크기의 Edit Control를 생성 시킨다.
2. 본문
1) CListCtrl를 상속받는 CMyList라는 Class를 만든다.
2) Member변수로 CEdit m_ctrEdit를 선언한다.
3) Member함수로 OnLButtonDown()과 GetSubItemFrompt(point, nItem, nSubItem, rcClient)를 선언 OnLButtonDown() : Edit Control를 생성/삭제 시키는 역할 GetSubItemFrompt(): 현재 Cursor가 있는 곳의 List정보를 가져온다.
4) 함수 내용을 구성한 후(예제 참조) 사용은 CListCtrl m_ctrList에서 CListCtrl ---> CMyList로 바꿔 주면 된다. 3.예제 실제로 클래스를 구성하면 다음과 같다.
class CMyList : public COXGridList
{
// Construction
public:
CMyList();
// Attributes
public:
CEdit m_ctrEdit;
// Operations
public:
void GetSubItemFrompt(Cpoint point, int &nItem,int&nSubItem,CRect&rect);
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CMyList)
//}}AFX_VIRTUAL
//Implementation
public:
virtual~CMyList();
//Generatedmessagemapfunctions
protected:
//{{AFX_MSG(CMyList)
afx_msgvoidOnLButtonDown(UINTnFlags,Cpointpoint);
//}}AFX_MSG
DECLARE_MESSAGE_MAp()
};
CMyList::CMyList()
{
}
CMyList::~CMyList()
{
}
BEGIN_MESSAGE_MAp(CMyList,COXGridList)
//{{AFX_MSG_MAp(CMyList)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAp
END_MESSAGE_MAp()
/////////////////////////////////////////////////////////////////////////////
//CMyListmessagehandlers
voidCMyList::OnLButtonDown(UINTnFlags,Cpointpoint)
{
intnItem,nSubItem;
CRectrcClient;
//현재 point의 영역 정보를 가져온다.
GetSubItemFrompt(point, nItem, nSubItem, rcClient);
// 두번째 SubItem일(두번째 Column) 경우에만 나타나게 함.
if (nSubItem == 1)
{
if (m_ctrTimeEdit.m_hWnd == NULL)
{
// Mask Edit Control 생성
m_ctrEdit.Create
(WS_CHILD|WS_VISIBLE|WS_TABSTOp|WS_BORDER|WS_HSCROLL,
CRect(0, 0, 30, 10), this, 1);
m_ctrEdit.MoveWindow(rcClient);
m_ctrEdit.ShowWindow(SW_SHOW);
}
else
{
m_ctrTimeEdit.MoveWindow(rcClient);
m_ctrTimeEdit.ShowWindow(SW_SHOW);
}
}
else
{
if (m_ctrTimeEdit.m_hWnd != NULL)
{
m_ctrTimeEdit.ShowWindow(SW_HIDE);
}
}
CListCtrl::OnLButtonDown(nFlags, point);
}
void CMyList::GetSubItemFrompt(Cpoint point, int &nItem, int &nSubItem, CRect &rect)
{
LVHITTESTINFO lvhti;
// Clear the subitem text the user clicked on.
lvhti.pt = point;
SubItemHitTest(&lvhti);
nItem = lvhti.iItem;
nSubItem = lvhti.iSubItem;
GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rect);
}
4. 참고 마우스를 더블 클릭하는 순간에 나타나게 하고 싶다면 마우스 더블 클릭 함수에서 구현해 주면 된다. 몇가지 함수만 추가하면 특정 Column에서만 Control이 나타나게 하는 것을 쉽게 구현 할 수 있을 것이다. - 2001.08.06 Smile Seo -
11. List Control 행크기 늘리기
----------------------------------------------------------------------
리스트 콘트롤의 행간 높이를 조절하고자 할때,
원래 윈도우가 날려주는 메세지가 있지만, CListCtrlView 를 이용하는경우 도움이 전혀 안됩니다.
이경우 마지막 방법은 이미지 리스트를 이용하는 것입니다.
CImageList m_image;
....
CListCtrl &m_list=GetListCtrl();
m_image.Create(1,20,ILC_COLORDDB,1,0);
list.SetImageList(&m_image,LVSIL_SMALL);
.......
을 써서 Y 크기를 조절해서 크기를 바꿀 수 있습니다.
12. List Control 에서 시스템 아이콘 사용하기
----------------------------------------------------------------------
CImageList m_ImgList;
HIMAGELIST hSystemSmallImageList;
SHFILEINFO ssfi;
hSystemSmallImageList =
(HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\\"), 0, &ssfi, sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
m_ImgList.Attach(hSystemSmallImageList);
m_listDir.SetImageList(&m_ImgList, LVSIL_SMALL);
// 이부분을 넣지 않으면 여러번 리스트컨트롤이 나타날때 이미지가 사라진다.
HWND hList = m_listDir.GetSafeHwnd();
DWORD dwCurrentStyle=GetWindowLong(hList, GWL_STYLE);
dwCurrentStyle |= LVS_SHAREIMAGELISTS;
SetWindowLong(hList, GWL_STYLE, dwCurrentStyle);
// 나중에 InsertItem으로 아이템 추가시 이미지 번호에 아래 함수를 호출하여 얻은 리턴값을 사용한다.
int CSystemListCtrl::GetIconIndex(const CString& csFileName) //full path and file name
{
SHFILEINFO sfi;
SHGetFileInfo(
(LPCTSTR)csFileName,
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON );
return sfi.iIcon;
}