// 컬럼 수는 외부에서 입력한다. 이 함수는 빈번하게 사용하므로 Header_GetItemCount 호출은 낭비.
void __stdcall ListItemSwap(HWND hList, int One, int Two, int iColCount)
{
// 텍스트 제외 속성 교환
LVITEM liOne={0}, liTwo={0};
liOne.mask = liTwo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
liOne.stateMask = liTwo.stateMask = LVIS_CUT | LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
liOne.iSubItem = liTwo.iSubItem = 0;
liOne.iItem = One;
liTwo.iItem = Two;
ListView_GetItem(hList, &liOne);
ListView_GetItem(hList, &liTwo);
liOne.iItem = Two;
liTwo.iItem = One;
ListView_SetItem(hList, &liOne);
ListView_SetItem(hList, &liTwo);
// 텍스트 교환
int i;
TCHAR szTextOne[1024]={0}, szTextTwo[1024]={0};
liOne.mask = liTwo.mask = LVIF_TEXT;
liOne.cchTextMax = liTwo.cchTextMax = sizeof(szTextOne);
liOne.iItem = One;
liTwo.iItem = Two;
liOne.pszText = szTextOne;
liTwo.pszText = szTextTwo;
for(i=0; i<iColCount; i++){
liOne.iSubItem = liTwo.iSubItem = i;
SendMessage(hList, LVM_GETITEMTEXT, One, (LPARAM)&liOne);
SendMessage(hList, LVM_GETITEMTEXT, Two, (LPARAM)&liTwo);
SendMessage(hList, LVM_SETITEMTEXT, Two, (LPARAM)&liOne);
SendMessage(hList, LVM_SETITEMTEXT, One, (LPARAM)&liTwo);
}
/* 참고) 텍스트 교환 매크로 함수 사용시
(함수 실행시마다 LVITEM 변수를 각각 선언하므로 좀 더 느리다.)
int i;
TCHAR szTextOne[1024]={0}, szTextTwo[1024]={0};
for(i=0; i<iColCount; i++){
ListView_GetItemText(hList, One, i, szTextOne, sizeof(szTextOne));
ListView_GetItemText(hList, Two, i, szTextTwo, sizeof(szTextTwo));
ListView_SetItemText(hList, Two, i, szTextOne);
ListView_SetItemText(hList, One, i, szTextTwo);
}*/
}
int __stdcall ListItemUp(HWND hList)
{
int iCount = ListView_GetItemCount(hList);
if(!iCount) return 0;
int iSelCount = ListView_GetSelectedCount(hList);
if(!iSelCount) return 0;
int iColCount=Header_GetItemCount(GetDlgItem(hList,0));
// iPre는 이전 처리항목의 인덱스, 비교해서 불필요한/엉뚱한 이동 방지
int i, iPre=-1, index=-1, iUp, iSwapCount=0;
for(i=0 ; i<iSelCount ; i++){
index = ListView_GetNextItem(hList, index, LVNI_ALL|LVNI_SELECTED);
if(index==0){ // 맨 첫라인인 경우 이동은 불필요하다.
iPre=0;
continue;
}
iUp = index-1; // 이동할 인덱스
if(iUp == iPre){ // 이전 처리항목의 인덱스와 같으면 스왑하면 안된다.
iPre=index;
} else {
ListItemSwap(hList, index, iUp, iColCount);
iPre=iUp;
++iSwapCount;
}
}
return iSwapCount;
}
int __stdcall ListItemFirst(HWND hList)
{
int iCount = ListView_GetItemCount(hList);
if(!iCount) return 0;
int iSelCount = ListView_GetSelectedCount(hList);
if(!iSelCount) return 0;
int iColCount=Header_GetItemCount(GetDlgItem(hList,0));
int i, j, index=-1, iInsertCount=0;
LVITEM li={0};
li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
li.stateMask = LVIS_CUT | LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
li.iSubItem = 0;
for(i=0 ; i<iSelCount ; i++){
index = ListView_GetNextItem(hList, index, LVNI_ALL|LVNI_SELECTED);
if(i == index) continue; // 이동할 필요가 없는 경우
// 속성을 같게하면서 아이템 삽입
li.iItem = index;
ListView_GetItem(hList, &li);
li.iItem = i;
ListView_InsertItem(hList, &li);
// 이제 텍스트 복사
TCHAR szText[1024]={0};
for(j=0; j<iColCount; j++){ // 아이템 삽입해서 한 줄 밀리므로 +1을 해줘야 한다.
ListView_GetItemText(hList, index+1, j, szText, sizeof(szText));
ListView_SetItemText(hList, i, j, szText);
}
++iInsertCount;
// 복사가 끝났으므로 소스행 삭제
ListView_DeleteItem(hList, index+1);
}
return iInsertCount;
}
int __stdcall ListItemDown(HWND hList)
{
int iCount = ListView_GetItemCount(hList);
if(!iCount) return 0;
int iSelCount = ListView_GetSelectedCount(hList);
if(!iSelCount) return 0;
int iColCount=Header_GetItemCount(GetDlgItem(hList,0));
// iPre는 이전 처리항목의 인덱스, 비교해서 불필요한/엉뚱한 이동 방지
int i, iPre=iCount, index=iCount-1, iDown, iSwapCount=0;
for(i=0 ; i<iSelCount ; i++){ // 맨아래 선택항목부터 처리해야 한다.
// 끝라인이 선택된 경우 인덱스는 아래와 같은 식으로 구해야 된다.
if(i==0 && LVIS_SELECTED == ListView_GetItemState(hList, iCount-1, LVIS_SELECTED)){
index=iCount-1;
} else {
index = ListView_GetNextItem(hList, index, LVNI_ALL|LVNI_ABOVE|LVNI_SELECTED);
}
if(index == iCount-1){ // 맨 끝라인인 경우 이동은 불필요하다.
iPre=iCount-1;
continue;
}
iDown = index+1; // 이동할 인덱스
if(iDown == iPre){ // 이전 처리항목의 인덱스와 같으면 스왑하면 안된다.
iPre=index;
} else {
ListItemSwap(hList, index, iDown, iColCount);
iPre=iDown;
++iSwapCount;
}
}
return iSwapCount;
}
int __stdcall ListItemLast(HWND hList)
{
int iCount = ListView_GetItemCount(hList);
if(!iCount) return 0;
int iSelCount = ListView_GetSelectedCount(hList);
if(!iSelCount) return 0;
int iColCount=Header_GetItemCount(GetDlgItem(hList,0));
int i, j, index=iCount-1, iInsertCount=0;
LVITEM li={0};
li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
li.stateMask = LVIS_CUT | LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
li.iSubItem = 0;
for(i=0 ; i<iSelCount ; i++){
// 끝라인이 선택된 경우 인덱스는 아래와 같은 식으로 구해야 된다.
if(i==0 && LVIS_SELECTED == ListView_GetItemState(hList, iCount-1, LVIS_SELECTED)){
index=iCount-1;
} else {
index = ListView_GetNextItem(hList, index, LVNI_ALL|LVNI_ABOVE|LVNI_SELECTED);
}
if(iCount-i-1 == index) continue; // 이동할 필요가 없는 경우
// 속성을 같게하면서 아이템 삽입
li.iItem = index;
ListView_GetItem(hList, &li);
li.iItem = iCount-i;
ListView_InsertItem(hList, &li);
// 이제 텍스트 복사
TCHAR szText[1024]={0};
for(j=0; j<iColCount; j++){
ListView_GetItemText(hList, index, j, szText, sizeof(szText));
ListView_SetItemText(hList, iCount-i, j, szText);
}
++iInsertCount;
// 복사가 끝났으므로 소스행 삭제
ListView_DeleteItem(hList, index);
}
return iInsertCount;
}
// return value is swap count.
int __stdcall ListItemArrange(HWND hList, int iColAxis, BOOL bAscending)
{
int i, j, iItemCount;
iItemCount=ListView_GetItemCount(hList);
if(!iItemCount) return 0;
int iColCount=Header_GetItemCount(GetDlgItem(hList,0));
// 비교할 때마다 ListView_GetItemText는 낭비이므로
// 일괄적으로 해당 열의 문자열을 뽑아 놓는다. 메모리 공간 확보: [1024]크기의 문자열 포인터(배열 포인터)
TCHAR (*apszText)[1024]=(TCHAR(*)[1024])VirtualAlloc(NULL, iItemCount*1024*sizeof(TCHAR), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(apszText==NULL) return 0;
for(i=0 ; i<iItemCount ; i++){
ListView_GetItemText(hList, i, iColAxis, apszText[i], 1024*sizeof(TCHAR));
}
// 선택 정렬
int index, iSwapCount=0;
TCHAR szTemp[1024]={0};
for(i=0 ; i<iItemCount-1 ; i++){
index=i;
for(j=i+1 ; j<iItemCount ; j++){ // 문자열 비교 루프
if(bAscending){ // 오름차순(0,1,2,3~~~ 갈수록 값이 올라간다.)
if(lstrcmpi(apszText[index], apszText[j])>0) index=j;
} else { // 내림차순(10,9,8,7~~~ 갈수록 값이 내려간다.)
if(lstrcmpi(apszText[index], apszText[j])<0) index=j;
}
}
if(index != i){ // 같으면 스왑할 필요 없으므로
ListItemSwap(hList, index, i, iColCount);
++iSwapCount;
// 앞의 문자열 메모리도 맞게 스왑
lstrcpy(szTemp, apszText[index]);
lstrcpy(apszText[index], apszText[i]);
lstrcpy(apszText[i], szTemp);
}
}
VirtualFree(apszText, 0, MEM_RELEASE);
return iSwapCount;
}
'API' 카테고리의 다른 글
리스트뷰(혹은 트리뷰 등등)의 배경에 그림 넣기입니다 (2) | 2009.11.05 |
---|---|
[팁] 일반 윈도우에서 다이얼로그박스의 편리한 키보드 인터페이스 구현하기 (1) | 2009.10.15 |
시스템 정보 알아내기....네이버 지식인 참조 (3) | 2009.10.04 |
윈도우 속성 제거 및 추가 (and or not 연산) (0) | 2009.08.17 |
[펌] 프로세스의 메모리안에 접근하고 읽고 쓰기. (0) | 2009.07.11 |
메시지 박스 띄울시 재진입 관련 문제..... (2) | 2009.07.08 |
멀티바이트 및 유니코드 문자열 길이 구하는 api 사용시 유의점 (3) | 2009.06.24 |