리스트뷰 -  ListBox가 발전된 형태로  좀 더 깔끔하고 다양한 기능을 사용할 수 있다.




리스트뷰 함수정리

ListView_GetItemCount()  :  등록된 항목의 개수

ListView_InsertItem()  :  새 항목 등록

ListView_SetItem()  :  항목의 정보를 변경(이미지 등)

ListView_SetItemText()  :  항목의 문자열을 변경

ListView_DeleteItem()  :  지정한 항목을 삭제

ListView_DeleteAllItems()  :  전체 항목을 삭제

ListView_GetItemText()  :  지정한 항목의 문자열을 얻어옴

ListView_GetNextItem()  :  옵션에 해당하는 항목의 인덱스 반환

ListView_FindItem()  :  제시한 조건과 일치하는 항목의 인덱스 반환

ListView_SetItemState()  :  지정한 항목의 상태 변경(포커스 등)





LVCOLUMN 구조체  -  LVCOLUMN 구조체에 헤더의 정보를 채운 뒤 LVM_INSERTCOLUMN 메시지 전송

Typedef struct_LVCOLUMN{
UINT mask;  :사용될 멤버 값 설정
int fmt;  :문자열의 정렬방법과 이미지 사용여부
int cx;  :헤더의 폭
LPTSTR pszText;  :보여질 문자열
int cchTextMax;  :문자열의 크기
int iSubItem;  :연결될 항목
#if(_WIN32_IE>=0x0300)  :IE의 버전(구 버전 이미지 사용불가)
int iImage;  :보여질 이미지
int iOrder;  :헤더의 순서
#endif
}LVCOLUMN,FAR*LPLVCOLUMN;



LVITEM 구조체 -  LVITEM 구조체에 항 정보를 채운 뒤 LVM_INSERTITEM  메시지 전송

Typedef struct_LVITEM{
UINT mask;  :사용될 멤버 값 설정
int iItem;  :항목의 Index설정
int iSubItem;  :항목의 Colum Index설정
UINT state;  :항목의 상태(focus, 선택 등)
UINT stateMask;  :상태를 설정
LPTSTR pszText;  :문자열(실제 내용)
int cchTextMax;  :문자열 길이
int iImage;  :왼쪽에 보여질 이미지의 인덱스
LPARAM lParam;  :항목의 추가 저장공간
#if(_WIN32_IE>=0x0300)  : IE의 버전(구 버전 들여쓰기 사용불가)
int iIndent;  :들여쓰기
#endif
}LVCOLUMN,FAR*LPLVCOLUMN;


 
LVFINDINFO 구조체 - LVFINDINFO 구조체에 검색할 정보를 채운 뒤 LVM_FINDITEM 메시지 전송

typedef struct tagLVFINDINFOW {
UINT flags;  :
검색 형태를 지정하는 옵션
LPCWSTR psz;  :검색할 문자열
LPARAM lParam;  :검색할 32bit Data
POINT pt;  :검색할 좌표값
UINT vkDirection;  :검색할 방향
} LVFINDINFOW, FAR* LPFINDINFOW;




#include <windows.h>
#include <commctrl.h>
#define IDC_LISTVIEW 150
#define LVIF_TEXT 151


LVCOLUMN COL; //열 구조체
LVITEM LI;          //항목 구조체
HWND hList;


void OnInitCOL(HWND hWnd)
{
 hList = CreateWindow(WC_LISTVIEW,NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT, 150,18,240,60,hWnd,(HMENU)IDC_LISTVIEW,0,0);
 ListView_SetExtendedListViewStyle(hList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
//리스트뷰 스타일 초기화

 COL.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
 COL.fmt = LVCFMT_LEFT;
 
 COL.cx=80;
 COL.pszText="가";   
 COL.iSubItem=0;
 ListView_InsertColumn(hList,0,&COL);   

//첫번째 : 해당 리스트 핸들
//두번째 : 몇번째 열인지
//세번째 : 해당 열의 초기화상태
 
 COL.cx=80;
 COL.pszText="나";   
 COL.iSubItem=1;
 ListView_InsertColumn(hList,1,&COL);
 
 COL.cx=80;
 COL.pszText="다";  
 COL.iSubItem=2;
 ListView_InsertColumn(hList,2,&COL);
}


void OnInitITEM()
{
 LI.mask = LVIF_TEXT;
 LI.iItem = 1;         //행 (전체 화면 - 캡션포함)
 LI.iSubItem = 0;    //열
 LI.pszText = "1";  //문자열 값
 ListView_InsertItem(hList, &LI);
//초기화된 항목구조체 정보를 토대로 해당리스트에 삽입 

 ListView_SetItemText(hList, 0, 1, "2"); 
//첫번째: 해당 리스트 핸들
//두번째 : 행 (캡션 미 포함)
//세번째 : 열
//네번째 : 값
 ListView_SetItemText(hList, 0, 2, "3");
 
  
 LI.iItem = 2;
 LI.pszText = "4";
 ListView_InsertItem(hList, &LI);

 ListView_SetItemText(hList, 1, 1, "5");
 ListView_SetItemText(hList, 1, 2, "6");
 
 LI.iItem = 3;
 LI.pszText = "7";
 ListView_InsertItem(hList, &LI);

 ListView_SetItemText(hList, 2, 1, "8");
 ListView_SetItemText(hList, 2, 2, "9");
}



결과



'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

ATOM  (0) 2010.02.09
간단한 DLL 예제  (1) 2010.02.03
리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
레지스트리  (0) 2010.02.02
o/s의 role  (0) 2010.01.28
Posted by 아몰라
TAG API, listview

댓글을 달아 주세요

윈도우 시스템은, 메시지구동 시스템으로 모든 이벤트는 메세지의 발생에 의해서 처리된다.


#define MY_USER 1000 
이렇게 선언할 경우 이미 1000이라는 값은 시스템이 내부적으로 예약해서 사용하는 상수일 수 있다.
그래서 이러한 현상을 막는 방법으로 WM_USER와 같은 사용자가 정의 할 수 있는 상수공간을 마련해두었다.


설명 - 이 메시지는 실제로 정의되어 있는 시스템 메시지가 아니며 사용자 정의 메시지의 시작 범위를 지정하는 상수값이다. 메시지는 정수값 하나로 표현되는데 윈도우즈는 메시지의 범위를 다음과 같이 정의하고 있다.



<범위 설명>

0~WM_USER-1
운영체제가 정의하는 시스템 메시지. WM_PAINT, WM_TIMER 등의 메시지들이 모두 이 범위에 속한다.

WM_USER~WM_APP-1
윈도우 클래스가 정의하는 사용자 정의 메시지
WM_APP~0xBFFF
응용 프로그램이 정의하는 사용자 정의 메시지

0xC000~0XFFFF
문자열로 등록되는 메시지

0x10000~ 이후의 사용을 위해 예약된 영역이며 현재는 사용되지 않는다.


WM_USER

WM_USER는 한 윈도우 클래스를 위한 고유의 메시지를 정의하기 위한 상수값이며 이 범위 이후부터 윈도우 클래스의 사용자 정의 메시지를 만들 수 있다. 이 값은 0x400으로 정의되어 있으며 보통 WM_USER+n으로 사용자 정의 메시지를 정의한다. 이때 n은 1보다 큰 정수이며 사용자 정의 메시지간의 구분을 위해 사용된다. 여러 개의 사용자 정의 메시지가 필요하다면 WM_USER+1, WM_USER+2, WM_USER+3,... 식으로 계속 n을 증가시켜 가며 메시지를 정의할 수 있다. 윈도우즈는 WM_USER이후 0x8000까지 사용자 정의 메시지 영역으로 정의하고 있으므로 n은 최대 0x7c00까지 가능하다. WM_USER+n을 곧바로 사용할 수도 있으며 자주 사용할 경우 다음과 같이 매크로를 정의하여 별도의 메시지를 만들 수 있다.

#define WM_MYMESSAGE WM_USER+1

이렇게 매크로를 정의해 놓고 이후부터 WM_MYMESSAGE라는 명칭을 대신 사용하면 된다.

주의
- 표준 컨트롤 중 일부는 자신만의 사용자 정의 메시지를 정의하여 사용하고 있다. 따라서 WM_USER+n은 가급적이면 한 윈도우 클래스내에서만 정의하여 사용해야 하며 응용 프로그램간의 통신에는 사용하지 않는 것이 바람직하다.
- 표준 컨트롤을 서브클래싱했을 경우 함부로 WM_USER+n을 사용하면 표준 컨트롤 고유의 메시지와 충돌이 발생할 수 있다.



예제
 
다음 예제는 사용자 정의 메시지로 윈도우를 이동시킨다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
        HDC hdc;
        PAINTSTRUCT ps;
        RECT wrt;
        TCHAR Mes[]="왼쪽 마우스 버튼을 누르면 이동합니다";

        switch(iMessage) {
        case WM_USER+1:
                GetWindowRect(hWnd,&wrt);
                wrt.left+=wParam;
                wrt.right+=wParam;
                wrt.top+=lParam;
                wrt.bottom+=lParam;
                MoveWindow(hWnd,wrt.left,wrt.top,wrt.right-wrt.left,wrt.bottom-wrt.top,TRUE);
                return 0;
        case WM_LBUTTONDOWN:
                SendMessage(hWnd,WM_USER+1,(WPARAM)-3,(LPARAM)5);
                return 0;
        case WM_PAINT:
                hdc=BeginPaint(hWnd, &ps);
                TextOut(hdc,10,10,Mes,lstrlen(Mes));
                EndPaint(hWnd, &ps);
                return 0;
        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
        }
        return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

이 예제에서 WM_USER+1은 윈도우를 이동하라는 뜻이며 wParam은 수평 이동 거리, lParam은 수직 이동 거리로 정의하였다. WM_USER+1을 받으면 이 인수들이 지정하는 거리만큼 윈도우를 이동시킨다.

WM_APP

#define WM_MYMESSAGE WM_APP+1

이렇게 매크로를 정의해 놓고 이후부터 WM_MYMESSAGE라는 명칭을 대신 사용하면 된다. WM_USER도 사용자 정의 메시지를 정의하는 용도로 사용되지만 표준 컨트롤중에 이미 WM_USER를 사용하는 컨트롤이 있으므로 중복될 위험성이 있다. 반면 WM_APP는 시스템이 전혀 이 영역을 사용하지 않고 있으므로 중복될 위험이 전혀 없으며 응용 프로그램간의 통신에 사용하기에 적합하다. 두 응용 프로그램의 약속에 의해 WM_APP+n 메시지를 정의하여 사용하면 된다.

WM_USER는 윈도우 클래스를 위한 사용자 정의 메시지이며 WM_APP는 응용 프로그램을 위한 사용자 정의 메시지라는 점이 다르다. 그러나 이 구분은 어디까지나 권장 사항일 뿐이지 강제 사항은 아니다. WM_USER를 응용 프로그램간의 통신에 사용하더라도 충돌이 없다는 확신만 있다면 가능하다. 다만 잠재적인 충돌 가능성이 있을 수 있다는 것을 고려할 때 바람직하지는 않다.

정리

이런 상황을 고려해 보자. MyApp에서 Con1이라는 커스텀 컨트롤을 사용하는데 이 컨트롤은 자신에게 변화가 있을 때 WM_USER+1이라는 통지 메시지를 부모 윈도우로 보내도록 되어 있다. 이런 상황에서 MyApp가 자신의 고유 용도로 WM_USER+1을 다시 정의한다면 메시지간의 충돌이 발생하게 된다. 이런 상황을 방지하기 위해 운영체제는 WM_USER를 내부적인 용도로 WM_APP를 응용 프로그램간의 통신에 사용하도록 권장하는 것이다. 하지만 WM_APP도 여전히 충돌이 발생할 가능성이 있으므로 좀 더 안전한 방법으로 메시지를 정의하고자 한다면 RegisterWindowMessage 함수로 문자열 메시지를 등록하여 사용하는 것이 좋다.


 

리턴값의 의미는 정해져 있다. 응용 프로그램이 의미를 정해서 사용할 수 있다. 이 메시지로 어떤 질문을 하고자할 때는 리턴값을 정의하며 그렇지 않을 경우는 통상 리턴값을 사용하지 않는다.



출처 http://www.winapi.co.kr/reference/Message/WM_USER.htm


'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

간단한 DLL 예제  (1) 2010.02.03
리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
레지스트리  (0) 2010.02.02
o/s의 role  (0) 2010.01.28
파일매핑예제  (0) 2010.01.25
Posted by 아몰라

댓글을 달아 주세요

정보의 저장

¢  프로그램은 실행 중에 사용자가 입력한 옵션 설정이나 프로그램 스스로 만들어낸 정보들을 다음 실행을 위해 그 정보를 저장 해두어야 한다.

¢  이런 정보는 사용자의 정보가 아니라 프로그램 자신의 정보이다

¢  프로그램의 설정 정보를 저장하는 방법에는 INI파일을 쓰는 방법과 레지스트리를 쓰는 방법이 있다.



레지스트리의 특징

¢  윈도우의 환경설정에 대한 모든 정보가 저장되어 관리되고 있는 Windows의 핵심적인 데이터베이스이다.

¢  다중 환경설정을 저장할 수 있다.

¢  INI 파일과 달리 크기가 64KB를 초과할 수 있다.

¢  INI 파일에 비해 속도가 빠르다.

¢  백업 및 복구가 간단하다.

 

레지스트리의 구조

 

¢  레지스트리는 디렉토리 구조와 유사한 계층적 구조로 구성

¢  각각의 가지(레지스트리 편집기에서 폴더 아이콘으로 표시되는)는 키라고 부르며, 각각의 키는 하위키를  포함할 수 있으며, 각각의 키는 값을 포함할 수 있다.

¢  이 값에 레지스트리에 저장되는 실제 정보가 저장됨



함수정리

레지스트리 키 생성 함수

LONG RegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved,                                   LPTSTR lpClass, DWORD dwOptions, REGSAM Desired, LPSECURITY_ATTRIBUTES lpSecurity, PHKEY hkResult, LPDWORD lpdwDisposition);


hKey :
새로 만들어지는 부모키 지정

     - HKEY_CLASSES_ROOT : 응용 프로그램을 위한 OLE정보와 모든 파일유형 정보 저장

     - HKEY_CURRENT_USER : 현재 로그인한 사용자를 위한 정보 저장

     - HKEY_LOCAL_MACHINE : 컴퓨터에 설치된 하드웨어와 소프트웨어에 대한 모든 정보 저장

     - HKEY_USERS : 컴퓨터를 사용하는 사용자 각각에 대한 속성을 저장

     - HKEY_CURRENT_CONFIG : 현재 하드웨어의 설정을 저장


lpSubKey : 만들고자 하는 서브키를 지정하는 널 종료 문자열로 반드시 지정해야 함.

                hKey 서브에 여기서 지정한 키가 생성됨.

Reserved : 예약된 인수, 0으로 지정

lpClass : 생성되는 키의 클래스를 지정하는 문자열

dwOptions : 생성하는 키의 옵션

   - REG_OPTION_NON_VOLATILE : 레지스트리에 저장되는 정보는 파일에

                                                  영구 저장되므로 재부팅해도 정보 유지

samDesired : 보안속성

   - KEY_ALL_ACCESS : 읽기, 쓰기 할 때 사용

   - KEY_WRITE : 쓰기,  KEY_READ : 읽기

lpSecurityAttribute : 생성된 키값이 상속될 것인가 지정하는 인수, NULL이면 상

                            속되지 않음


phkResult  : 만들어지거나 열려진 키값이 대입되는 변수 포인터

                  여기에 HKEY구조체 변수를 대입

lpdwDisposition : 키가 새로 생성되었는지 기존의 키가 오픈된 것인지 리턴받기

                         위한 출력용 변수


열려진 키에 값을 저장하는 함수

LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved,  DWORD dwType, CONST BYTE *lpData, DWORD cbData);


hKey :
값을 저장하고자 하는 키 핸들(현재 열려진 키)

lpValueName : 값의 이름

Reserved : 이 인수는 사용하지 않음

dwType : 값의 데이터 타입을 지정 (대부분의 정보를 저장할 수 있다)

    - REG_BINARY : 이진 데이터

    - REG_SZ : 문자열

lpData : 저장하고자 하는 데이터의 포인터

cbData : 데이터의 크기


저장한 위치의 값을 읽어오는 함수

LONG RegQueryValueEx(HKEY hKey, LPTSTR lpValueName, LPDWORD lpReserved,                          LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);


hKey :
값을 저장하고자 하는 키 핸들(현재 열려진 키)

lpValueName : 값의 이름

lpReserved : 이 인수는 사용하지 않음

lpType : 읽은 값의 타입을 대입받을 변수의 포인터

lpcbData : 실제 복사된 데이터의 크기를 리턴, 대입받을 변수의 크기를 대입

RegCreateKeyEx(), RegSetValueEx(), RegQueryValueEx() 이 함수들은 제대로 읽거나 저장

                                                                   했다면 ERROR_SUCCESS(0)가 리턴 된다



열려진 레지스트리 키를 닫는 함수


 

LONG RegCloseKey(HKEY hKey);

레지스트리 키도 메모리를 소모하므로 사용하고 난 후에는 해제를 해야함



실습예제

#include <windows.h>
#include "resource.h"


BOOL CALLBACK DlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam);

#define CURRENT HKEY_CURRENT_USER
#define KEY "SoftWare\\Bit\\Test\\"

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nShowcmd)
{
 DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),0,DlgProc);  

 return 0;
}

BOOL CALLBACK DlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 TCHAR str[256];
 HKEY key;
 DWORD dwDisp;
 DWORD Size;  //불러올때 사이즈

 switch(iMessage)
 {
 case WM_INITDIALOG:  break;
 
 case WM_COMMAND:

  switch(LOWORD(wParam))
  {
  case IDOK: //저장하기
   
   GetDlgItemText(hDlg, IDC_EDIT1, str, 256);
   RegCreateKeyEx(CURRENT, KEY"Edit",0,NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0,&key, &dwDisp);
   RegSetValueEx(key, "STR", 0, REG_SZ, (LPBYTE)str, strlen(str)+1);
   RegCloseKey(key);
   break;

  case IDOK2: //불러오기

   RegCreateKeyEx(CURRENT, KEY"Edit",0,NULL, REG_OPTION_NON_VOLATILE,KEY_READ,0, &key, &dwDisp);
   RegQueryValueEx(key, "STR", 0, NULL, (LPBYTE)str, &Size);
   MessageBox(hDlg, str, "", MB_OK);
   RegCloseKey(key);
   break;
  case IDCANCEL:
   EndDialog(hDlg,IDCANCEL);
   break;
  }

  return TRUE;
 
 }
 return FALSE;
}

'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
레지스트리  (0) 2010.02.02
o/s의 role  (0) 2010.01.28
파일매핑예제  (0) 2010.01.25
WNDCLASS 구조체  (0) 2010.01.25
Posted by 아몰라
TAG registry

댓글을 달아 주세요