리스트 컨트롤

 

1. 리스트 컨트롤

- 리스트 박스 vs 리스트 컨트롤

리스트 박스 : 단일 항목 나열

리스트 컨트롤 : 리스트를 여러개 가짐

- 다양한 뷰 스타일 제공 (Icon, Small Icon, List, Report 스타일)

 

- 다양한 매크로 함수 제공

- 포함 헤더 : Commctrl.h, Windowsx.h

 

Report 스타일로 설정

 

이(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;
}

 

항목1,2,3,4 컬럼이 생성된다.

 


※ 아이템 관련 매크로 함수 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;

 

변수 추가
버튼 눌림을 위한 WM_COMMAND문 추가
버튼을 누를때 마다 아이템이 자신의 인덱스를 넣으면서 추가된다.

 


※ 아이템 항목 설정 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 : 아이템(열) 전체 선택
);

 

DlgProc에 인덱스 변수 추가

 

WM_INITDIALOG에 ListView_SetExtendedListViewStyle 속성을 설정한다

 

WM_NOTIFY 문 추가
선택 결과가 아래 Edit Control에서 보인다


※ 데이터 값 수정하기

ListView_GetItemText()

ListView_SetItemText()

nIndex 값 다시 설정
nIndex 가 -1이 아닐때. 즉, 선택되었을 때를 의미
수정

'Project > WIN32 API' 카테고리의 다른 글

컨트롤(2)  (0) 2021.07.22
컨트롤  (0) 2021.07.21
다이얼로그  (0) 2021.07.21
키보드, 마우스  (0) 2021.07.13
그래픽 오브젝트  (0) 2021.07.12

+ Recent posts