반응형
경일게임아카데미 프로그래밍반 28기 14일차 수업과제 (2021. 04. 27)
오늘은 WIN32 API을 마우스를 활용하여 드래그 앤 드롭 기능을 제작해봅시다!
과제1 - 아이콘 드래그 앤 드롭
과제2 - 탐색기 창 각 끄트머리 잡고 드래그 앤 드롭
이하 과제 1.
#include "stdafx.h"
HINSTANCE _hInstance;
HWND _hWnd;
LPCTSTR _lpszClass = TEXT("경일 28기 이시영 :-) ");
void setWindowsSize(int x, int y, int width, int height);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int cmdShow)
{
_hInstance = hInstance;
MSG message;
WNDCLASS wndClass;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = (WNDPROC)WndProc;
wndClass.lpszClassName = WINNAME;
wndClass.lpszMenuName = NULL;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndClass);
_hWnd = CreateWindow(WINNAME, WINNAME, WS_OVERLAPPEDWINDOW, WINSTARTX, WINSTARTY, WINSIZEX, WINSIZEY, NULL, (HMENU)NULL, hInstance, NULL);
setWindowsSize(WINSTARTX, WINSTARTY, WINSIZEX, WINSIZEY);
ShowWindow(_hWnd, cmdShow);
while (GetMessage(&message, 0, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
POINT _ptMouse;
RECT _rc;
bool _flag = false;
int _disX = 0;
int _disY = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
char str[128];
switch (iMessage)
{
// 윈도우 창이 생성될때 딱 한번 호출되는 것
case WM_CREATE:
{
_rc = RectMakeCenter(WINSIZEX / 2, WINSIZEY / 2, 100, 100);
}
break;
// 그림을 그려주는 것
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
sprintf_s(str, "마우스 X : %d, 마우스 Y : %d", _ptMouse.x, _ptMouse.y);
TextOut(hdc, 20, 20, str, strlen(str));
Rectangle(hdc, _rc);
EndPaint(hWnd, &ps);
}
break;
// 마우스 움직이면 여기서 메시지 발생
case WM_MOUSEMOVE:
{
_ptMouse.x = LOWORD(lParam);
_ptMouse.y = HIWORD(lParam);
if (_flag == true)
{
_rc = RectMakeCenter(_ptMouse.x - _disX, _ptMouse.y - _disY, 100, 100);
}
InvalidateRect(_hWnd, NULL, true);
}
break;
// 마우스 왼쪽 클릭 (눌려지고 있을때 여기)
case WM_LBUTTONDOWN:
{
//마우스가 렉트안을 클릭했을 떄
//if (_rc.left < _ptMouse.x && _ptMouse.x < _rc.right &&
// _rc.top < _ptMouse.y && _ptMouse.y < _rc.bottom)
//{
// _flag = true;
// _disX = _ptMouse.x - (_rc.left + _rc.right) / 2;
// _disY = _ptMouse.y - (_rc.top + _rc.bottom) / 2;
//}
// 96번 라인과 같은 내용
if (PtInRect(&_rc, _ptMouse))
{
_flag = true;
_disX = _ptMouse.x - (_rc.left + _rc.right) / 2;
_disY = _ptMouse.y - (_rc.top + _rc.bottom) / 2;
}
}
break;
// 마우스 왼쪽 눌렀다 뗏을 때
case WM_LBUTTONUP:
{
_flag = false;
}
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_ESCAPE:
{
PostQuitMessage(0);
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}
void setWindowsSize(int x, int y, int width, int height)
{
RECT winRect;
winRect.left = 0;
winRect.top = 0;
winRect.right = width;
winRect.bottom = height;
AdjustWindowRect(&winRect, WINSTYLE, false);
SetWindowPos(_hWnd, NULL, x, y, (winRect.right - winRect.left), (winRect.bottom - winRect.top), SWP_NOZORDER | SWP_NOMOVE);
}
어떻게 구현해야 할까?
마우스 왼쪽 버튼이 눌리면(LBUTTONDOWN) 그 위치에 있는 대상과 위치를 검사하여, 왼쪽 버튼이 눌려 있는 부분이 대상의 위치와 일치 한다면, 플래그를 On(true)시킨다.
마우스가 움직였을 때(MOUSEMOVE) 플래그의 상태가 On(true)라면 마우스의 x,y 위치를 대상의 x,y에 대입하면 된다.
그 후 왼쪽 버튼이 손에서 떨어지면(LBUTTONUP) 플래그를 Off(false)로 변경한다.
로직은?
1.사각형의 중점과 마우스 클릭한 좌표와의 x,y 거리를 구한다
2.마우스가 움직일때마다 사각형의 중점을 1에서 구한 x,y거리가 유지되도록 옮긴다
결과화면 & 심화학습
마우스가 윈도우 화면 바깥으로 나가지 않게 해보자
반응형
'학원 > 경일게임아카데미' 카테고리의 다른 글
23. 열다섯번째 수업 (0) | 2022.12.26 |
---|---|
22. 열네번째 수업과제 [윈도우 탐색기 구현] (1) | 2022.12.23 |
20. 열네번째 수업 (0) | 2022.12.22 |
19. 열세번째 수업과제 [사각형 밀기] (0) | 2022.12.22 |
18. 열세번째 수업 (0) | 2022.12.22 |