GSI

ListCtrl의 LPARAM의 포인터 변수 지우는 방법!!

가끔 생각해 보면 참 바보 같다는 생각이 든다.
기존의 작업 스탈을 보면 ListCtrl의 하나하나의 열에 해당 포인터 변수를 추가해서
사용하게 되는 경우가 많은데,
이때 포인터 변수이기 때문에 메모리를 소거해야 하는 부담감에 휩싸이게 된다.
하지만 난 이제까지 몰랐던것이다.. -.-;

ListCtrl의 흐름 자체를 말이다.

삭제를 할때 나는 해당 아이템을 DeleteItem(i); 이런식으로 하기 전에 사용자 데이터를
지워주어야 하는줄 알았다.
하지만 이 작업은 중간 중간 수정을 하거나 모두 지우거나 추가 하면서
몇가지 부수적인 작업패턴을 부적절하게 발생 시키게 된다.

하지만 이것은 아래의 함수에서 DeleteItem(), DeleteAllItem()을 할때 매번 호출 되는
오버라이드 함수가 있었다는 사실을 알게 되었다.

즉,
ON_NOTIFY(LVN_DELETEITEM, IDC_LIST_IMAGELIST, OnLvnDeleteitemListImagelist)
이 함수를 오버라이딩 해서 사용하게 되면 해당 아이템이 지워질때
이 함수가 호출 되게 된다. 다시 말해서 이 함수 안에서 해당 하는 아이템만
지워 주면 다른건 신경 쓰지 않아도 되는 것이다.


그렇다면 모두 지우는 과정에서는 어떻게 되는가 하고 모르는 분들이라면 질문을 할텐데요.
위의 함수가 그 개수만큼 호출 됩니다.

그래서 위의 함수에서 해당 데이터를 지워 주기만 하면 된다는 것이죠.
아래 처름요.

void CDlgProgrammingPage::OnLvnDeleteitemListImagelist(NMHDR *pNMHDR, LRESULT *pResult)
{
 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
 
 // 메모리 삭제하기
 CString* pStr = (CString*)m_ImageList.GetItemData(pNMLV->iItem);  //<-- 이 부분은 작업자가 포함시킨 포인터 변수(가정)
 SAFE_DELETE(pStr);

 *pResult = 0;
}

Posted by gsi
:

ListCtrl의 한줄로 선택되도록 처리 하는 방법 + 그리드 라인을 같이 그려주는 코드
생성시에 한번 호출해서 설정해 주면 됩니다.


m_listPortSequencePerAddress.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);

컬럼 설정하는 방법

// 리스트 컬럼 추가함수
void CDlgSequencePage::AddColumn()
{
 //컬럼 채우기
 int m_nColWidths[] = { 90, 60}; // sixty-fourths
 TCHAR * lpszHeaders[] = {
        _T("Port/Sequence"),
        _T("Address"),
        NULL };

 int i;
 LV_COLUMN lvcolumn;
 memset(&lvcolumn, 0, sizeof(lvcolumn));

 // add columns
 for (i = 0; ; i++) {
  if (lpszHeaders[i] == NULL)
   break;

  lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  lvcolumn.fmt = LVCFMT_LEFT;
  lvcolumn.pszText = lpszHeaders[i];
  lvcolumn.iSubItem = i;
  lvcolumn.cx = m_nColWidths[i];
  m_listPortSequencePerAddress.InsertColumn(i, &lvcolumn);
 }
}

데이터 추가시
Lparam도 같이 추가할 때

void CDlgSequencePage::AddData(CString portName, int Address, lpFixtureElement pFixEle)
{
 CString strText;
 int index = 0;
 index = m_listPortSequencePerAddress.GetItemCount();

 // Insert the item, select every other item.
 strText = portName;
 int id = m_listPortSequencePerAddress.InsertItem(LVIF_TEXT|LVIF_PARAM, index, strText, 0, 0, 0, (LPARAM)pFixEle);

 // Insert 10 items in the list view control.
 strText.Format(TEXT("%d"), Address);
 m_listPortSequencePerAddress.SetItemText(index, 1, strText);
}

해당 Row를 선택시에 Lparam의 값을 가져와서 처리 하는 방법

void CDlgSequencePage::OnLvnItemchangedSequenceListInfo(NMHDR *pNMHDR, LRESULT *pResult)
{
 LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

 static int oldSelectItemLine = -1;

 // 해당 아이템 번호가 항상 3번 호출되고 다른 번호가 들어오기 때문에
 // 여기서 걸러 준다.
 if(pNMLV->iItem != oldSelectItemLine) {
  oldSelectItemLine = pNMLV->iItem;

  // 리스트 컨트롤에 저장된 포인터 정보를 사용해서
  // 선택정보를 변경하자.
  lpFixtureElement pFixEle = (lpFixtureElement)m_listPortSequencePerAddress.GetItemData(pNMLV->iItem);
  ASSERT(pFixEle);
  FixtureArray::GetInstance().ChangedFixtureElement(pFixEle);

  // PixelMap View 화면을 업데이트 한다.
  g_PixelMapView->Invalidate();
 }

 *pResult = 0;
}


 

Posted by gsi
: