MFC 총결산 의 CListCtrl 용법 및 기교 (二)

다음 1 편: MFC 총결산 의 CListCtrl 용법 및 기교 (一)http://blog.csdn.net/zwgdft/article/details/7560592
        본 고 는 표 두 를 드래그 하 는 것 을 금지 하고 첫 번 째 열 을 가운데 로 표시 하 며 줄 높이 와 글꼴 설정, 가상 목록 기술, 표 두 를 클릭 할 때 분류, 위로 이동 과 아래로 이동, 동적 크기 조정 문제, 반 짝 임 문 제 를 피한다.
 6. 시계 머리 끌 기 금지       무 거 운 짐
OnNotify 메시지 응답 함수, 두 메시지 알림 코드 차단:
HDN_BEGINTRACKW 와...
HDN_DIVIDERDBLCLICKW。예 는 다음 과 같다.
BOOL CXXXX::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO: Add your specialized code here and/or call the base class
	//         ,      List  
	NMHEADER* pNMHeader = (NMHEADER*)lParam;
	if(((pNMHeader->hdr.code == HDN_BEGINTRACKW) | 
             (pNMHeader->hdr.code == HDN_DIVIDERDBLCLICKW)))
	{
		*pResult = TRUE;
		return TRUE;
	}

	return CDialog::OnNotify(wParam, lParam, pResult);
}

 7. 첫 번 째 열 을 가운데 로 표시 합 니 다.        열 을 삽입 할 때 우 리 는 통과 할 수 있다.
인자 nFormat 은 텍스트 의 가운데 표 시 를 설정 하지만 이 설정 은 첫 번 째 열 에 작용 하지 않 습 니 다.이 때 우 리 는 우리 의 내용 을 두 번 째 열 에서 부터 삽입 하 는 것 을 고려 할 수 있다.첫 번 째 열 을 삽입 한 다음 에 첫 번 째 열 을 삭제 하면 원래 의 두 번 째 열 이 첫 번 째 열 이 된다.
 8. 줄 높이 와 글꼴 설정        CListCtrl 의 줄 높이 를 설정 합 니 다. 함수 인터페이스 가 없습니다. 자체 그림 을 통 해 이 루어 질 수 있 지만 귀 찮 습 니 다.비교적 간단 한 방법 은 빈 그림 을 사용 하여 줄 을 지탱 하여 높이 를 변화 시 키 는 것 이다.예 는 다음 과 같다.
CImageList m_image;
m_image.Create(1,24,ILC_COLOR32,1,0);
m_listInfo.SetImageList(&m_image, LVSIL_SMALL);
        글꼴 설정 에 대해 서 는 사용 할 수 있 습 니 다.
SetFont 함수 로 구현 합 니 다.CListView 의 글꼴 을 수정 하 는 것 을 예 로 들 면 OnInitialUpdate 함수 에 열 을 삽입 하기 전에 SetFontSelf 함 수 를 호출 합 니 다.먼저 글꼴 을 만 든 다음 SetFont 을 호출 하여 설정 합 니 다.주의해 야 할 것 은 종료 할 때 만 든 글꼴 을 삭제 하고 메모리 유출 을 피해 야 한 다 는 것 이다.
//       
void CMyListView::SetFontSelf(int nHeight, LPCTSTR lpszFacename)
{
	//       
	if(m_font != NULL)
		delete m_font;
	m_font = new CFont;
	//    
	m_font->CreateFont(
		nHeight,                   // nHeight
		0,                         // nWidth
		0,                         // nEscapement
		0,                         // nOrientation
		FW_NORMAL,                 // nWeight
		FALSE,                     // bItalic
		FALSE,                     // bUnderline
		0,                         // cStrikeOut
		ANSI_CHARSET,              // nCharSet
		OUT_DEFAULT_PRECIS,        // nOutPrecision
		CLIP_DEFAULT_PRECIS,       // nClipPrecision
		DEFAULT_QUALITY,           // nQuality
		DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
		lpszFacename);             // lpszFacename

	//    
	CListCtrl &theCtrl = GetListCtrl();		//     ,    
	theCtrl.SetFont(m_font, TRUE);
}

 9. 가상 목록 기술        링크 를 주 고 비교적 상세 하 게 소개 합 니 다.http://hi.baidu.com/qi_xian/blog/item/929b04ce27d02c0592457ef8.html
       데이터 양 이 많 을 때 InsertItem 을 사용 하여 데 이 터 를 삽입 하 는 과정 은 매우 길다.이때 우 리 는 이 문 제 를 해결 하 는 두 가지 방법 이 있다. 하 나 는 CListCtrl 의 가상 목록 기술 을 사용 하 는 것 이 고, 다른 하 나 는 페이지 별로 표시 하 는 방법 이다.가상 목록 기술 에 대해 상기 링크 중의 글 은 매우 상세 하 게 말 했다. 나 는 비교적 간단 한 방법 을 사용 한 적 이 있 는데 나중에 페이지 를 나 누 는 방법 으로 바 꾸 었 다.
       가상 목록 기술 을 사용 하려 면 세 가지 가 있 습 니 다.
① 가상 기술 을 사용 할 때 CListCtrl 컨트롤 의 Owner Data 속성 을 ture 로 설정 해 야 한다.
② 가상 목록 에 요 소 를 추가 할 때 InserItem 함 수 를 사용 하지 않 고 SetItemCount 를 호출 하여 데이터 총 개 수 를 설정 한 다음 시스템 에서 서로 다른 메 시 지 를 만들어 해당 하 는 메시지 응답 함수 에 삽입 작업 을 완료 합 니 다.
③ 가상 목록 이 부모 창 에 보 내 는 메 시 지 는 세 가지 가 있다. (1) 데이터 가 필요 할 때 LVN 을 보낸다.GETDISPINFO 메시지;(2) 사용자 가 특정한 요 소 를 찾 으 려 고 할 때 LVN 을 보낸다.ODFINDITEM 메시지;⑶ 버퍼 데이터 가 필요 할 때 전송 LVN_ODCACHEHINT 소식.   
        우리 가 LVN 을 사용 할 때GETDISPINFO 의 메시지 처리 함수 가 요 소 를 삽입 할 때 목록 에서 요청 한 데이터 (예 를 들 어 LVIF TEXT, LVIF IMAGE 등) 를 먼저 확인 한 다음 다른 하위 항목 을 삽입 해 야 합 니 다.예 는 다음 과 같다.
void CDataAnalysis::OnLvnGetdispinfoAnalysisList(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
	// TODO: Add your control notification handler code here
	LV_ITEM* pItem= &(pDispInfo)->item;
	int iItemIndex= pItem->iItem;
	size_t converted = 0;
	wchar_t wStr[30];            //Unicode   
	if (pItem->mask & LVIF_TEXT) //        
	{
		switch(pItem->iSubItem)
		{
		case 0: //        ,xxxxx        
			mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
			lstrcpy(pItem->pszText,wStr);
			break;
		case 1: //    1
			mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
			lstrcpy(pItem->pszText,wStr);
			break;
		case 2: //    2
			mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
			lstrcpy(pItem->pszText,wStr);
			break;
		case 3:	//    3
			lstrcpy(pItem->pszText,xxxxxx);
			break;
		}
	}

	*pResult = 0;
}

 10. 표 머리 클릭 시 분류 정렬         시스템 통과 전송
LVM_SORTITEMS 메시지 로 분류 문 제 를 처리 합 니 다. 이 메시지 의 처리 함수 에서 하 나 를 호출 해 야 합 니 다.
반전 함수, 이 반전 함 수 는 우리 가 디자인 하여 서로 다른 분류 방법 을 완성 해 야 합 니 다.리 셋 함수 원형 은 다음 과 같 습 니 다.
                      int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
          상기 반전 함수 에 대해 다음 과 같은 몇 가지 점 을 알 아야 합 니 다.
① 매개 변수 인 lparam 1 과 lparam 2 는 각각 CListCtrl 의 두 줄 데이터 로 비교 대상 이다.CListCtrl 의 구성원 함수 SetItemData 를 통 해 이 함수 의 원형 을 설정 합 니 다.
                     int SetItemData(int nIndex,  DWORD_PTR dwItemData )
첫 번 째 매개 변 수 는 줄 번호 이 고 두 번 째 매개 변 수 는 이 줄 에 대응 하 는 매개 변 수 를 가리킨다.인자 dwItemData 는 보통 한 줄 의 매개 변수의 배열 로 설정 합 니 다. 예 를 들 어 pData [2] [2] = {1, 3}, {2, 3}};매번 pData [i] 를 dwItemData 로 사용 합 니 다.
② 매개 변수 lParamSort 에 대해 서 는 열 항목, 즉 몇 번 째 열 을 가리 키 는 데 사 용 됩 니 다.이 매개 변 수 는 리 셋 함수 와 함께 CListCtrl 의 구성원 함수 SortItems 를 통 해 설정 되 며, 함수 원형 은 다음 과 같 습 니 다.
                    BOOL SortItems( PFNLVCOMPARE pfnCompare,DWORD_PTR dwData )
매개 변수 pfn Compare 는 리 턴 함수 입구 주소 이 고 매개 변수 dwData 는 열 항목 입 니 다.
③ SetItemData 는 데 이 터 를 처음 삽입 할 때 호출 하여 설정 하고, SortItems 는 목록 헤드 를 클릭 할 때 응답 하 는 메시지 처리 함수 에서 설정 합 니 다.
예 는 다음 과 같다.
//         
BOOL CDataAnalysis::InitListCtl()
{
	//    ,      ,     
	//   
	for(int i=0; i<LineNum; i++)
	{
		//  char*   wchar_t*
		mbstowcs_s(&converted, wStr, 30, m_analysis[i].Date, _TRUNCATE);
		m_listAnalysis.InsertItem(i, wStr);								//  
		mbstowcs_s(&converted, wStr, 30, m_analysis[i].Time, _TRUNCATE);
		m_listAnalysis.SetItemText(i, 1, wStr);							//  
		mbstowcs_s(&converted, wStr, 30, m_analysis[i].ID, _TRUNCATE);
		m_listAnalysis.SetItemText(i, 2, wStr);							//ID
		m_listAnalysis.SetItemText(i, 3, m_analysis[i].lpszEvent);		//  

		//         
		m_listAnalysis.SetItemData(i, (LPARAM)(m_analysis+i));
	}

	return TRUE;
}
void CDataAnalysis::OnHdnItemclickAnalysisList(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
	// TODO: Add your control notification handler code here

	//              
	m_listAnalysis.SortItems(SortFunc, phdr->iItem);

	*pResult = 0;
}
//       
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	int result;		//   

	//     ,    
	ANALYSISFORMAT* pAnalysis1 = (ANALYSISFORMAT*)lParam1;
	ANALYSISFORMAT* pAnalysis2 = (ANALYSISFORMAT*)lParam2;

	//  
	switch(lParamSort)
	{
	case 0:		//  
		result = strcmp(pAnalysis1->Date, pAnalysis2->Date);
		break;
	case 1:		//  
		result = strcmp(pAnalysis1->Time, pAnalysis2->Time);
		break;
	case 2:		//ID
		result = strcmp(pAnalysis1->ID, pAnalysis2->ID);
		break;
	case 3:		//  
		result = wcscmp(pAnalysis1->lpszEvent, pAnalysis2->lpszEvent);
		break;
	default:
		break;
	}

	return result;
}

 11. 위 와 아래로 이동
        표 항목 의 내용 을 위로 이동 하거나 아래로 이동 해 야 할 때 도 있 습 니 다. 위로 이동 하 는 방법 을 제시 하고 아래로 이동 하 는 방법 은 유사 합 니 다.
① 제2 절 에서 말 한 내용 을 이용 하여 줄 번호 n Item 을 얻 고 줄 번호 가 줄 의 첫 번 째 인지 여 부 를 판단 하 며 줄 의 첫 번 째 가 아니면 ② 에 들어간다.
② nItem 줄 의 모든 하위 항목 내용 가 져 오기;
③ nItem 줄 을 삭제 하고 nItem - 1 의 위치 에 원래 의 nItem 줄 의 내용 을 다시 삽입 합 니 다.
④ nItem - 1 의 위 치 를 밝 게 표시
예 는 다음 과 같다.
/*************************    **************************/
void CStudyTestDlg::OnPageup() 
{
    if (nItem == 0)
    {
        MessageBox("          !");
        return;
    }

    //     
    CString temp[4];
	int i;
    for(i=0;i<4;i++)
        temp[i] = m_ListCtrl.GetItemText(nItem, i);

    //   
    m_ListCtrl.DeleteItem(nItem);

    //  nItem-1     
    for (i=0; i<4; i++)
        m_ListCtrl.SetItemText(nItem-1,i,temp[i]);

    //    
    UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
    m_ListCtrl.SetItemState(--nItem, flag, flag);
}

/*************************    **************************/
void CStudyTestDlg::OnPagedown() 
{
    if (nItem == m_ListCtrl.GetItemCount()-1)
    {
        MessageBox("           !");
        return;
    }

    //     
    CString temp[4];
	int i;
    for (i=0; i<4; i++)
        temp[i] = m_ListCtrl.GetItemText(nItem, i);

    //   
    m_ListCtrl.DeleteItem(nItem);

    //  nItem+1     
    for (i=0; i<4; i++)
        m_ListCtrl.SetItemText(nItem+1, i,temp[i]);

    //    
    UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
    m_ListCtrl.SetItemState(++nItem, flag, flag);
}

 12. 반 짝 임 문 제 를 피한다.           이 문 제 는 나의 앞의 박문 에서 언급 되 었 다.
  http://blog.csdn.net/zwgdft/article/details/7394318
 
13. 동적 크기 조정
        소프트웨어 가 실 행 될 때의 컴퓨터 화면 크기 가 불확실 하기 때문에 화면 크기 에 따라 CListCtrl 컨트롤 의 크기 를 동적 으로 설정 해 야 할 때 도 있 습 니 다.동적 크기 의 설정 을 할 때 높이 와 너비 설정 을 영역 제한 을 초과 하지 않도록 주의해 야 합 니 다. 그렇지 않 으 면 스크롤 바 가 없어 서 일부 내용 을 볼 수 없습니다.내 가 만난 예 를 들 어 그 상황 은 12 절 에서 언급 한 그 박문 에서 말 한 바 와 같다. View 를 세 개의 창 으로 나 누고 왼쪽 상단 View 에 CProperty Sheet 이 있 는데 그 위 에 CProperty Page 가 몇 개 있 고 각 속성 페이지 에 CListCtrl 이 있어 서 사용자 가 정 보 를 볼 수 있다.이 때 설정 해 야 할 CListCtrl 의 크기 는 다음 과 같 습 니 다.
                                              너비 = 왼쪽 상단 보기 너비
                                              높이 = 왼쪽 상단 View 높이 - 속성 페이지 의 Tab 항목 높이
MoveWindow 함 수 를 호출 하여 설정 하면 됩 니 다.
* * * * * * * * * * * * * * * * * * * * * * *

좋은 웹페이지 즐겨찾기