CreateWindow

원형 HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID lpParam);
MFC 원형 virtual BOOL CWnd::Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
인수

▶lpClassName : 생성할 윈도우의 윈도우 클래스를 지정하는 문자열이다. 윈도우 클래스는 RegisterClass(Ex) 함수로 직접 등록할 수도 있고 또는 button, edit, listbox, static 등과 같이 미리 정의되어 있는 시스템 전역 클래스일 수도 있다. 또는 GlobalAddAtom 함수로 미리 등록해 놓은 정수형의 아톰을 사용하는 것도 가능하다.

▶lpWindowName : 윈도우의 타이틀 바에 나타날 캡션 문자열이다. 캡션이 나타날 위치는 윈도우 클래스에 따라 달라지는데 오버랩드 윈도우는 타이틀 바에 캡션이 나타나며 버튼, 스태틱 등의 컨트롤은 컨트롤 중앙에 캡션이 출력된다.

▶dwStyle : 생성될 윈도우의 스타일을 지정한다.

스타일 설명
WS_OVERLAPPED 디폴트 윈도우. 타이틀 바와 크기 조절이 안되는 경계선을 가진다. 아무런 스타일도 주지 않으면 이 스타일이 적용된다.
WS_POPUP 팝업 윈도우를 만든다. WS_CHILD와 함께 쓸 수 없다.
WS_CHILD 차일드 윈도우를 만든다. WS_POPUP과 함께 쓸 수 없다.
WS_MINIMIZE 최초 최소화된 상태로 윈도우를 만든다.
WS_VISIBLE 윈도우를 만들자 마자 화면에 출력한다.
WS_DISABLED 사용금지된 상태, 즉 입력을 받아들일 수 없는 상태로 만든다.
WS_CLIPSIBLINGS 차일드끼리 상호 겹친 영역은 그리기 영역에서 제외된다.
WS_CLIPCHILDREN 차일드가 위치한 영역은 그리기 영역에서 제외된다.
WS_MAXIMIZE 최초 최대화된 상태로 윈도우를 만든다.
WS_CAPTION 타이틀 바를 가진 윈도우를 만들며 WS_BORDER 스타일을 포함한다.
WS_BORDER 단선으로 된 경계선을 만들며 크기 조정은 할 수 없다.
WS_DLGFRAME 두꺼운 경계선을 가지며 타이틀 바를 가질 수 없다.
WS_VSCROLL 수직 스크롤 바를 가진 윈도우를 만든다.
WS_HSCROLL 수평 스크롤 바를 가진 윈도우를 만든다.
WS_SYSMENU 시스템 메뉴를 가진 윈도우를 만든다.
WS_THICKFRAME 크기 조정이 가능한 두꺼운 경계선을 가진다.
WS_GROUP 라디오 버튼 등 그룹을 이루는 컨트롤의 그룹 지정에 사용된다.
WS_TABSTOP Tab키로 포커스를 이동할 수 있도록 한다.
WS_MINIMIZEBOX 최소화 버튼을 만든다.
WS_MAXIMIZEBOX 최대화 버튼을 만든다.
WS_OVERLAPPEDWINDOW 가장 일반적인 윈도우 스타일. WS_OVERLAPPED |WS_CAPTION |WS_SYSMENU |WS_THICKFRAME |WS_MINIMIZEBOX |WS_MAXIMIZEBOX 스타일들이 조합된 스타일이다.
WS_POPUPWINDOW 일반적인 팝업 윈도우. WS_POPUP |WS_BORDER |WS_SYSMENU
WS_CHILDWINDOW WS_CHILD와 같다.

각 스타일의 비트 배치는 다음과 같다.

▶x, y : 윈도우의 좌표를 지정한다. 오버랩드, 팝업 윈도우는 화면의 원점을 기준으로 한 좌표로 지정하며 차일드 컨트롤은 부모 윈도우의 작업 영역 원점을 기준으로 한 좌표로 지정한다. CW_USEDEFAULT로 지정할 경우 시스템이 적절한 디폴트 위치에 윈도우를 생성해 주는데 이 값은 오버랩드 윈도우에만 적용되며 차일드나 팝업 윈도우에는 적용되지 않는다.

▶nWidth, nHeight : 윈도우의 수평 크기와 수직 크기를 장치 단위(픽셀)로 지정한다. 오버랩드 윈도우의 경우 nWidth에 CW_USEDEFAULT를 지정할 수 있으며 이 경우 시스템은 적절한 폭과 높이를 디폴트로 설정해 준다. nWidth가 CW_USEDEFAULT일 경우 nHeight는 무시된다.

▶hWndParent : 부모 윈도우, 또는 소유주 윈도우의 핸들을 지정한다. 차일드 윈도우는 부모 핸들을 반드시 지정해야 하며 팝업 윈도우는 부모 윈도우를 생략할 수도 있다. NT 5.0이상에서 이 인수에 HWND_MESSAGE를 지정하거나 이미 만들어져 있는 메시지 전용 윈도우 핸들을 부모로 지정하면 메시지 전용의 윈도우가 생성된다.

▶hMenu : 오버랩드 윈도우나 팝업 윈도우의 경우 메뉴의 핸들을 지정한다. 윈도우 클래스에 메뉴가 지정되지 않았을 경우 이 인수가 지정하는 핸들이 사용되며 만약 윈도우 클래스와 이 인수에 동시에 다른 메뉴가 지정되어 있으면 이 인수가 지정하는 메뉴가 우선적으로 적용된다. 차일드 윈도우의 경우 컨트롤의 ID를 지정하는데 이 ID는 차일드가 부모 윈도우(주로 대화상자)에게 통지 메시지를 보낼 때 차일드간의 구분을 위해 사용하므로 같은 부모에 속한 컨트롤끼리는 중복되는 ID를 가지지 않아야 한다.

▶hInstance : 이 윈도우를 생성하는 인스턴스 핸들을 지정한다. 이 인스턴스가 종료될 때 윈도우도 같이 파괴된다.

▶lpParam : WM_CREATE메시지의 lParam으로 전달될 CREATESTRUCT 구조체를의 포인터이다. MDI 클라이언트 윈도우를 만들 때는 CLIENTCREATESTRUCT 구조체의 포인터를 전달해야 한다.

리턴 윈도우 생성에 성공했으면 생성된 윈도우의 핸들을 리턴하며 에러 발생시 NULL을 리턴한다.
설명

윈도우 클래스와 이 함수의 인수 정보를 바탕으로 하여 윈도우를 생성한다. RegisterClass 함수로 직접 윈도우 클래스를 등록하여 메인 윈도우를 만들 수도 있으며 또는 이미 등록된 컨트롤을 생성할 수도 있다.

이 함수는 윈도우 생성 후 WM_CRETATE. WM_GETMINMAXINFO, WM_NCCREATE 메시지를 해당 윈도우로 차례대로 보내주며 WS_VISIBLE 스타일이 지정되어 있을 경우 윈도우를 보여주고 활성화시키기 위한 모든 동작을 하며 관련 메시지를 보내준다.

예제 1

다음 예제는 메인 윈도우, 차일드 윈도우, 팝업 윈도우를 각각 생성한다.

	// 팝업 윈도우의 윈도우 클래스를 등록한다.
	WndClass.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
	WndClass.lpfnWndProc=(WNDPROC)WndProcPopup;
	WndClass.lpszClassName="mypopup";
	RegisterClass(&WndClass);

	hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,(HMENU)NULL,hInstance,NULL);
	ShowWindow(hWnd,nCmdShow);
	hWndMain=hWnd;
	
	while(GetMessage(&Message,0,0,0)) {
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return Message.wParam;
}

HWND hPopup=NULL;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch(iMessage) {
	case WM_CREATE:
		CreateWindow("button","차일드 컨트롤",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
			20,20,150,30,hWnd,(HMENU)0,g_hInst,NULL);
		return 0;
	case WM_LBUTTONDOWN:
		if (hPopup)
			return 0;
		hPopup=CreateWindow("mypopup","팝업 윈도우",WS_POPUPWINDOW | WS_CAPTION,
			100,100,320,200,hWnd,(HMENU)0,g_hInst,NULL);
		ShowWindow(hPopup,SW_SHOW);
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

LRESULT CALLBACK WndProcPopup(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	char str[]="팝업 윈도우입니다";

	switch(iMessage) {
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		TextOut(hdc,10,10,str,lstrlen(str));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		hPopup=NULL;
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

WinMain에서 오버랩드 윈도우와 팝업 윈도우의 윈도우 클래스를 등록하였고 메인 윈도우가 생성될 때 버튼 차일으 윈도우를 생성하였다. 마우스 왼쪽 버튼을 누르면 팝업 윈도우를 만든다.

 

참고함수

DestroyWindow : 윈도우를 파괴한다.

CreateWindowEx, ShowWindow, MoveWindow

플렛폼 95이상
참조  

MessageBox

원형 int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
원형 int CWnd::MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK );
인수

▶hWnd : 부모 윈도우의 핸들. 메시지 박스의 이 윈도우의 모달 대화상자로 열린다. 부모 윈도우가 없을 경우 NULL로 지정할 수 있다.

▶lpText : 메시지 내용을 나타내는 널 종료 문자열. 이 문자열은 ANSI 문자열일 수도 있고 유니코드 문자열일 수도 있는데 어떤 포맷이라도 메시지 출력이 가능하다.

▶lpCaption : 메시지 박스의 타이틀 바에 나타날 문자열. NULL일 경우 디폴트로 Error(한글 윈도우즈에서는 오류)가 표시된다.

▶uType : 메시지 박스에 나타날 버튼의 종류와 아이콘 모양, 동작 방식을 지정한다. 다음 여러 그룹의 플래그 조합을 지정할 수 있다.

그룹 1 - 메시지 박스에 나타날 버튼의 종류를 지정한다.

플래그 나타나는 버튼들
MB_ABORTRETRYIGNORE
MB_OK
MB_OKCANCEL
MB_RETRYCANCEL
MB_YESNO
MB_YESNOCANCEL

그룹 2 - 메시지 박스에 나타날 아이콘을 지정한다.

플래그 아이콘
MB_ICONEXCLAMATION, MB_ICONWARNING
MB_ICONINFORMATION, MB_ICONASTERISK
MB_ICONQUESTION
MB_ICONSTOP, MB_ICONERROR, MB_ICONHAND

그룹 3 - 디폴트 버튼을 지정한다.

플래그 디폴트 버튼
MB_DEFBUTTON1

첫번째 버튼이 디폴트 버튼이 된다. 별다른 지정이 없으면 이 플래그가 선택된다.

MB_DEFBUTTON2 두번째 버튼이 디폴트 버튼이 된다.
MB_DEFBUTTON3 세두번째 버튼이 디폴트 버튼이 된다.
MB_DEFBUTTON4 네번째 버튼이 디폴트 버튼이 된다.

그룹 4 - 대화상자의 모달 여부를 지정한다.

플래그 설명
MB_APPMODAL

hWnd 윈도우의 모달 대화상자로 열리므로 메시지 박스를 닫기 전에는 같은 스레드에 속한 다른 윈도우로 전환할 수 없다. 그러나 다른 스레드의 윈도우로 전환할 수는 있으며 팝업 윈도우로도 전환할 수 있다. 아무 플래그도 지정되지 않으면 이 모드가 디폴트로 적용된다.

MB_SYSTEMMODAL

MB_APPMODAL과 동일하되 항상 위 스타일을 가져 모든 윈도우보다 위에 배치된다. 메모리 부족 등의 긴급한 상황을 알리고자 할 때 이 플래그를 사용한다.

MB_TASKMODAL

MS_APPMODAL과 동일하되 hWnd가 NULL일 경우 현재 스레드에 속한 모든 최상위 윈도우가 사용 금지된다는 점이 다르다. DLL이나 라이브러리에서 부모 윈도우로 지정할만한 윈도우가 없을 때 이 플래그를 사용한다.

그룹 5 - 기타 몇가지 옵션을 지정한다.

플래그 설명
MB_DEFAULT_DESKTOP_ONLY 사용자가 로그온안 후 응용 프로그램이 실행되고 있는 디폴트 데스크 탑인 경우만 메시지 박스가 나타나도록 한다.
MB_HELP 도움말 버튼을 보여준다. 이 버튼을 누르거나 F1키를 누르면 Help 이벤트가 발생한다.
MB_RIGHT 메시지를 오른쪽으로 정렬한다.
MB_RTLREADING 아랍이나 헤브루 윈도우즈에서 오른쪽에서 왼쪽 읽기로 출력한다. 한글 윈도우즈에서는 의미가 없다.
MB_SETFOREGROUND 메시지 박스를 포그라운드 윈도우로 만든다. 시스템은 내부적으로 SetForegroundWindow 함수를 호출한다.
MB_TOPMOST 항상 위 옵션으로 메시지 박스를 생성한다.
MB_SERVICE_NOTIFICATION NT의 서비스 프로그램만 사용할 수 있는 플래그이다. 현재 로긴한 사용자가 없더라도 액티브되어 있는 데스크 탑에 메시지 박스를 출력한다. 이 경우 hWnd는 반드시 NULL이어야 한다.
MB_SERVICE_NOTIFICATION_NT3X MB_SERVICE_NOTIFICATION와 동일하되 NT 3.51버전에서 사용한다.
리턴

메시지 박스를 생성할 메모리가 부족할 경우 0을 리턴한다. 그 외의 경우 사용자가 누른 버튼의 ID를 리턴한다.

리턴값 버튼
IDABORT 중단 버튼을 눌렀다.
IDCANCEL 취소 버튼을 눌렀다. Esc키를 눌러 대화상자를 닫을 때도 이 값이 리턴된다.
IDIGNORE 무시 버튼을 눌렀다.
IDNO 아니오 버튼을 눌렀다.
IDOK 확인 버튼을 눌렀다.
IDRETRY 재시도 버튼을 눌렀다.
IDYES 예 버튼을 눌렀다.

 

설명

메시지 박스는 응용 프로그램이 사용자와 대화할 수 있는 가장 간단한 방법이다. 짧은 메시지와 함께 MB_OK 플래그로 간단하게 전달 사항만 전달하는 것이 보편적이다.

MessageBox(hWnd,"야! 신난다.","알림",MB_OK);

위 코드는 짧은 문자열을 보여준다. 여러 줄의 긴 메시지를 출력할 때는 다음과 같이 문자열 중간에 개행 코드를 삽입해 주면 된다.

MessageBox(hWnd,
	"동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라 만세\r\n"
	"남산 위의 저 소나무 철갑을 두른 듯 바람서리 불변함을 우리 기상일세\r\n"
	"가을 하늘 공활한데 높고 구름없이 밝은 달은 우리 가슴 일편 단심일세\r\n"
	"이 기상과 이 맘으로 충성을 다하여 괴로우나 즐거우나 나라 사랑하세",
	"애국가",MB_OK);

다음 코드는 메시지 박스로 사용자에게 질문을 하는 예이다. 질문에 응답한 결과를 조사하여 다른 처리를 하고자 할 때도 메시지 박스를 사용할 수 있다.

if (MessageBox(hWnd,"WinApi에 자주 오십니까?","질문",MB_YESNO)==IDYES) {
	// 자주 올 때의 처리
} else {
	// 그렇지 않을 때의 처리
}

또한 메시지 박스는 디버깅 중에 제어의 흐름을 감시하거나 변수의 값을 간단하게 살펴보고자 할 때도 자주 사용된다. 원하는 변수값을 wsprintf 등의 함수로 조립한 후 화면으로 출력하면 실행중에 변수값을 확인할 수 있다.

참고함수 MessageBoxEx, MessageBeep
플렛폼 95이상
참조  

ReadFile

원형

BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);

MFC 원형

해당하는 함수 없음

인수

▶hFile : 읽고자 하는 파일의 핸들. 이 파일은 GENERIC_READ 액세스 권한으로 열어야 한다.

▶lpBuffer : 읽는 데이터를 저장할 버퍼의 포인터, 충분한 길이를 가지고 있어야 한다.

▶nNumberOfBytesToRead : 읽고자 하는 바이트 수

▶lpNumberOfBytesRead : 실제로 읽은 바이트 수를 리턴받기 위한 출력용 인수. ReadFile은 호출 즉시 이 값을 0으로 만든다. 비동기 입출력을 하지 않을 경우 이 인수는 NULL로 줄 수 없으며 반드시 DWORD형 변수에 대한 포인터를 제공해야 한다.

▶lpOverlapped : 비동기 입출력을 위한 OVERLAPPED 구조체의 포인터. 파일을 FILE_FLAG_OVERLAPPED 플래그로 열었으면 이 구조체를 반드시 제공해야 한다. 비동기 입출력을 사용하지 않을 경우 NULL을 주면 된다.

리턴

성공하면 0이 아닌 값을 리턴한다. 만약 리턴값이 0이 아닌데 실제 읽은 바이트가 0이라면 파일 포인터가 끝부분(EOF)인 것이다. 실패하면 0을 리턴한다.

설명

파일로부터 데이터를 읽는다. 주로 동기적인 입력에 사용하므로 데이터를 완전히 읽기 전에는 리턴하지 않는다. 비동기 입력에 사용할 경우는 즉시 리턴한다. 파일 포인터 위치에서부터 데이터를 읽으며 다 읽은 후 실제 읽은 바이트 수만큼 파일 포인터를 이동시켜 준다. 단, 비동기 입출력중일 때는 응용 프로그램이 파일 포인터를 직접 이동시켜 주어야 한다.

예제 1

다음 예제는 C드라이브의 루트 폴더에 있는 boot.ini 파일을 읽어 메시지 박스로 보여준다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	HANDLE hFile;
	TCHAR buf[32000]={0,};
	DWORD dwRead;

	switch(iMessage) {
	case WM_CREATE:
		return 0;
	case WM_LBUTTONDOWN:
		hFile=CreateFile("c:\\boot.ini",GENERIC_READ,0,NULL,
			OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
		if (hFile!=INVALID_HANDLE_VALUE) {
			ReadFile(hFile,buf,1024,&dwRead,NULL);
			CloseHandle(hFile);
			MessageBox(hWnd,buf,"읽은 결과",MB_OK);
		}
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

참고함수

CreateFile, WriteFile

플랫폼

95이상

참조

 

API

CreateFile

원형

HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES pSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

MFC 원형

해당하는 함수 없음

인수

▶lpFileName : 생성하고자 하는 파일(또는 오브젝트)의 이름을 지정한다. 오브젝트의 이름은 최대 MAX_PATH의 길이로 지정할 수 있으나 NT/2000에서 유니코드로 컴파일할 경우는 32000자까지의 길이를 사용할 수 있다. 이때 파일명은 "\\?\"로 시작되어야 한다. 파일의 경우 완전 경로를 줄 수도 있고 현재 디렉토리를 기준으로 한 상대 경로로 줄 수도 있다.

▶dwDesiredAccess : 파일에 대한 액세스 권한을 지정한다. 생성하거나 연 파일로 어떤 작업을 할 것인가에 따라 적절한 액세스 권한을 지정해야 한다. 다음 플래그 중 하나 또는 조합을 지정할 수 있는데 이 플래그들은 모든 오브젝트에 공통적으로 적용되는 일반형 권한이다.

플래그

설명

0

장치 오브젝트에 대한 쿼리 액세스만 요청한다. 이 권한으로 장치를 열 경우 실제로 장치를 액세스하지 않고도 장치의 특성을 조사할 수 있다. 예를 들어 디스켓이 없는 상태에서도 플로피 드라이브의 타입이나 용량등을 조사하는 것이 가능하다.

GENERIC_READ

읽기 위한 용도로 파일을 연다. 이 액세스 권한으로 연 파일은 읽을 수만 있으며 쓸 수는 없다.

GENERIC_WRITE

쓰기 위한 용도로 파일을 연다. 읽기와 쓰기를 동시에 하려면 GENERIC_READ | GENERIC_WRITE 플래그를 지정하면 된다.

액세스 권한은 가급적이면 최소한으로 요청하는 것이 좋다. 예를 들어 읽기만 할 용도로 파일을 연다면 GENERIC_READ 플래그만 주어야 한다. 불필요하게 읽기와 쓰기 액세스 권한을 동시에 요청할 경우 읽기 전용 파일이나 CD-ROM의 파일을 열지 못하게 된다.

이런 일반형 권한 외에 오브젝트 고유의 권한을 같이 지정하거나 아니면 일반형 권한없이 표준 권한과 고유형 권한으로 액세스 마스크를 구성할 수도 있다. 각 오브젝트의 고유한 권한에 대해서는 해당 오브젝트를 참조하기 바란다.

▶dwShareMode : 파일의 공유 모드를 지정한다. 공유 모드란 파일이 열려져 있는 상태에서 다른 프로세스가 또 이 파일을 오픈할 때 이를 허가할 것인가 아닌가를 지정한다. 만약 현재 프로세스가 파일을 쓰고 있는 상태에서 다른 프로세스가 파일을 읽을 수 없도록 하고 싶다면 공유 모드를 지정하지 않아야 한다. 다음 플래그들의 조합으로 공유 모드를 지정한다.

플래그

설명

FILE_SHARE_READ

다른 프로세스가 읽기 액세스 권한을 요청했을 때 이를 허가한다. 즉, 이 프로세스가 파일을 사용하는 동안에도 다른 프로세스가 파일을 읽을 수 있다.

FILE_SHARE_WRITE

다른 프로세스가 쓰기 액세스 권한을 요청했을 때 이를 허가한다. 즉, 이 프로세스가 파일을 사용하는 동안에도 다른 프로세스가 파일에 데이터를 쓸 수 있다.

FILE_SHARE_DELETE

NT/2000. 삭제 액세스 권한을 요청했을 때만 이를 허가한다.

▶pSecurityAttributes : 파일의 보안 속성을 지정하는 SECURITY_ATTRIBUTES 구조체의 포인터이다. 이 보안 속성에 따라 생성되는 파일의 보안 설명자가 달라지며 차일드 프로세스로 핸들을 상속할 수 있는가의 여부가 결정된다. NULL이면 핸들은 상속될 수 없으며 디폴드 보안 설명자가 할당된다. 단, 파일의 보안 설명자가 할당되기 위해서는 파일이 저장되는 디스크의 파일 시스템이 반드시 NTFS로 포맷되어 있어야 한다.

▶dwCreationDisposition : 파일을 생성할 것인지 열 것인지를 지정한다. 또한 생성하고자 하는 파일이 이미 존재하거나 또는 열고자 하는 파일이 없을 경우의 동작을 지정한다. 적절한 에러를 리턴받기 위해서는 이 플래그를 신중하게 잘 지정해 주어야 한다. 그렇지 않으면 없는 파일이 열리거나 기존 파일이 깨지는 등 프로그램이 오동작을 할 위험이 있다.

플래그

설명

CREATE_NEW

파일을 새로 만든다. 만약 이미 파일이 존재한다면 에러를 리턴한다.

CREATE_ALWAYS

항상 파일을 새로 만든다. 만약 이미 파일이 존재한다면 해당 파일을 덮어쓴다. 이는 기존 파일을 삭제하고 다시 만드는 것과 같다. 파일의 존재 여부에 상관없이 무조건 파일을 생성한다.

OPEN_EXISTING

이미 존재하는 파일을 연다. 만약 열고자 하는 파일이 없다면 이 함수는 에러를 리턴한다. 파일이 아닌 장치를 열고자 할 때는 반드시 이 플래그를 사용해야 한다.

OPEN_ALWAYS

무조건 파일을 연다. 열고자 하는 파일이 없을 경우는 직접 만든 후 이 파일을 연다. 파일이 없어도 에러를 리턴하지 않으므로 기존 파일을 열 때는 이 플래그를 사용하지 말아야 한다.

TRUNCATE_EXISTING

파일을 연 후 크기를 0으로 만든다. 즉, 기존 파일을 다시 작성하고자 할 때 이 플래그를 사용한다. 이 플래그를 사용하는 프로세스는 쓰기 액세스 권한으로 파일을 열어야 하며 파일이 없을 경우는 에러를 리턴한다.

▶dwFlagsAndAttributes : 생성할 파일의 속성 또는 기타 옵젝트이 속성을 지정한다. 파일의 속성은 다음 플래그들의 조합을 사용할 수 있다.

플래그

설명

FILE_ATTRIBUTE_ARCHIVE

기록 속성을 설정한다. 파일의 기록 속성은 백업, 리스토어 프로그램에 의해 사용되며 이 파일이 백업되어야 함을 알리는 플래그이다.

FILE_ATTRIBUTE_ENCRYPTED

파일을 암호화한다. 파일의 경우 파일의 데이터를 암호화하며 디렉토리의 경우 이후부터 생성되는 파일과 서브 디렉토리를 암호화하도록 한다. 시스템 파일에는 적용되지 않는다.

FILE_ATTRIBUTE_HIDDEN

숨김 파일로 생성한다. 숨김 파일은 통상적인 방법으로는 보이지 않으므로 목록에 나타나지 않는다.

FILE_ATTRIBUTE_NORMAL

아무런 속성도 가지지 않는 파일을 만든다. 이 이 플래그는 단독으로 사용될 때만 유효하며 다른 플래그와 함께 사용하면 해당 플래그의 속성이 설정되다.

FILE_ATTRIBUTE_NOT_CONTENT_INDEXED

컨텐트 인덱싱 서비스에 대해 인덱스되지 않도록 한다.

FILE_ATTRIBUTE_OFFLINE

데이터가 오프라인 상태이며 즉시 사용할 수 있는 상태가 아니다. 이 속성은 윈도우즈 2000의 계층적 저장 관리자의 원격 저장소에 의해 사용되므로 응용 프로그램이 이 플래그를 직접 사용해서는 안된다.

FILE_ATTRIBUTE_READONLY

읽기 전용의 파일로 생성한다. 응용 프로그램은 이 파일의 내용을 읽을 수는 있지만 변경하거나 삭제할 수는 없다.

FILE_ATTRIBUTE_SYSTEM

시스템 파일로 생성한다. 시스템 파일은 운영체제에 의해 배타적으로 사용되는 파일이다.

FILE_ATTRIBUTE_TEMPORARY

임시 파일로 생성한다. 임시 파일은 디스크로 곧바로 입출력을 행하지 않고 가급적이면 메모리상에서 읽기와 쓰기를 수행하기 때문에 일반 파일보다 입출력 속도가 빠르다는 장점이 있다. 응용 프로그램은 임시파일을 다 사용한 후 반드시 삭제해 주어야 한다.

파일 속성과 함께 다음 플래그들도 같이 지정할 수 있다.

플래그

설명

FILE_FLAG_WRITE_THROUGH

가급적이면 캐시를 사용하지 않고 곧바로 디스크로 입출력을 행하도록 한다. 그러나 이 플래그를 지정해도 시스템이 쓰기 캐시를 사용할 수는 있되 다만 너무 늦게 버퍼를 비우지 않도록 해 준다. 기록 후 곧바로 사용해야 하는 데이터는 이 플래그를 주는 것이 좋다.

FILE_FLAG_OVERLAPPED

파일 입출력이 완전히 끝날 때까지 대기하지 않고 곧바로 리턴하는 비동기 입출력 모드로 파일을 연다. 이 모드를 사용하면 입출력 시간이 오래 걸릴 때 백그라운드로 파일을 액세스할 수 있으며 하나의 파일 핸들로 동시에 액세스가 가능하다. 이 모드로 열려진 파일을 액세스하는 함수는 OVERLAPPED 구조체를 초기화한 후 제공해여 한다.

비동기 입출력에 관한 상세한 내용은 34-1-사절을 참조하기 바란다.

FILE_FLAG_NO_BUFFERING

버퍼링이나 캐시를 하지 않으므로써 비동기 효율을 극대화한다. 이 플래그를 사용하기 위해서는 몇가지 요구 사항을 충족시켜야 한다.

FILE_FLAG_RANDOM_ACCESS

파일을 랜덤으로 액세스한다는 것을 시스템에게 알려준다. 시스템은 캐시를 최적화할 때 이 정보를 사용한다. 이 플래그는 어디까지나 시스템에 대한 힌트일 뿐이다.

FILE_FLAG_SEQUENTIAL_SCAN

파일을 순차 액세스한다는 것을 시스템에 알려준다. 시스템은 캐시 최적화에 이 정보를 사용하여 순차 액세스의 효율을 높일 수 있는 방식으로 캐시를 사용한다. 그러나 이 플래그를 지정했다고 해서 랜덤 액세스를 하지 못하는 것은 아니다. 큰 파일을 대부분 순차적으로 액세스하고 드물게 랜덤 액세스를 할 경우 이 플래그를 지정하면 효율을 높일 수 있다.

FILE_FLAG_DELETE_ON_CLOSE

이 파일에 대한 모든 핸들이 닫히면 파일을 삭제하도록 한다.

FILE_FLAG_BACKUP_SEMANTICS

NT/2000 이후. 백업, 리스토어를 위해 파일을 연다. 이 경우 시스템은 보안 체크를 무시한다.

FILE_FLAG_POSIX_SEMANTICS

파일을 POSIX 규칙대로 액세스한다. 파일명은 대소문자를 구분하며 대소문자만 다른 같은 파일명을 액세스할 수 있다. 이렇게 생성된 파일은 16비트 프로그램에서 액세스할 수 없다.

FILE_FLAG_OPEN_REPARSE_POINT

Specifying this flag inhibits the reparse behavior of NTFS reparse points. When the file is opened, a file handle is returned, whether the filter that controls the reparse point is operational or not. This flag cannot be used with the CREATE_ALWAYS flag.

FILE_FLAG_OPEN_NO_RECALL

Indicates that the file data is requested, but it should continue to reside in remote storage. It should not be transported back to local storage. This flag is intended for use by remote storage systems or the Hierarchical Storage Management system.

▶hTemplateFile : 생성될 파일의 속성을 제공할 템플릿 파일이다. 95/98은 템플릿 파일을 지원하지 않으므로 반드시 NULL이어야 한다.

리턴

생성 또는 연 파일의 핸들을 리턴한다. 실패할 경우 INVALID_HANDLE_VALUE를 리턴하는데 이 값은 NULL과는 다르므로 NULL과 비교해서는 안된다. 즉 다음과 같은 에러 처리는 잘못된 것이므로 주의하기 바란다.

hFile=CreateFile(...
if (hFile == NULL) {
에러처리
}

이 함수를 출하기 전에 파일이 이미 존재하고 있었으면 GetLastError는 ERROR_ALREADY_EXISTS를 리턴한다.

설명

이 함수는 파일을 생성하는 가장 기본적인 함수이다. 그러나 이름과는 달리 파일을 생성하는 것뿐만 아니라 기존의 파일을 열 수도 있으며 파일 외에 다음과 같은 오브젝트를 생성하거나 열 수도 있다.

파이프
메일슬롯
COM 포트 등의 통신 장치
디스크 장치
테입 드라이브
콘솔
디렉토리

이 함수로 생성한 핸들은 반드시 CloseHandle로 닫아 주어야 한다.

예제 1

다음 예제는 파일을 생성하고 파일에 텍스트를 기록한다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	HANDLE hFile;
	DWORD dwWritten;
	LPCTSTR str=TEXT("테스트 파일입니다");

	switch(iMessage) {
	case WM_LBUTTONDOWN:
		hFile=CreateFile("c:\\TestFile.txt",GENERIC_WRITE,0,NULL,
			CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
		WriteFile(hFile,str,lstrlen(str),&dwWritten,NULL);
		CloseHandle(hFile);
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

C드라이브의 루트 디렉토리에 TestFile.txt 파일을 쓰기 액세스 권한으로 생성하였다. CREATE_ALWAYS 플래그를 주어 파일이 있을 경우 새로 만든다. 예제를 실행한 후 TestFile.txt 를 확인해 보면 문자열이 기록되어 있을 것이다.

참고함수

ReadFile : 파일로부터 데이터를 읽는다.
WriteFile : 파일에 데이터를 기록한다.
CloseHandle : 핸들을 닫는다.

플랫폼

95이상

참조

액세스 권한에 대한 상세한 내용은 39-2-사절을 참고하기 바란다.

API

#include <windows.h> /* 기본적인 데이터 타입, 함수 원형, 매크로 상수 정의 헤더파일 */

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPSTR lpszClass="TextOut";

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
    ,LPSTR lpszCmdParam,int nCmdShow) /* 윈도우즈 프로그램의 시작점은 Main이 아닌 WinMain이다. EP(Entry Point) */
    /* hInstance : 프로그램의 인스턴스 핸들이다. */
    /* hPrevInstance : 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들이다. 없을 경우는 NULL이 되며 Win32에서는 항상 NULL이다.
    16비트와의 호환성을 위해서만 존재하는 인수이므로 신경쓰지 않아도 된다. 역사가 오래되다 보니 어쩔 수 없이 생기는 일종의 찌꺼기이다. */
    /* lpszCmdParam : 명령행으로 입력된 프로그램 인수이다. 도스의 argv인수에 해당하며 보통 실행직후에 열 파일의 경로가 전달 된다. */
    /* nCmdShow : 프로그램이 실행될 형태이며 최소화, 보통 모양 등이 전달된다. */
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;
 
 WndClass.cbClsExtra=0; /* 일종의 예약 영역, 예약 영역을 사용하지 않을 경우 0으로 지정 */
 WndClass.cbWndExtra=0; /* 일종의 예약 영역, 예약 영역을 사용하지 않을 경우 0으로 지정 */
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); /* 윈도우의 배경 색상을 지정한다. */
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW); /* 마우스 커서 지정 */
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION); /* 아이콘 지정 */
 WndClass.hInstance=hInstance; /* 이 윈도우 클래스를 등록하는 프로그램 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입하면 된다.*/
 WndClass.lpfnWndProc=(WNDPROC)WndProc; /* 윈도우의 메시지 처리 함수 지정 */
 WndClass.lpszClassName=lpszClass; /*윈도우 클랙의 이름을 문자열로 정의한다. */
 WndClass.lpszMenuName=NULL; /* 이 프로그램이 사용할 메뉴를 지정한다. */
 WndClass.style=CS_HREDRAW | CS_VREDRAW; /* 윈도우의 스타일 정의 */
 RegisterClass(&WndClass);

 hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
    NULL,(HMENU)NULL,hInstance,NULL); /* CreateWindow : 윈도우 생성*/
 ShowWindow(hWnd,nCmdShow);
 
 while(GetMessage(&Message,0,0,0)) {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }
 return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;

 switch(iMessage) {
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  SetTextAlign(hdc, TA_CENTER);
  TextOut(hdc,200,60,TEXT("Beautiful Korea"), 15);
  //SetTextAlign(hdc, TA_CENTER);
  TextOut(hdc,200,80,TEXT("is My"), 5);
  TextOut(hdc,200,100,TEXT("Lovely Home Country"), 19);
  EndPaint(hWnd,&ps);
  return 0;
 }
 return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

출력 결과:




메시지를 처리하는 WndProc 함수 루틴이 조금 더 늘어난것뿐이 없습니다 ㅎㅎ

Uncover와 문자열 정렬방법에 대해서 공부하였습니다.

'[+] Information > [-] ETC' 카테고리의 다른 글

API GraphOut 예제  (0) 2009.07.20
API DrawText 예제  (0) 2009.07.18
API TextOut 예제  (0) 2009.07.18
첫번째 예제  (0) 2009.07.16
API 셋팅.  (0) 2009.07.16

+ Recent posts