MFC 마우스 정보와 커서관리
- 마우스 정보
::GetSystemMetrics(int nIndex);
<nIndex>
nIndex | 의미 |
SM_CMOUSEBUTTONS | 마우스 버튼 개수 리턴, 마우스 없으면 0 리턴 |
SM_MOUSEPRESENT | 마우스의 설치 여부를 TRUE 또는 FALSE로 리턴 |
SM_SWAPBUTTON | 왼쪽과 오른쪽 버튼의 의미가 바뀌었으면 TRUE 리턴 |
SM_MOUSEWHEELPRESENT | 휠 마우스이면 TRUE 리턴 |
- 커서 바꾸기
HCURSOR SetCursor(HCURSOR hCursor);
<hCursor>
앞으로 사용할 커서를 나타내는 커서 리소스를 가리키는 핸들
- WM_SETCURSOR 메시지
OS는 Client영역(View)에 마우스 포인터가 들어올때 WM_SETFOCUS 메시지 받고, 나갈때 WM_KILLFOCUS 받음
커서 모양을 바꿀 필요가 있으면 WM_SETCURSOR 메시지에서 처리한다.
CWinApp::LoadStandardCursor() : OS에서 제공하는 마우스 커서를 선택
CWinApp::LoadCursor() : 사용자가 만든 마우스 커서를 선택
CWinApp 내부 함수가 아닌 다른 곳에서 CWinApp 내부 함수호출하려면 AfxGetApp() 을 이용하면 된다.
- 사용자 정의 마우스 커서 그리기
바탕화면과 투명색/반전색 선택 가능하고 핫스팟은 마우스 커서의 위치를 지정한다. 위 그림에서는 반전색과 핫스팟을 마우스 커서 그림의 중앙을 선택한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
void CMFCApplication2View::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SelectStockObject(LTGRAY_BRUSH);
dc.Rectangle(100, 100, 300, 300);
}
BOOL CMFCApplication2View::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT)
{
CPoint point;
::GetCursorPos(&point);
ScreenToClient(&point);
CRect rect(100, 100, 300, 300);
if (rect.PtInRect(point)) // 마우스 커서가 사각형안에 있는지 검사
SetCursor(AfxGetApp()->LoadCursorW(IDC_CURSOR1)); // 사용자 정의 커서
else
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS)); // 시스템 커서
return TRUE;
}
return CView::OnSetCursor(pWnd, nHitTest, message);
}
void CMFCApplication2View::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rect(100, 100, 300, 300);
ClientToScreen(&rect);
::ClipCursor(&rect); // 카우스 커서 이동을 사각형 안으로 제한
CView::OnLButtonDown(nFlags, point);
}
void CMFCApplication2View::OnRButtonDown(UINT nFlags, CPoint point)
{
::ClipCursor(NULL); // 해제
CView::OnRButtonDown(nFlags, point);
}
|
cs |
위 코드는 마우스 포인터를 위치에 따라 바꿀 수 있게 해준다.
마우스 커서가 사각형 안에 있으면 사용자 정의 커서로 바꾸고 밖이면 시스템커서로 바꿔준다.
::ClipCursor(const RECT* lpRect); 커서가 움직일 수 있는 범위를 lpRect 안으로 제한한다.
참고>
마우스커서 모양을 바꾸려면 OnSetCursor(), OnLButtonDown(), OnRButtonDown() 을 구현해야 한다.
아래는 표를 그리고 제목줄에서 드래그로 컬럼 폭 조절할때 마우스 포인터 모양을 바꾸는 코드 이다.
자세한 전체 코드 20221001 (비공개) : https://petra.tistory.com/1731
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
class CDataListWnd : public CWnd
{
...
private:
BOOL m_bMouseCursor;
bool m_is_clicked_title;
}
void CDataListWnd::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
point.x += m_nHScroll;
for (int i = 0; i < m_nColumn_count; i++)
{
if (m_pTitleRect[i].PtInRect(point))
{
// 마우스 이벤트에서 마으스커서를 직접 변경하면 드래그할때 화살표 마웃으 포인터가 보이는 문제가 있어,
// WM_SETCURSOR 메시지 처리기에서 마우스 포인터를 로드한다. 20221001
m_bMouseCursor = TRUE;
SetCursor((AfxGetApp()->LoadStandardCursor(IDC_SIZEWE))); // 제목 세로 경계선에 오면 마우스 커서를 바꾸고 싶은데 여기서 로드 해야만 적용된다. 20221001
}
else if (false == m_is_clicked_title)
{
m_bMouseCursor = FALSE;
}
}
...
}
void CDataListWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
int nItem = point.y / ITEM_HEIGHT; // 제목줄이 0 이므로 m_nVscroll 은 무시한다. 20220927
if (0 == nItem)
{
CRect rect(m_nHScroll, m_nVScroll * ITEM_HEIGHT, m_view_cx * MAX_WIDTH_SIZE, ITEM_HEIGHT);
ClientToScreen(&rect);
::ClipCursor(&rect); // 마우스커서를 캡쳐할 영역을 지정한다. (항목 크기)
int pos = point.x;
if (pos > m_pnCol_max[m_nCol] - 3 && pos < m_pnCol_max[m_nCol] + 3) // 컬럼의 폭 정보를 가진 배열
m_is_clicked_title = true;
else
m_is_clicked_title = false;
return;
}
...
CWnd::OnLButtonDown(nFlags, point);
}
void CDataListWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
::ClipCursor(NULL);
if (true == m_is_clicked_title)
{
m_is_clicked_title = false;
m_nCol = -1;
}
m_bMouseCursor = FALSE;
CWnd::OnLButtonUp(nFlags, point);
}
BOOL CDataListWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
if(TRUE == m_bMouseCursor)
SetCursor((AfxGetApp()->LoadStandardCursor(IDC_SIZEWE)));
else
SetCursor((AfxGetApp()->LoadStandardCursor(IDC_ARROW)));
return TRUE; // 여기서 반환하지 않으면 마우스 커서 모양이 드래그할때 계속 바뀌는 문제가 생긴다. 20221001
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
|
cs |