윈도우창 생성
![]() |
위 텍스트 파일을 c++소스에 넣으면 옆과 같은 윈도우 어플리케이션 창이 만들어진다. 이 번 학기의 목표는 한글같이 키보드를 마우스를 누르면 반응하는 프로그램을 만드는게 목표이다. |
원도우 프로그램의 소스
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("Class");
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
, LPSTR lpszCmdParam, int nCmdShow) //이 부분은 차후 수업에서 알아 보겠다
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = 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);
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&Message, NULL, 0, 0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
//당분간은 이 함수를 설명한다.
{
HDC hdc;
PAINTSTRUCT ps;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
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));
}
WinMain 함수는 나중에 나중에 배워보도록 하고 당분간 수업에서는 WndProc함수에 대해 본다.
사각형을 그리는 WndProc함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
//당분간은 이 함수를 설명한다.
{
HDC hdc;
PAINTSTRUCT ps;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
hdc=GetDC(hwnd);
Rectangle(hdc, 10, 10, 60, 60)// 사각형을 그려라
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));
}
마우스 오른쪽 버튼을 눌렀을 때 사각형을 그리도록 바꾼 WndProc함수이다.
Rectangle(hdc, 좌, 상 ,우, 하)이다
누르는 지점에 파란색 사각형을 그리는 WndProc함수
int px[1000], py[1000]; //도형의 좌표를 기억하는 변수
int iCount; //사각형의 갯수를 저장하는 변수
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int x, y;
HBRUSH hBrush;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
hdc = GetDC(hWnd); //원도우 그리기 도구 상자 얻기
px[iCount] = x = LOWORD(lParam);
py[iCount] = y = HIWORD(lParam);
iCount++;
hBrush = CreateSolidBrush(RGB(0, 0, 255));//도형의 색을 선택
SelectObject(hdc, hBrush); // 그리기 도구 hdc의 색을 지정
Rectangle(hdc, x-10, y-10, x+60, y+60);// 사각형을 그려라
return 0;
case WM_PAINT: //최소화하고 다시 그려진다
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < iCount; i++)//iCount(도형의 갯수 만큼 반복해서 그림)
{
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
Rectangle(hdc, px[i] - 10, py[i] - 10, px[i] + 60, py[i] + 60);
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
마우스 왼쪽버튼을 누르면 px배열에 클릭한 위치의 좌표가 저장된다. iCount를 통해 다음 배열에 저장
LOWORD=x의 좌표를 HIWORD=y좌표를 두 매크로를 통해 좌표값을 받아올 수 있다.
iCount가 증가하면서 다음 배열에 클릭 횟수를 추가한다.
HBRUSH 면을 채울 때 사용하는 GDI오브젝트 차후 수업에서 자세하게 다룬다. 여기서는 파란색으로 설정되었다.
SelcetObject 함수를 통해 hdc그리기 도구의 면 색을 hBrush로 설정해준다.
윈도우창을 최소화하면 그려진 사각형들이 다 사라지는데 이걸 다시 그려주는 매크로가 WM_PAINT이다.
0부터 도형의 갯수만큼 반복해서 도형을 다시 그린다.
※ 변수 명명법
접두어 | 원래말 | 의미 |
cb | Count of Byte | 바이트 수 |
dw | double word | 부호없는 long형 정수 |
h | handle | 윈도우, 비트맵, 파일 등의 핸들 |
sz | Null Terminated | NULL 종료 문자열 |
ch | Character | 문자형 |
a | Array | 배열 |
w | Word | 부호없는 정수형 |
i | lnteger | 정수형 |
p, lp | long pointer | 포인터형 |
b | Bool | 논리형 |
윈도우즈 프로그래밍에서 변수에 주로 이름을 붙이는 방법이다. 꼭 이 방식으로 변수를 만들필요는 없지만 표준 함수들은 모두 이 방식대로 인수 이름을 작성하므로 접두어들을 외우고 있으면 함수의 인수가 어떤의미를 가지는 파악하기 쉽다.
과제
오른쪽 클릭시 파란원 / 왼쪽 클릭시 빨간원을 만드는 프로그램
최소화 했을하고 다시 띄웠을때도 파란원과 빨간원이 그대로 있어야 한다.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("Class");
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = 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);
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&Message, NULL, 0, 0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
int px[1000], py[1000];//빨간원 좌표
int px2[1000], py2[1000];//파란원 좌표
int iCount_Red = 0;//빨간원 갯수
int iCount_Blue = 0;//파란원 갯수
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int x, y;
HBRUSH hBrush;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
hdc = GetDC(hWnd);
px[iCount_Red] = x = LOWORD(lParam);
py[iCount_Red] = y = HIWORD(lParam);
iCount_Red++;
hBrush = CreateSolidBrush(RGB(255, 0, 0));
SelectObject(hdc, hBrush);
Ellipse(hdc, x - 10, y - 10, x + 10, y + 10);
return 0;
case WM_RBUTTONDOWN: //오른쪽버튼을 누르면
hdc = GetDC(hWnd);
px2[iCount_Blue] = x = LOWORD(lParam);
py2[iCount_Blue] = y = HIWORD(lParam);
iCount_Blue++;
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
Ellipse(hdc, x - 10, y - 10, x + 10, y + 10);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < iCount_Blue; i++)
{
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
Ellipse(hdc, px2[i] - 10, py2[i] - 10, px2[i] + 10, py2[i] + 10);
}
for (int i = 0; i < iCount_Red; i++)
{
hBrush = CreateSolidBrush(RGB(255, 0, 0));
SelectObject(hdc, hBrush);
Ellipse(hdc, px[i] - 10, py[i] - 10, px[i] + 10, py[i] + 10);
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
오른쪽클릭시 생성되는 원과 왼쪽클릭시 생성되는 원에 저장되는 좌표와 갯수를 세는 변수를 다르게 해서 구현했다.
원이 2가지 밖에 없어 이런방법으로 접근해도 되지만 여러가지의 원이 있을 때도 초기화되지 않는 방법을 생각해봐야겠다.
'학교수업 > 윈도우즈 프로그래밍' 카테고리의 다른 글
6주차 - 컨트롤 / 버튼 / 라디오 버튼 /리스트 박스, 콤보 박스 컨트롤 (0) | 2021.01.26 |
---|---|
5주차 - 펜 스타일 지정 /oldPen/ 선하나 지우기/리소스 메뉴 (0) | 2021.01.25 |
4주차 - KeyDown / static 변수 / UINCODE&MultiByte /선그리기 (0) | 2021.01.24 |
3주차 - 복습 / struct와 class로 1, 2주차 프로그램 만들기 (0) | 2021.01.21 |
2주차 - Debugging / DC / 문자열 출력 / 키보드 입력 (0) | 2021.01.21 |