이전 섹션에서는 마우스 클릭 및 마우스 이동에 대해 설명했습니다. 다음은 마우스로 수행할 수 있는 몇 가지 다른 작업입니다.
UI 요소 끌기
UI에서 UI 요소의 끌기를 지원하는 경우 마우스 아래로 메시지 처리기에서 호출해야 하는 다른 함수는 DragDetect. DragDetect 함수는 사용자가 끌기로 해석되어야 하는 마우스 제스처를 시작하면 TRUE 반환합니다. 다음 코드는 이 함수를 사용하는 방법을 보여줍니다.
case WM_LBUTTONDOWN:
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (DragDetect(m_hwnd, pt))
{
// Start dragging.
}
}
return 0;
다음은 프로그램에서 끌어서 놓기를 지원하는 경우 모든 마우스 클릭이 끌기로 해석되지 않도록 하는 것입니다. 그렇지 않으면 사용자가 단순히 클릭하려는 경우(예: 선택하기 위해) 실수로 무언가를 끌 수 있습니다. 그러나 마우스가 특히 민감한 경우 클릭하는 동안 마우스를 완벽하게 유지하기가 어려울 수 있습니다. 따라서 Windows는 몇 픽셀의 끌기 임계값을 정의합니다. 사용자가 마우스 단추를 누르면 마우스가 이 임계값을 초과하지 않는 한 끌기로 간주되지 않습니다. DragDetect 함수는 이 임계값에 도달했는지 여부를 테스트합니다. 함수가 TRUE 반환하는 경우 마우스 클릭을 끌기로 해석할 수 있습니다. 그렇지 않으면 그렇지 않습니다.
메모
DragDetect false 반환하면 사용자가 마우스 단추를 놓으면 Windows에서 WM_LBUTTONUP 메시지가 표시되지 않습니다. 따라서 프로그램이 현재 끌기를 지원하는 모드에 있지 않으면 DragDetect 호출하지 마세요. (예를 들어 끌기 가능한 UI 요소가 이미 선택된 경우) 이 모듈의 끝에는 DragDetect 함수를 사용하는 더 긴 코드 예제가 표시됩니다.
커서 제한
경우에 따라 클라이언트 영역 또는 클라이언트 영역의 일부로 커서를 제한할 수 있습니다. ClipCursor 함수는 커서의 이동을 지정된 사각형으로 제한합니다. 이 사각형은 클라이언트 좌표가 아닌 화면 좌표로 제공되므로 점(0, 0)은 화면의 왼쪽 위 모서리를 의미합니다. 클라이언트 좌표를 화면 좌표로 변환하려면 ClientToScreen함수를 호출합니다.
다음 코드는 커서를 창의 클라이언트 영역으로 제한합니다.
// Get the window client area.
RECT rc;
GetClientRect(m_hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(m_hwnd, &pt);
ClientToScreen(m_hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
// Confine the cursor.
ClipCursor(&rc);
ClipCursorRECT 구조를 사용하지만 ClientToScreenPOINT 구조를 사용합니다. 사각형은 왼쪽 위와 오른쪽 아래 점으로 정의됩니다. 창 외부 영역을 포함하여 커서를 사각형 영역으로 제한할 수 있지만 커서를 클라이언트 영역으로 제한하는 것이 함수를 사용하는 일반적인 방법입니다. 커서를 창 외부의 지역으로 완전히 제한하는 것은 드문 일이며 사용자는 이를 버그로 인식할 수 있습니다.
제한을 제거하려면 NULL 값으로 ClipCursor 호출합니다.
ClipCursor(NULL);
마우스 추적 이벤트: 마우스로 가리키고 나가기
다른 두 개의 마우스 메시지는 기본적으로 사용하지 않도록 설정되지만 일부 애플리케이션에 유용할 수 있습니다.
- WM_MOUSEHOVER: 커서가 고정된 기간 동안 클라이언트 영역 위로 마우스를 가져간 경우
- WM_MOUSELEAVE: 커서가 클라이언트 영역을 떠났습니다.
이러한 메시지를 사용하도록 설정하려면 TrackMouseEvent 함수를 호출합니다.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
TRACKMOUSEEVENT 구조체에는 함수에 대한 매개 변수가 포함됩니다. 구조체의 dwFlags 멤버에는 관심 있는 추적 메시지를 지정하는 비트 플래그가 포함되어 있습니다. 여기에 표시된 대로 WM_MOUSEHOVER 및 WM_MOUSELEAVE둘 다 또는 둘 중 하나만 가져올 수 있습니다. dwHoverTime 멤버는 시스템에서 가리키기 메시지를 생성하기 전에 마우스를 가리켜야 하는 기간을 지정합니다. 이 값은 밀리초 단위로 제공됩니다. 상수 HOVER_DEFAULT 시스템 기본값을 사용하는 것을 의미합니다.
요청한 메시지 중 하나가 표시되면 TrackMouseEvent 함수가 다시 설정됩니다. 다른 추적 메시지를 받으려면 다시 호출해야 합니다. 그러나 TrackMouseEvent를 다시 호출하기 전에 다음 마우스 이동 메시지가 때까지 기다려야 합니다. 그렇지 않으면 추적 메시지로 창이 플러드될 수 있습니다. 예를 들어 마우스를 마우스로 가리키면 마우스가 고정되어 있는 동안 시스템에서 WM_MOUSEHOVER 메시지 스트림을 계속 생성합니다. 마우스가 다른 지점으로 이동하고 마우스를 다시 가리킬 때까지 다른 WM_MOUSEHOVER 메시지를 실제로 원하지 않습니다.
다음은 마우스 추적 이벤트를 관리하는 데 사용할 수 있는 작은 도우미 클래스입니다.
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false)
{
}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
다음 예제에서는 창 프로시저에서 이 클래스를 사용하는 방법을 보여 줍니다.
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
mouseTrack.OnMouseMove(m_hwnd); // Start tracking.
// TODO: Handle the mouse-move message.
return 0;
case WM_MOUSELEAVE:
// TODO: Handle the mouse-leave message.
mouseTrack.Reset(m_hwnd);
return 0;
case WM_MOUSEHOVER:
// TODO: Handle the mouse-hover message.
mouseTrack.Reset(m_hwnd);
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
마우스 추적 이벤트에는 시스템에서 추가 처리가 필요하므로 필요하지 않은 경우 사용하지 않도록 둡니다.
완전성을 위해 기본 가리키기 시간 제한에 대해 시스템을 쿼리하는 함수는 다음과 같습니다.
UINT GetMouseHoverTime()
{
UINT msec;
if (SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &msec, 0))
{
return msec;
}
else
{
return 0;
}
}
마우스 휠
다음 함수는 마우스 휠이 있는지 확인합니다.
BOOL IsMouseWheelPresent()
{
return (GetSystemMetrics(SM_MOUSEWHEELPRESENT) != 0);
}
사용자가 마우스 휠을 회전하면 포커스가 있는 창에 WM_MOUSEWHEEL 메시지가 표시됩니다. 이 메시지의 wParam 매개 변수에는 휠이 회전된 정도를 측정하는 델타 정수 값이 포함되어 있습니다. 델타는 임의의 단위를 사용합니다. 여기서 120개 단위는 하나의 "작업"을 수행하는 데 필요한 회전으로 정의됩니다. 물론 작업의 정의는 프로그램에 따라 달라집니다. 예를 들어 마우스 휠을 사용하여 텍스트를 스크롤하는 경우 각 120 단위의 회전은 한 줄의 텍스트를 스크롤합니다.
델타의 부호는 회전 방향을 나타냅니다.
- 양수: 사용자로부터 멀리 앞으로 회전합니다.
- 음수: 사용자를 향해 뒤로 회전합니다.
델타 값은 몇 가지 추가 플래그와 함께 wParam 배치됩니다. GET_WHEEL_DELTA_WPARAM 매크로를 사용하여 델타 값을 가져옵니다.
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
마우스 휠의 해상도가 높은 경우 델타의 절대값은 120보다 작을 수 있습니다. 이 경우 작업이 더 작은 증분으로 발생하는 것이 합리적이라면 그렇게 할 수 있습니다. 예를 들어 텍스트는 한 줄 미만씩 스크롤할 수 있습니다. 그렇지 않으면 휠이 동작을 수행할 만큼 충분히 회전할 때까지 총 델타를 누적합니다. 사용하지 않는 델타를 변수에 저장하고 120단위가 누적되면(양수 또는 음수) 작업을 수행합니다.
다음