1장 시작하기 ¶
API공부 세가지 조건
- MicrosoftWindows 구성 알기
- CLanguage를 알아야 한다.
- Windows 프로그래밍에 적합한 32bit C 컴파일러와 개발 환경이 설치되어 있어야 한다.
3장 Windows와 메시지 ¶
#include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("HelloWin"); HWND hWnd; MSG msg; WNDCLASS wndClass; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = szAppName; if(!RegisterClass(&wndClass)) // 1. 윈도우 클래스 등록 { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hWnd = CreateWindow(szAppName, // 2. 윈도우 생성 TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, iCmdShow); // 3. 윈도우를 보여준다 UpdateWindow(hWnd); // 4. 윈도우 갱신 while(GetMessage(&msg, NULL, 0, 0)) // 5. 메세지를 받는다 { TranslateMessage(&msg); // 6. 키보드 메시지를 번역 DispatchMessage(&msg); // 7. 윈도우 프로시저에 메시지를 보낸다. } // 8. 5,6,7 반복 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch(message) { case WM_CREATE: return 0; case WM_PAINT: hdc = BeginPaint(hWnd,&ps); TextOut(hdc,100,100,"Hello, Windows!",15); EndPaint(hWnd,&ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); }
- 함수들을 순서대로 나열해 보았다.
RegisterClass(); // 1. 윈도우 클래스 등록 CreateWindow(); // 2. 윈도우 생성 ShowWindow(hWnd, iCmdShow); // 3. 윈도우를 보여준다 UpdateWindow(hWnd); // 4. 윈도우 갱신 GetMessage() // 5. 메세지를 받는다 TranslateMessage(&msg); // 6. 키보드 메시지를 번역 DispatchMessage(&msg); // 7. 윈도우 프로시저에 메시지를 보낸다.
- 윈도우 클래스
하나 이상의 윈도우가 하나의 윈도우 클래스를 기반으로 생성될 수 있다. 예를 들어 모든 단추 윈도우는 동일한 윈도우 클래스를 기반으로 하여 생성된다.
typedef struct { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCSTR lpszMenu; LPCSTR lpszClassName; }WNDCLASS, *PWNDCLASS;
- 윈도우 생성하기
- 메시지 루프
while(GetMessage(&msg, NULL, 0, 0)) // 5. 메세지를 받는다 { TranslateMessage(&msg); // 6. 키보드 메시지를 번역 DispatchMessage(&msg); // 7. 윈도우 프로시저에 메시지를 보낸다. } // 8. 5,6,7 반복
Windows는 현재 Windows에서 실행되고 있는 각각의 Windows 프로그램에 대해 메시지 큐를 유지한다.
- 메시지
typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; }
- 윈도우 프로시저(를 호출하는 WIndows)
- 메시지 큐 (message queue)
큐에 저장되지 않는 메시지는 윈도우에 의한 윈도우 프로시저에 대한 직접적인 호출의 결과이다.
- CreateWindow를 호출할때 윈도우 프로시저에게 WM_CREATE 메시지를 보낸다.
- ShowWindow를 호출할 때 윈도우 프로시저에게 WM_SIZE, WM_SHOWWINDOW 메시지를 보낸다.
- UpdateWindow를 호출할 때 윈도우 프로시저에게 WM_PAINT 메시지를 보낸다.
4장 문자출력 ¶
- 클라이언트 영역 - 프로그램이 자유로이 그릴 수 있고 사용자에게 시각적인 정보를 제공 해 주는 윈도우 한 부분이다.
- 장치독립적 프로그래밍 - 출력 장치와 상관없이(출력 장치의 시스템 메카니즘을 모르고도) GDI 통하여 프로그래밍 한다.
- 문자 모드환경 - 프로그램 출력은 그대로 유지되고, 갑작스럽게 사라지지도 않을 것이다. 따라서 프로그램은 표시된 화면을 다시 그리기 위한 정보를 버릴 수 있다.
- 그래픽 모드환경 - 윈도우 창이 다른 창에 의해 지워 질 수 가 있다. 이 처럼 정보가 손실되므로 정보를 출력 정보는 저장하여야 한다.
- 사용자가 윈도우를 옮기거나 제거했을 때 이전에 감추어졌던 윈도우 영역이 보이게 될때
- 사용자가 윈도우의 크기를 조정했을 때
- 프로그램이 클라이언트 영역의 일부를 스크롤 하기 위해 ScrollWindow나 ScrollDC함수를 사용하는 경우
- 프로그램이 InvalidateRect나 InvalidateRgn함수를 사용하여 WM_PAINT메시지를 생성할 때
- Windows가 윈도우의 일부가 겹친 대화상자나 메시지 상자를 제거할 때
- 메뉴가 나타났다가 사라질 때
- 풍선 도움말이 나타났을 때
- 마우스커서가 클라이언트 영역을 지나갈 때
- 아이콘이 클라이언트 영역을 지나서 드래그 될 때
- 무효영역(Invalid region) - 다시그리기위한 영역. 대화상자가 제거되었을 때 대화상자가 있던 영역만 복원
- InvalidateRect함수 - 자기자신의 클라이언트 영역에서 사각형을 무효로 만들 수 있다.
hdc(handle to a device context) : 모든 GDI함수의 첫 인자
장치 컨텍스트 ¶
- 핸들은 단순히 Windows가 내부적으로 개체를 참조하는 데 사용하는 번호라는 것을 기억할 것이다.
- 장치 컨텍스트 핸들은 GDI함수들에 대한 윈도우의 패스포트이다.
- GDI에 의해 내부적으로 관리되는 데이터 구조체이다.
- 비디오 디스플레이나 프린터 같은 특정 디스플레이 장치와 연결되어 있다.
방법1. WM_PAINT 메시지를 처리할 때 이 방법 사용.
case WM_PAIN: hdc = BeginPaint(hwnd,&ps); //GDI 함수사용 EndPaint(hwnd,&ps); return 0;방법2. WM_PAINT이외의 다른 메시지, 장치 컨텍스트에 대한 정보를 얻는 등의 다른 목적으로.
hdc = GetDC(hwnd); //GDI 함수사용 ReleaseDC(hwnd, hdc);
스크롤 바 ¶
iBar SB_VERT or SB_HORZ
iMin,iMax 최소,최대
bRedraw true : Windows가 새로운 범위를 바탕으로 스크롤 바를 다시 그리기 원하면
iMin,iMax 최소,최대
bRedraw true : Windows가 새로운 범위를 바탕으로 스크롤 바를 다시 그리기 원하면
Windows의 책임 영역
GetScrollInfo(hwnd, iBar, &si);
- 스크롤 바에 대한 모든 마우스 메시지를 처리한다.
- 사용자가 클릭했을 때 반전된 화면을 제공한다.
- 범위 내에서 사용자가 막대를 이동시킬 때 막대를 이동시킨다.
- 스크롤 바 메시지를 스크롤 바를 포함하고 있는 윈도우의 윈도우 프로시저에 전달한다.
- 스크롤 바의 범위와 위치를 초기화한다.
- 윈도우 프로시저에 대한 스크롤 바 메시지를 처리한다.
- 막대의 위치를 업데이트 한다.
- 스크롤 바의 변화에 대하여 클라이언트 영역을 변경시킨다.
GetScrollInfo(hwnd, iBar, &si);
typedef struct tagSCROLLINFO
{
{
UINT cbSize;
UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
}UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
si.cbSize = sizeof(SCROLLINFO);
si.cbMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = NUMLINES - 1;
si.nPage = cyClient / cyChar;
SetScrollInfo(hwnd,SB_VERT, &si, TRUE);
si.cbMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = NUMLINES - 1;
si.nPage = cyClient / cyChar;
SetScrollInfo(hwnd,SB_VERT, &si, TRUE);
SIF_RANGE nMin,nMax(스크롤 바 범위) 설정
SIF_PAGE nPage(페이지 크기) 설정
SIF_PAGE nPage(페이지 크기) 설정
GDI철학 ¶
GDI32.DLL 이런 동적 링크 라이브러리는 설정되어 있는 비디오 출력이나 프린터의 장치 드라이버에 있는 루틴들을 호출한다. 비디오 드라이버는 비디오 출력 하드웨어를 엑세스하며 프린터 드라이버는 GDI 명령을 각각의 프린터가 이해할 수 있는 코드나 명령으로 변환한다.
GDI의 주된 목적 중의 하나는 장치에 구애 받지 않고 그랙픽을 지원하는 것이다. 다른 종류의 출력 장치에 대한 독특한 특성들로부터 프로그램을 분리시킴으로써 이런 목적을 완수한다.
GDI의 주된 목적 중의 하나는 장치에 구애 받지 않고 그랙픽을 지원하는 것이다. 다른 종류의 출력 장치에 대한 독특한 특성들로부터 프로그램을 분리시킴으로써 이런 목적을 완수한다.
- 가상 좌표계 - 하드웨어에 구애받지 않게
- 장치 좌표계 - 하드웨어에 더욱 밀접
- 장치 컨텍스트를 얻고(혹은 생성하고) 해제(혹은 소멸시키는)하는 함수들
- 장치 컨텍스트에 대한 정보를 획득하는 함수들
- 무엇인가를 그리는 함수들
- 장치컨텍스트의 속성을 설정하고 얻어내는 함수들
- GDI개체를 다루는 함수들
다른 것들 : 매핑 모드와 transform, 메타 파일, 영역, 경로, 클리핑, 팔레트, 인쇄
장치컨텍스트 : 화면이나 프린터 같은 그래픽 출력 장치에 그리고자 할 때에는 반드시 먼저 장치 컨텍스트에 대한 핸들을 얻어야 한다. 프로그램에 이 핸들을 주는 것으로 Windows는 사용자가 그 장치를 사용할 수 있도록 허가해 준다.
장치 컨텍스트에 대한 핸들을 얻어내는 보다 더 일반적인 함수
CreateDC(pszDriver, pszDevice, pszOutput, pData);
hdc = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL); //예) 전체 출력에 장치 컨텍스트 핸들
CreateDC(pszDriver, pszDevice, pszOutput, pData);
hdc = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL); //예) 전체 출력에 장치 컨텍스트 핸들
그리지는 않고 단지 장치 컨텍스트에 대한 정보만을 필요할 때도 있다.
CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL); //예) 전체 출력에 장치 컨텍스트 핸들
CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL); //예) 전체 출력에 장치 컨텍스트 핸들