리스트 컨트롤
1. 리스트 컨트롤
- 리스트 박스 vs 리스트 컨트롤
리스트 박스 : 단일 항목 나열
리스트 컨트롤 : 리스트를 여러개 가짐
- 다양한 뷰 스타일 제공 (Icon, Small Icon, List, Report 스타일)
- 다양한 매크로 함수 제공
- 포함 헤더 : Commctrl.h, Windowsx.h
이(Report)는 엑셀과 비슷한 구조로, 행과 열로 구분할 수 있다.
열은 컬럼(Column), 행은 아이템(Item)이라고 부른다. 열의 모든 내용은 서브 아이템(Sub Item)이라고 부른다.
시작 인덱스는 모두 0 이다.
※ ListView_InsertColumn() 함수를 통한 컬럼 생성과 문자열 등록
void ListView_InsertColumn(
HWND hwnd, //윈도우 핸들
int iCol, //컬럼 인덱스
const LPLVCOLUMN pcol //LVCOLUMN의 메모리 주소
);
+ LVCOLUMN 구조체
typedef struct tagLVCOLUMNA {
UINT mask; //컬럼에 적용할 속성 설정(뭐뭐 조합할지)
int fmt;
int cx;
LPSTR pszText;
int cchTextMax;
int iSubItem;
int iImage;
int iOrder;
int cxMin;
int cxDefault;
int cxIdeal;
} LVCOLUMNA, *LPLVCOLUMNA;
+ LVCLOUMN mask : 컬럼에 적용할 속성 결정 (OR연산 이용)
LVCF_FMT | 정렬(왼쪽, 가운데, 오른쪽) |
LVCF_WIDTH | 길이 적용 |
LVCF_TEXT | 문자열 적용 |
LVCF_SUBITEM | 서브 아이템 적용 |
+ LVCOLUMN fmt : 컬럼과 서브 아이템의 데이터 정렬 형식 지정
LVCFMT_LEFT | Text is left-aligned. |
LVCFMT_RIGHT | Text is right-aligned. |
LVCFMT_CENTER | Text is centered. |
주의할 점 : 인덱스가 0인 컬럼과 서브아이템은 항상 왼쪽 정렬
+ LVCOLUMN cx, pszText, iSubItem
cx : 가로 길이
pszText : 문자열 지정
iSubItem : 서브 아이템 인덱스
#include "framework.h"
#include "WindowsProject9_ListControl.h"
#include "Commctrl.h"
#include "Windowsx.h"
INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
return 0;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
static HWND hList;
char* strMenu[] = { "항목1","항목2", "항목3", "항목4" };
LVCOLUMN lvColumn;
switch (message)
{
case WM_INITDIALOG:
hList = GetDlgItem(hDlg, IDC_LIST1);
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
lvColumn.fmt = LVCFMT_CENTER;
for (int i = 0; i < 4; i++) {
lvColumn.cx = strlen(strMenu[i]) * 10;//너무 붙어있지 말라고
lvColumn.pszText = strMenu[i];
ListView_InsertColumn(hList, i, &lvColumn);
}
return (INT_PTR)TRUE;
case WM_CLOSE:
EndDialog(hDlg, 0);
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
}
※ 아이템 관련 매크로 함수 ListView_GetItemCount
void ListView_GetItemCount(
HWND hwnd
);
void ListView_InsertItem(
HWND hwnd,
const LPLVITEM pitem
);
+ LVITEM 구조체
typedef struct tagLVITEMA {
UINT mask; //보통 LVIF_TEXT 만 지정하면 됨
int iItem; //ListView_GetItemCount
int iSubItem; //0 고정
UINT state;
UINT stateMask;
LPSTR pszText; //문자열 설정
int cchTextMax;
int iImage;
LPARAM lParam;
int iIndent;
int iGroupId;
UINT cColumns;
PUINT puColumns;
int *piColFmt;
int iGroup;
} LVITEMA, *LPLVITEMA;
※ 아이템 항목 설정 ListView_SetItemText() 이용 예제
#include "framework.h"
#include "WindowsProject9_ListControl.h"
#include "Commctrl.h"
#include "Windowsx.h"
#include <stdio.h>
INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
return 0;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
static HWND hList;
char* strMenu[] = { "순번","C","C++","WIN32" };
LVCOLUMN lvColumn;
LVITEM lvItem;
char string[100];
switch (message)
{
case WM_INITDIALOG:
hList = GetDlgItem(hDlg, IDC_LIST1);
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
lvColumn.fmt = LVCFMT_CENTER;
for (int i = 0; i < 4; i++) {
lvColumn.cx = 50;
lvColumn.pszText = strMenu[i];
ListView_InsertColumn(hList, i, &lvColumn);
}
return (INT_PTR)TRUE;
case WM_CLOSE:
EndDialog(hDlg, 0);
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON1) {
lvItem.iItem = ListView_GetItemCount(hList);
lvItem.iSubItem = 0;
lvItem.mask = LVIF_TEXT;
sprintf_s(string, "%d", lvItem.iItem);
lvItem.pszText = string;
ListView_InsertItem(hList, &lvItem);
GetDlgItemText(hDlg, IDC_EDIT1, string, 10);
ListView_SetItemText(hList, lvItem.iItem, 1, string);
GetDlgItemText(hDlg, IDC_EDIT2, string, 10);
ListView_SetItemText(hList, lvItem.iItem, 2, string);
GetDlgItemText(hDlg, IDC_EDIT3, string, 10);
ListView_SetItemText(hList, lvItem.iItem, 3, string);
//에디트 컨트롤 클리어
SetDlgItemText(hDlg, IDC_EDIT1, NULL);
SetDlgItemText(hDlg, IDC_EDIT2, NULL);
SetDlgItemText(hDlg, IDC_EDIT3, NULL);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
※ 서브 아이템 데이터 가져오기 ListView_GetItemText()
void ListView_GetItemText(
HWND hwndLV,
int iItem,
int iSubItem_,
LPTSTR pszText_, //문자열 저장을 위한 메모리 공간
int cchTextMax_
);
1단계) 아이템 선택에 대한 메세지 알아내기
- 발생 메세지 : WM_NOTIFY, 부가적 정보가 담긴 메모리 주소가 lparam에 담김
(부가적 정보 = 통지 코드, 컨트롤 핸들, 아이디가 저장된 메모리 주소)
lParam 다루는 방법 : NMHDR 구조체 사용
typedef struct tagNMHDR {
HWND hwndFrom; //윈도우 핸들
UINT_PTR idFrom; //컨트롤 아이디
UINT code; //통지 코드, NM_CLICK
} NMHDR;
2단계) 아이템 인덱스 알아내기 ListView_GetNextItem()
void ListView_GetNextItem(
HWND hwnd,
int i, //임의의 인덱스, 선택이 없을 때:-1
UINT flags //LVNI_SELECTED
);
+) 리스트 컨트롤 뷰 설정 ListView_SetExtendedListViewStyle()
void ListView_SetExtendedListViewStyle(
HWND hwndLV,
DWORD dwExStyle //LVS_EX_FULLROWSELECT : 하나의 행 전체 선택, LVS_EX_GRIDLINES : 아이템(열) 전체 선택
);
※ 데이터 값 수정하기
ListView_GetItemText()
ListView_SetItemText()