#include <windows.h>
// WinMain 함수에서참조하므로함수원형을선언한다.
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
// winmain 에는가지특성을지님
// 1. 윈도우클래스를초기화및등록
// 2. 윈도우클래스참조해서윈도우만들고출력
// 3. 윈도우가끝나면안되니깐메시지루프
{
WNDCLASS wndclass;
HWND hwnd;
MSG msg;
/***** 1단계*******/
// 윈도우클래스를초기화하고운영체제에등록한다.
// 윈도우클래스는구조체로필드는10개이다.
wndclass.style = CS_HREDRAW | CS_VREDRAW; // 스타일지정
// CS_HREDRAW | CS_VREDRAW bit or 연산이스타일에들어간다.
// CS_F1 = 0001 (1)
// CS_F2 = 0010 (2)
// Cs_F1 | CS_F2 = 0011 (3) 서로중복안되게비트중복이되지않아서OR연산을한다.
// 32비트32개를가질수있다.
// 이값을변경하려면무엇을찻아야하는가?? MSDN 사이트
// CS_HREDRAW -> Horzontal(수평) 윈도우크기변경시WM_PAINT 발생
// CS_VREDRAW -> Vertical
// 추가메시지발생여부를정의한다.
wndclass.lpfnWndProc = WndProc; // 윈도우프로시저이름
// 윈도우상에서메시지가발생하면이걸로처리한다.
// 디스패치함수안에서이것이호출된다.
// long point 함수이름을넘겨준다.
/*
이런트리형을가진다, 같은윈도우를가질수있다.
인스턴스▼
윈도우클래스- 윈도우프로시져
윈도우 윈도우
윈도우에서발생하는메시지는각상위의윈도우프로시져에서참조한다.
*/
wndclass.cbClsExtra = 0; // 여분메모리(0바이트)
wndclass.cbWndExtra = 0; // 여분메모리(0바이트)
// 이것을빼버리면쓰레기값들어가니0으로반드시
wndclass.hInstance = hInstance; // 인스턴스핸들
// 어플리케이션을대표하는핸들러
// HINSTANCE / HWND / HMENU/ HDC
// 핸들: 시스템관리자원에대한식별자.
// 메모리에로드된시작주소이다.
// 식별자!= 아이디
// 아이디는개발자가이용하기위해서정의하는것이다.
// 식별자는시스템자체에서정의하는것이다. 사용자는단지빌려옴
// HINSTANCE 프로그램코드의시작주소이다.
// IE8처럼하나의아이콘으로여러창을띄울수있는데
// HINSTANCE hPrevInstance 이것을가지고조정이가능하다.
// 이미창이있으면실행안되거나, 혹은가능하도록
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 아이콘모양
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // 커서모양
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); // 배경(흰색)
wndclass.lpszMenuName = NULL; // 메뉴(NULL->메뉴없음)
// ▲이4가지는같은클래스를쓰면모두같아진다.
// IDI_APPLICATION , IDC_ARROW등은툴에서값을준것이다.-> 상수
wndclass.lpszClassName = "HelloClass"; // 윈도우클래스이름
// 윈도우의이름을적용한것이다.
// 윈도우만들때처음인자를참조할때쓴다.
//CreateWindow("HelloClass", "HelloSDK", WS_OVERLAPPEDWINDOW,
if(!RegisterClass(&wndclass)) return 1;
/***** 2단계*******/
// 윈도우를생성하고화면에보이게한다.
hwnd = CreateWindow("HelloClass", "HelloSDK", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
// 메모리상에윈도우를로드하는것이다. 아직출력은아님
// ▽이런것시험나온다. 바탕화면은클래스에서변경
// HellowSDK : 타이틀바에나타나는것이다. 다다르므로직접만들때변경
// WS_OVERLAPPEDWINDOW : WindowStyle의준말자주쓰는스타일을정의해둔것.
// CW_USEDEFAULT, CW_USEDEFAULT 2개는나타나는위치를
// CW_USEDEFAULT, CW_USEDEFAULT 가로세로크기를조정하는것.
ShowWindow(hwnd, nCmdShow);
// 윈도우를보이기위해서사용
/***** 3단계*******/
// 메시지큐에서메시지를하나씩꺼내서처리한다.
while(GetMessage(&msg, NULL, 0, 0) > 0){
// 언제끝이나는가?? GetMessage의반환값이이하일경우종료
// 그래서언제끝나냐고??
// GetMessage 함수는메시지큐에서가져옴반환값음정수
// WM_QUIT 를가져오면을리턴한다.= > 메시지루프종료-> 프로그램종료
// 그럼QUIT 메시지가언제발생하는가????
// x 버튼( 종료버튼) 을누르면WM_DESTROY 호출
// 하지만윈도우만끄는것이지, 프로세스는종료되지않는다.
//case WM_DESTROY:
// PostQuitMessage(0); 여기서QUIT 를호출하는것이다.
TranslateMessage(&msg); // 키보드메세지를해석한다.
DispatchMessage(&msg);
// 콜백합수이다. --> 시스템에서 호출하는 함수.
// wndclass.lpfnWndProc = WndProc; 이것을가져와서처리한다.
}
// winmain이끝나면윈도우창이사라진다. 그럼윈도우의미가없다.
// 그래서위처럼메시지를무한루프돌린다.
// 3개의메시지큐중에서처리하는하는것을말한다.
// 메시지없다면대기
// GetMessage -> 응용프로그램메시지큐에서메시지를가져온다.
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
핸들이랑 id 는?
핸들은 자원을 식별하기 위한 식별값이다.
Id랑 차이는? 사용자가 지정하는 값이다.
핸들은 내가 지정하는 것이 아니라 시스템에서 컨트롤 하는 값이다.
*/
{
// 여기서서는메시지처리한후에다시디스패치함수로반환된다....
// 메시지가없다면대기모드로간다.
// -> 동기화함수이다: 메시지가없다면대기하는것.-> 다른프로세스에양도를한다.
HDC hdc;
PAINTSTRUCT ps;
char *str = "Hello, SDK";
// 발생한메시지의종류에따라적절히처리한다.
switch(message){
메시지 별로 처리하는 핸들러를
메시지 핸들러라고 칭한다.
-> 윈도우 프로그래밍의 기본 포맷. 메시지 별로 처리.
mfc는 별도의 멤버 함수로 -> onpaint();
*/
case WM_CREATE:
return 0;
case WM_LBUTTONDOWN:
MessageBox(hwnd, "마우스를클릭했습니다.", "마우스메시지", MB_OK);
return 0;
// 다시 그려야 할때 호출된다. 창을 내리거나 올리고 등등
// 무효화 시키는 것 invalidate();
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 100, 100, str, lstrlen(str));
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY: // x버튼(종료버튼) 누르면윈도우창은파괴하지만프로세스는그대로
PostQuitMessage(0);
// 프로세스를죽이는것은여기서발생한다.
// PostQuitMessage(0); 라는API함수를호출해야지...
return 0;
}
// 응용프로그램이처리하지않은메시지는운영체제가처리한다.
return DefWindowProc(hwnd, message, wParam, lParam);
}