Presentation is loading. Please wait.

Presentation is loading. Please wait.

6. 마우스.

Similar presentations


Presentation on theme: "6. 마우스."— Presentation transcript:

1 6. 마우스

2 1. 마우스의 기본 마우스의 존재여부 확인 마우스 단추의 개수 알아내기
fMouse = GetSystemMetrics(SM_MOUSEPRESENT); 마우스가 설치되어 있다면 TRUE, 설치되어 있지 않다면 FALSE 마우스 단추의 개수 알아내기 cButtons = GetSystemMetrics(SM_CMOUSEBUTTONS); 마우스가 설치되어 있지 않다면 0을 Return한다. Windows는 몇 가지의 미리 정의된 마우스 커서를 가지고 있다. IDC_ARROW,IDC_CROSS,IDC_WAIT wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);

3 2. 클라이언트 영역 마우스 메시지 윈도우 프로시저는 윈도우 클래스에 더블 클릭 메시지를 받도록 미리 정의된 경우만 DBCLICK메시지를 받는다. 마우스의 모든 메시지에는 lParam값에 마우스의 위치를 담고 있다. x = LOWORD(lParam); y = HIWORD(lParam); wParam에는 마우스 단추와 Shift키 및 Ctrl키의 상태를 나타낸다. MK_LBUTTON 왼쪽 단추가 눌린 상태 MK_MBUTTON 중간 단추가 눌린 상태 MK_RBUTTON 오른쪽 단추가 눌린 상태 MK_SHIFT Shift가 눌린 상태 MK_CONTROL Control키가 눌린 상태 wParam & MK_SHIFT값이 TRUE이면 SHIFT키가 눌린 상태를 나타냄 MK_LBUTTON 왼쪽 단추를 누른 상태 MK_MBUTTON 중간 단추를 누른 상태 MK_RBUTTON 오른쪽 단추를 누른 상태 MK_SHIFT SHIFT키를 누른 상태 MK_CONTROL Control키를 누른 상태 윈도우의 클라이언트 영역 밖에 있을 때에도 계속 마우스의 메시지를 받을 수 있다. 만약 시스템 메시지 상자나 대화상자가 나타나 있으면, 다른 어떤 프로그램도 마우스 메시지를 받을 수 없다.

4 /*--------------------------------------------------
CONNECT.C -- Connect-the-Dots Mouse Demo Program (c) Charles Petzold, 1998 */ #include <windows.h> #define MAXPOINTS 1000 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Connect") ; 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)) MessageBox (NULL, TEXT ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Connect-the-Points Mouse Demo"), WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ;

5 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ static POINT pt[MAXPOINTS] ; static int iCount ; HDC hdc ; int i, j ; PAINTSTRUCT ps ; switch (message) case WM_LBUTTONDOWN: iCount = 0 ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case WM_MOUSEMOVE: if (wParam & MK_LBUTTON && iCount < 1000) pt[iCount ].x = LOWORD (lParam) ; pt[iCount++].y = HIWORD (lParam) ; hdc = GetDC (hwnd) ; SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0) ; ReleaseDC (hwnd, hdc) ; } case WM_LBUTTONUP: InvalidateRect (hwnd, NULL, FALSE) ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; for (i = 0 ; i < iCount - 1 ; i++) for (j = i + 1 ; j < iCount ; j++) MoveToEx (hdc, pt[i].x, pt[i].y, NULL) ; LineTo (hdc, pt[j].x, pt[j].y) ; ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; EndPaint (hwnd, &ps) ; case WM_DESTROY: PostQuitMessage (0) ; return DefWindowProc (hwnd, message, wParam, lParam) ;

6 2. Shift Key처리 if (wParam & MK_SHIFT) { if (wParam & MK_CONTROL)
[Shift와 Ctrl 키 눌린 상태] } else [Shift 키 눌린 상태] [Ctrl key 눌린 상태] [ Shift key와 Ctrl키가 눌리지 않음]

7 3. 마우스 더블 클릭 윈도우가 더블 클릭을 받기를 원하면 CS_DBCLKS를 지정하지 않으면 CS_DBCLKS를 지정하면
wndclass.style=CS_HREDRAW|CS_VREDRAW|CS_DBCLKS; CS_DBCLKS를 지정하지 않으면 WM_LBUTTONDOWN WM_LBUTTONUP CS_DBCLKS를 지정하면 WM_LBUTTONDBCLK

8 4. 비 클라이언트 영역 마우스 메시지 윈도우에서 비클라이언트 영역은 제목표시줄, 메뉴, 윈도우 스크롤바를 포함한다.
비클라이언트 영역을 표시하기 위하여 ‘NC’를 포함하고 있다. WM_NCLBUTTONDOWN, WM_NCRBUTTONDOWN wParam 마우스가 움직이거나 클릭된 비클라이언트 영역을 나타낸다. lParam 화면상의 좌표 화면상의 좌표를 클라이언트 좌표로 ScreenToClient(hwnd,&pt); 클라이언트 좌표를 화면상의 좌표로 ClientToScreen(hwnd,&pt);

9 5. Hit-Test메시지 비클라이언트 ‘hit-test’를 나타내는 WM_NCHITTEST 메시지
이 메시지는 다른 모든 클라이언트 영역과 비 클라이언트 영역 마우스 메시지에 우선한다. lParam 마우스의 화면좌표 wParam 사용하지 않는다. 일반적으로 Windows응용 프로그램은 이 메시지를 DefWindowProc에 전달한다. 윈도우는 이것을 바탕으로 다른 모든 마우스 메시지를 생성한다. WM_NCHITTEST가 처리 될 때 DefWindowProc에서 반환된 값은 마우스 메시지의 wParam매개 변수가 된다. DefWindowProc이 WM_NCHITTEST를 처리한 후 HTCLIENT를 반환하면 Windows는 화면 좌표를 클라이언트 영역 좌표로 변환하고 클라이언트 영역 마우스 메시지를 생성한다. HTCLIENT 클라이언트 영역 HTNOWHERE 창에서 눌리지 않음 HTTRANSPARENT 다른 윈도우에 의해 덮여있는 윈도우 HTERROR DefWindowProc에 의해 소리 발생 case WM_NCHITTEST: return (LRESULT)HTCAPTION;

10 6. 메시지를 생성하는 메시지 시스템 메뉴 아이콘 더블 클릭 WM_NCLBUTTONDBLCLK WM_SYSCOMMAND
WM_HITTEST DefWindowProc은 HTSYSMENU의 값을 반환 WM_NCLBUTTONDBLCLK wParam => HTSYSMENU DefWindowProc에 전달 DefWindowProc이 받으면 WM_SYSCOMMAND wParam =>SC_CLOSE WM_CLOSE메시지를 발생 DestroyWindow()함수 호출 WM_DESTROY메시지 발생 PostQuitMessage(0) WM_QUIT메시지 발생

11 #include <windows.h>
#define DIVISIONS 5 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Checker2") ; 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)) MessageBox (NULL, TEXT ("Program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Checker2 Mouse Hit-Test Demo"),WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ;

12 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ static BOOL fState[DIVISIONS][DIVISIONS] ; static int cxBlock, cyBlock ; HDC hdc ; int x, y ; PAINTSTRUCT ps ; POINT point ; RECT rect ; switch (message) case WM_SIZE : cxBlock = LOWORD (lParam) / DIVISIONS ; cyBlock = HIWORD (lParam) / DIVISIONS ; return 0 ; case WM_SETFOCUS : ShowCursor (TRUE) ; return 0 ; case WM_KILLFOCUS : ShowCursor (FALSE) return 0 ; case WM_KEYDOWN : GetCursorPos (&point) ; ScreenToClient (hwnd, &point) ; x = max (0, min (DIVISIONS - 1, point.x / cxBlock)) ; y = max (0, min (DIVISIONS - 1, point.y / cyBlock)) ; switch (wParam) case VK_UP : y-- ; break ; case VK_DOWN : y++ ; break ; case VK_LEFT : x-- ; break ; case VK_RIGHT : x++ ; break ; case VK_HOME : x = y = 0 ; break ; case VK_END : x = y = DIVISIONS - 1 ; break ; case VK_RETURN : case VK_SPACE : SendMessage (hwnd, WM_LBUTTONDOWN, MK_LBUTTON,MAKELONG (x * cxBlock, y * cyBlock)) ; break ; } x = (x + DIVISIONS) % DIVISIONS ; y = (y + DIVISIONS) % DIVISIONS ; point.x = x * cxBlock + cxBlock / 2 ; point.y = y * cyBlock + cyBlock / 2 ; ClientToScreen (hwnd, &point) ; SetCursorPos (point.x, point.y) ; return 0 ;

13 case WM_LBUTTONDOWN : x = LOWORD (lParam) / cxBlock ; y = HIWORD (lParam) / cyBlock ; if (x < DIVISIONS && y < DIVISIONS) { fState[x][y] ^= 1 ; rect.left = x * cxBlock ; rect.top = y * cyBlock ; rect.right = (x + 1) * cxBlock ; rect.bottom = (y + 1) * cyBlock ; InvalidateRect (hwnd, &rect, FALSE) ; } else MessageBeep (0) ; return 0 ; case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; for (x = 0 ; x < DIVISIONS ; x++) for (y = 0 ; y < DIVISIONS ; y++) Rectangle (hdc, x * cxBlock, y * cyBlock,(x + 1) * cxBlock, (y + 1) * cyBlock) ; if (fState [x][y]) MoveToEx (hdc, x *cxBlock, y *cyBlock, NULL) ; LineTo (hdc, (x+1)*cxBlock, (y+1)*cyBlock) ; MoveToEx (hdc, x *cxBlock, (y+1)*cyBlock, NULL) ; LineTo (hdc, (x+1)*cxBlock, y *cyBlock) ; EndPaint (hwnd, &ps) ; case WM_DESTROY : PostQuitMessage (0) ; return DefWindowProc (hwnd, message, wParam, lParam) ;

14 /*-------------------------------------------------
CHECKER3.C -- Mouse Hit-Test Demo Program No. 3 (c) Charles Petzold, 1998 */ #include <windows.h> #define DIVISIONS 5 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ; TCHAR szChildClass[] = TEXT ("Checker3_Child") ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Checker3") ; 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)) MessageBox (NULL, TEXT ("Program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } wndclass.lpfnWndProc = ChildWndProc ; wndclass.cbWndExtra = sizeof (long) ; wndclass.hIcon = NULL ; wndclass.lpszClassName = szChildClass ; RegisterClass (&wndclass) ; hwnd = CreateWindow (szAppName, TEXT ("Checker3 Mouse Hit-Test Demo"),WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ;

15 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ static HWND hwndChild[DIVISIONS][DIVISIONS] ; int cxBlock, cyBlock, x, y ; switch (message) case WM_CREATE : for (x = 0 ; x < DIVISIONS ; x++) for (y = 0 ; y < DIVISIONS ; y++) hwndChild[x][y] = CreateWindow (szChildClass, NULL,WS_CHILDWINDOW | WS_VISIBLE, 0, 0, 0, 0, hwnd, (HMENU) (y << 8 | x), (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE), NULL) ; return 0 ; case WM_SIZE : cxBlock = LOWORD (lParam) / DIVISIONS ; cyBlock = HIWORD (lParam) / DIVISIONS ; MoveWindow (hwndChild[x][y],x * cxBlock, y * cyBlock,cxBlock, cyBlock, TRUE) ; case WM_LBUTTONDOWN : MessageBeep (0) ; case WM_DESTROY : PostQuitMessage (0) ; } return DefWindowProc (hwnd, message, wParam, lParam) ;

16 LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam)
{ HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) case WM_CREATE : SetWindowLong (hwnd, 0, 0) ; // on/off flag return 0 ; case WM_LBUTTONDOWN : SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ; InvalidateRect (hwnd, NULL, FALSE) ; case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; Rectangle (hdc, 0, 0, rect.right, rect.bottom) ; if (GetWindowLong (hwnd, 0)) MoveToEx (hdc, 0, , NULL) ; LineTo (hdc, rect.right, rect.bottom) ; MoveToEx (hdc, 0, rect.bottom, NULL) ; LineTo (hdc, rect.right, 0) ; } EndPaint (hwnd, &ps) ; return DefWindowProc (hwnd, message, wParam, lParam) ;

17 6. 윈도우의 종류 WS_CHILD, WS_POPUP 오버랜드가 아닌 윈도우는 차일드나 팝업 윈도우 둘 중 하나가 된다.
이 두 스타일은 상호 배치되는 성질이 있기 때문에 동시에 같이 사용할 수는 없다. WS_CHILD 다른 윈도우의 차일드 윈도우가 된다. CreateWindow의 hParent인수에 부모 윈도우의 핸들을 대입해 주어 어떤 윈도우의 차일드가 될 것인가를 지정해 주어야 한다. 차일드 윈도우는 부모 윈도우의 작업영역 밖을 벗어날 수 없다. 메인 윈도우의 작업영역 내부에서 사용되는 컨트롤이 이 스타일을 사용한다. WS_POPUP 만든 윈도우는 대화상자나 메시지 박스처럼 부모 윈도우의 작업 영역밖으로 이동할 수 있다. 항상 부모 윈도우보다 수직적으로 위에 위치(Z 순서)하므로 부모에 의해 가려지지 않는다.

18 #include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, 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)) MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName,MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, // window class name "The Hello Program", // window caption WS_POPUPWINDOW, // window style 10, // initial x position 10, // initial y position 200, // initial x size 100, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) TranslateMessage (&msg) ; DispatchMessage (&msg) ; return msg.wParam ;

19 6. 확장 윈도우 스타일 HWND CreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName) CreateWindow에 dwExStyle이 추가되었다. WS_EX_TOPMOST 모든 윈도우보다 수직적으로 위에 있는 윈도우를 만든다. 활성화된 상태에서도 다른 윈도우에 가려지지 않는다. WS_EX_TRANSPARENT 형제 윈도우가 다 그려지기 전에 그려지지 않아 투명하게 보이는 윈도우를 만든다. WS_EX_CLIENTEDGE 작업영역이 쑥 들어간 음각 모양으로 만든다. WS_EX_LAYERD 2000에서 추가된 속성이며 레이어드 윈도우를 생성한다.

20 6. 확장 윈도우 스타일 작업영역 크기 설정 BOOL AdjustWindowRect( LPRECT lpRect, DWORD dwStyle, BOOL bMenu); 이 함수는 원하는 작업영역의 크기를 주면 작업영역 크기에 맞는 윈도우 크기를 계산해 준다. lpRect : 작업영역의 크기 dwStyle : 윈도우의 스타일 bMenu : 메뉴의 존재 여부를 전달 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) case WM_CREATE: RECT rect = {0,0,300,300}; AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW,FALSE); MoveWindow(hwnd,100,100,rect.right-rect.left,rect.bottom-rect.top,FALSE); } return 0;

21 7. 마우스 캡쳐 마우스 캡처하기 SetCapture(hwnd); ReleaseCapture();
윈도우의 클라이언트나 비클라이언트 영역 위에 있을 때 마우스 메시지를 받을 수 있다. 마우스가 윈도우 밖에 있을 때 마우스 메시지를 받고 싶으면 마우스를 캡처해야 한다. SetCapture(hwnd); ReleaseCapture();


Download ppt "6. 마우스."

Similar presentations


Ads by Google