안녕하세요

프로그램 과정에서 막혔던 문제들에 대한 해결책 정리


페이지 목록

2014년 11월 21일 금요일

[MFC] Listctrl Item 간 위치 변경

첨부화일을 참고하세요....... void MoveTo(CListCtrl* pList, int index1, int index2) // index1 < index2 이고.. { // index1의 item을 index2+1로 이동후 index1의 item은 지움.. if(index1==index2) return; int idx1 = index1; int idx2 = index2; if(index1 > index2) { idx1 = index2; idx2 = index1; } int nCount = pList->GetHeaderCtrl()->GetItemCount(); CString str; str = pList->GetItemText(idx1,0); pList->InsertItem(idx2+1, str); for(int k=1; kGetItemText(idx1,k); pList->SetItemText(idx2+1, k,str); } pList->DeleteItem(idx1); } void CABC11Dlg::OnButtonMoveup() { // TODO: Add your control notification handler code here CListCtrl *pList = &m_list; ///////////// POSITION pos = pList->GetFirstSelectedItemPosition(); if(pos == NULL) return; int PreIndex=-1; int Index; while(pos) { Index = pList->GetNextSelectedItem(pos); if( PreIndex+1 != Index) { MoveTo(pList, Index, Index-1); pList->SetItemState(Index-1, LVIS_SELECTED, LVIS_SELECTED); PreIndex = Index-1; } else PreIndex = Index; } } void CABC11Dlg::OnButtonMovedown() { // TODO: Add your control notification handler code here CListCtrl *pList = &m_list; //////// POSITION pos = pList->GetFirstSelectedItemPosition(); if(pos == NULL) return; vector IndexData; while(pos) { int Index = pList->GetNextSelectedItem(pos); IndexData.push_back(Index); } int size = IndexData.size()-1; int PreIndex=pList->GetItemCount(); int Index; for( ;0<=size ; --size) { Index = IndexData[size]; if(Index+1 != PreIndex) { MoveTo(pList, Index, Index+1); pList->SetItemState(Index+1, LVIS_SELECTED, LVIS_SELECTED); PreIndex = Index+1; } else PreIndex = Index; } } Vㅔ리 굳 출처: http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=50&MaeulNo=20&no=874306&ref=874281

[MFC] listctrl SetItemStatus 를 이용한 다중 선택

결국 for문인가.. int i = 0; for(i = 0; i<_lcDataReport.GetItemCount(); i++){ _lcDataReport.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); } 출처: http://adnoctum.tistory.com/176

[MFC] ListCtrl 기본 예제

List Control List control은 아이콘, 작은 아이콘, 간단히, 보고서의 네 가지 형태로 데이터를 보여주는 컨트롤입니다. 이중 보고서 모드가 List control에 설정된 데이터를 가장 자세히 보여주는 모드입니다. 따라서 List control에 데이터를 설정할 때는 이 모드를 기준으로 하면 됩니다. 보고서 모드에는 하나의 아이템에 대해 가로줄로 여러 가지 데이터를 보여줄 수 있는데, 이러한 가루 줄을 각각 컬럼이라고 하고, 컬럼 맨 위에 각 컬럼의 제목을 표시하는 줄을 컬럼 헤더라고 합니다. |구현하고자 하는 기능| List control을 포함하는 대화상자를 만들어 보도록 합니다. 선택항목 삭제, 위로, 아래로 등을 이용해 위치를 바꾸고 삭제하는 프로그램을 만들어 보겠습니다. |App Wizard| 스켈레톤 코드를 생성한다. 프로젝트 생성 다이얼로그 형식의 프로젝트를 생성합니다. Project type Project name MFC AppWizard (exe) ListControl Step. 1 Dialog based |App Setup| 사용자 인터페이스 요소들을 시작적으로 디자인한다. 대화상자 리소스 디자인 위와 같이 대화상자에 List control을 올려놓고, List control의 속성을 설정합니다. List control의 속성을 아래에 정리 해 놓았습니다. 속성 정리 속성 의미 View Icon, Small Icon, List, Report 중 하나를 선택할 수 있습니다. Allign Left, Right 중 하나를 선택할 수 있으며, 아이콘 정렬의 기준을 설정합니다. Sort None, Ascending, Descending 중 하나를 선택할 수 있으며, 정렬 방법을 설정합니다. Single selection 오직 하나의 항목만 선택할 수 있도록 합니다. Auto arrange Icon 또는 Small Icon에서 아이콘들을 자동으로 정렬되도록 합니다. No label wrap 아이콘과 함께 쓰이는 텍스트가 한 줄로 쓰여지도록 합니다. Edit labels 텍스트를 편집할 수 있게 합니다. 이 스타일을 선택하면 텍스트 편집이 끝나면 LVN_ENDLABELEDIT 이벤트가 발생합니다. No column header Report에서 컬럼 헤더를 표시하지 않도록 합니다. No sort header 컬럼 헤더가 표시되더라도 동작하지 않도록 합니다. 보통 컬럼 헤더는 정렬 모드를 바꾸기 위해 사용됩니다. 속성 설정 컨트롤 ID Caption 기타 List control IDC_LIST1 [View] 속성 [Report] Push Button1 IDC_BUTTON_UP 위로 Push Button2 IDC_BUTTON_DOWN 아래로 Push Button3 IDC_BUTTON_DELETE 삭제 Push Button4 IDC_BUTTON_PRINT 출력 탭 순서 설정 순서가 중요한 프로그램이 아니어서 순서 지정 없이 진행합니다. |Class Wizard| AppStudio에서 시각적으로 디자인된 요소들을 실제 프로그램 코드와 연결 시킨다. 새로운 클래스를 정의한다. 각 컨트롤들의 메시지 핸들러를 재 정의한다. 컨트롤과 멤버 변수 연결 Class Wizard 의 Member Variables 에서 연결 시킨다. Control Type Member List control Control CListCtrl m_ctrlList CListCtrl의 주요 멤버 함수 List control에 컬럼 및 아이템을 추가 삭제등 한다. 멤버 함수 기능 InsertItem 새로운 항목을 추가 합니다. DeleteItem 지정된 항목을 삭제 합니다. DeleteAllitems 모든 항목들을 삭제 합니다. GetItemCount 항목의 개수를 얻습니다. SetItem GetItem 각각의 아이템의 정보를 설정합니다. 각각의 아이템의 정보를 얻습니다. SetItemText GetItemText 각각의 아이템의 텍스트를 설정합니다. 각각의 아이템의 텍스트를 얻습니다. InsertColumn 새로운 컬럼을 추가 합니다. DeleteColumn 지정된 컬럼을 삭제 합니다. SetImageList GetImageList 각각의 아이콘으로 사용될 이미지 리스트를 설정합니다. 각각의 아이콘으로 사용될 이미지 리스트를 얻습니다. List Control이 발생시키는 이벤트 List control이 발생시키는 주요 이벤트 이벤트 발생 시기 LVN_COLUMNCLICK 컬럼 헤더가 클릭 되었을 때 LVN_DELETEITEM 항목이 삭제 되었을 때 LVN_DELETEALLITEMS 모든 항목이 삭제 되었을 때 LVN_INSERTITEM 새로운 항목이 추가 되었을 때 LVN_ITEMCHANGED 선택된 항목이 다른 항목으로 변경 되었을 때 LVN_KEYDOWN 키보드가 눌렸을 때 메시지 핸들러 재 정의 각각의 버튼들의 메시지 핸들러를 재 정의 합니다. void CListControlDlg::OnButtonUp() { } void CListControlDlg::OnButtonDown() { } void CListControlDlg::OnButtonDelete() { } void CListControlDlg::OnButtonPrint() { } |코딩| 컨트롤 초기화 //컬럼을 생성합니다. BOOL CListControlDlg::OnInitDialog() { CRect rect; m_ctrlList.GetClientRect(&rect); m_ctrlList.InsertColumn(0, _T("이름"), LVCFMT_LEFT, 100); m_ctrlList.InsertColumn(1, _T("나이"), LVCFMT_RIGHT, 100); m_ctrlList.InsertColumn(2, _T("성별"), LVCFMT_CENTER, 100); m_ctrlList.InsertColumn(3, _T("전화"), LVCFMT_LEFT, rect.Width()-220); return TRUE; // return TRUE unless you set the focus to a control } 아이템 추가 //각 컬럼에 아이템을 추가한다. BOOL CListControlDlg::OnInitDialog() { CString str; for(int i=0; i<7; i++) { m_ctrlList.InsertItem(i, strName[i], rand()%5); str.Format("%d",rand()%100); m_ctrlList.SetItemText(i, 1, str); if(rand()%2 == 0) str="남자"; else str = "여자"; m_ctrlList.SetItemText(i,2,str); str.Format("%03d - %04d", rand()%1000, rand()%10000); m_ctrlList.SetItemText(i,3,str); } return TRUE; } 선택 항목 위로 //아이템을 선택하고 위로 버튼을 눌렀을 때를 처리한다. void CListControlDlg::OnButtonUp() { POSITION pos; while(pos = m_ctrlList.GetFirstSelectedItemPosition()) { int nSelItem = m_ctrlList.GetNextSelectedItem(pos); CString strTemp; strTemp = m_ctrlList.GetItemText(nSelItem-1, 0); if(!strTemp.IsEmpty()) { CString strName, strAge, strSex, strTel; strName = m_ctrlList.GetItemText(nSelItem,0); strAge = m_ctrlList.GetItemText(nSelItem,1); strSex = m_ctrlList.GetItemText(nSelItem,2); strTel = m_ctrlList.GetItemText(nSelItem,3); m_ctrlList.DeleteItem(nSelItem); m_ctrlList.InsertItem(nSelItem-1, strName, 0); m_ctrlList.SetItemText(nSelItem-1, 1, strAge); m_ctrlList.SetItemText(nSelItem-1, 2, strSex); m_ctrlList.SetItemText(nSelItem-1, 3, strTel); } else break; } } 선택 항목 아래로 //아이템을 선택하고 아래로 버튼을 눌렀을 때를 처리한다. void CListControlDlg::OnButtonDown() { POSITION pos; while(pos = m_ctrlList.GetFirstSelectedItemPosition()) { int nSelItem = m_ctrlList.GetNextSelectedItem(pos); CString strTemp; strTemp = m_ctrlList.GetItemText(nSelItem+1, 0); if(!strTemp.IsEmpty()) { CString strName, strAge, strSex, strTel; strName = m_ctrlList.GetItemText(nSelItem,0); strAge = m_ctrlList.GetItemText(nSelItem,1); strSex = m_ctrlList.GetItemText(nSelItem,2); strTel = m_ctrlList.GetItemText(nSelItem,3); m_ctrlList.DeleteItem(nSelItem); m_ctrlList.InsertItem(nSelItem+1, strName, 0); m_ctrlList.SetItemText(nSelItem+1, 1, strAge); m_ctrlList.SetItemText(nSelItem+1, 2, strSex); m_ctrlList.SetItemText(nSelItem+1, 3, strTel); } else break; } } 선택 항목 삭제 //아이템을 선택하고 삭제 버튼을 눌렀을 때를 처리한다. // 다중선택시 void GetIndex() { int nItemCount = m_ctrlList.GetSelectedCount(); POSITION pos = m_ctrlList.GetFirstSelectedItemPosition(); for (int i = 0; i < nItemCount; i++) { int nIndex = m_ctrlList.GetNextSelectedItem(pos); } } // 단일 선택 int GetIndex() { int nSelectedItem = m_ctrlList.GetNextItem( -1, LVNI_SELECTED ); CString strKey = m_ctrlList.GetItemText(nSelectedItem, 0); if ( strKey == "") { return -1; } return nSeletedItem; } // 다중 선택한거 골라서 삭제 int nItem; POSITION pos; pos = m_ctrlList.GetFirstSelectedItemPosition(); while (pos != NULL) { nItem = m_ctrlList.GetNextSelectedItem(pos); m_ctrlList.DeleteItem(nItem); pos = m_ctrlList.GetFirstSelectedItemPosition(); } 항목 삭제 //출력 버튼을 눌렀을 때를 처리한다. void CListControlDlg::OnButtonPrint() { int nSelItem = 0; CString strPrint, strTemp; while(1) { strTemp = m_ctrlList.GetItemText(nSelItem,0); if(strTemp.IsEmpty()) break; strTemp += " "; strTemp += m_ctrlList.GetItemText(nSelItem,1); strTemp += " "; strTemp += m_ctrlList.GetItemText(nSelItem,2); strTemp += " "; strTemp += m_ctrlList.GetItemText(nSelItem,3); strTemp += "\n"; strPrint += strTemp; nSelItem ++; } AfxMessageBox(strPrint); } 문자열 이용삭제 일반적으로 리스트 컨트롤에서 아이템을 지우려면 DeleteItem 이라는 함수를 사용합니다.하지만 이 함수가 지우고자하는 아이템의 인덱스를 요구하기 때문에 님이 사용하고자 하는 직접적인 형태는 아닌것 같네요.. 따라서 아이템 스트링을 가지고 삭제하고 싶다면 FindItem이라는 함수를 사용해서 먼저 해당 아이템의 인덱스를 얻은 후, DeleteItem을 사용하면 될것 같습니다. 해당 코드를 함수로 구성해 보면 다음과 같습니다... void 해당클래스::DeleteItemWithString(const char *parm_name) { LVFINDINFO find_item; find_item.flags = LVFI_STRING; find_item.psz = parm_name; int index = 리스트컨트롤.FindItem(&find_item); if(-1 != index) 리스트컨트롤.DeleteItem(index); } 이렇게 하면 리스트 컨트롤에서 지우고자 하는 아이템의 이름이 "홍길동" 이라면 다음과 같이 호출하면 됩니다. DeleteItemWithString("홍길동"); 체크 선택, 해제 m_ctrlList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES ); //출력 버튼을 눌렀을 때를 처리한다. void CListControlDlg::Secheck(BOOL _bisCheck) { int nCntlist = m_ctrlList.GetIemcount(); for(int i = 0; i < nCntlist; i++) { m_ctrlList.SetCheck(i, _bisCheck); } } 아이템 선택 // 1개 이상 선택 및 확인 POSITION pos = m_list.GetFirstSelectedItemPosition(); if (pos == NULL) { AfxMessageBox(_T("No items were selected!\n")); } else { while (pos) { int nItem = m_list.GetNextSelectedItem(pos); CString temp = m_list.GetItemText(nItem,0); } } temp.Format(_T("%s seq가 선택됨"),temp); AfxMessageBox(temp); 아이템 선택리스트 컨트롤 사용시 원하는 라인에 포커스 설정 및 라인 이동 Ex) CListCtrl m_list; m_list.SetItemState( -1, 0, LVIS_SELECTED|LVIS_FOCUSED ); m_list.SetItemState(nRow, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); m_list.EnsureVisible(nRow, FALSE); m_list.SetFocus(); // 깜박임 없이 마지막 라인으로 자동 스트롤 된다. m_list.SendMessage(WM_VSCROLL,SB_BOTTOM,NULL); 설명) SetItemState(옵션1, 옵션2, 옵션3) 옵션1 : 선택라인 옵션2 : 선택한 상태로 리스트를 출력(옵션3에서 나열된 옵션에서만 선택 가능) 옵션3 : 옵션2에서 선택할수 있는 옵션 나열 // 해당 라인으로 스크롤 이동 EnsureVisible // 해당 라인으로 포커스 설정 SetFocus 선택은 - SetItemState( nCount, LVIS_SELECTED, LVIS_SELECTED ); 비선택은 - SetItemState( nCount, 0, LVIS_SELECTED ); LVIS_SELECTED 는 선택 LVIS_FOCUSED 는 포커스.. - 키보드 로 이동한다거 할때 이넘을 기준으로 움직이는거임.. ps. 마우스로 클릭할경우에는 컨트롤키를 누르지 않은 이상 하나만 선택되고, 포커스가 맞춰지는데 위의 코드로 선택만 설정해주게 되면 기존에 선택된 아이템이 있을경우 추가로 선택이 되기때문에 기존에 선택된것들은 지우든지 한다. 물론 LVS_SINGLESEL 스타일이 적용되어있다면 관계없다. 쵝오로 잘 정리되어 있음 출처: http://izen8.tistory.com/696

[MFC] ListCtrl Row 순서 변경

최초 시도 시에는 InsertItem으로 넣은 후에 기존 Row를 삭제하는 방법을 선택 2,3번 변경시 3번을 2번 위치로 변경 index1 = 2; CString str = listctrl.GetItemText(index1,0); index2 = 3; listctrl.InsertItem(index2+1, str); listctrl.DeleteItem(index1); 하지만 위와 같이 동작할 때 이상하게 InsertItem의 위치가 틀어짐 그래서 다른 방법을 생각해 냄 일단 2번,3번 열의 데이터를 각각 저장 2번 열 데이터 저장 (CString str1) 3번 열 데이터 저장 (CString str2) 그리고 SetItemText로 데이터 변경 listctrl.SetItemText(index1,str2); listctrl.SetItemText(index2,str1); 미션 컴플리트