마우스 입력을 활용하여, 드래그 & 드랍의 기능을 구현해 보자.
또한 마우스가 윈도우에서 벗어 났을 때 어떻게 확인 해야 할지에 대해서도 하나씩 알아 보자.
기본 적으로 드래그 & 드랍을 생성하기 위해서는,
3가지의 WM메시지가 필요 하다.( 마우스 왼쪽 버튼을 사용한다고 하였을 때 )
1. LBUTTONDOWN
2. MOUSEMOVE
3. LBUTTONUP
다음의 3가지 WM메시지를 메시지탭에서 추가한다.
기본적인 드래그 & 드랍의 구조는
마우스 왼쪽 버튼이 눌리면(LBUTTONDOWN) 그 위치에 있는 대상과 위치를 검사하여,
왼쪽 버튼이 눌려 있는 부분이 대상의 위치와 일치 한다면,
특정 플래그를 On(true)시키고,
마우스가 움직였을 때(MOUSEMOVE) 특정 플래그가 On(true)라면 마우스의 x,y위치를 대상의 x,y에 대입하면 된다.
그 후 왼쪽 버튼이 손에서 떨어지면(LBUTTONUP) 특정 플래그를 Off(false)로 변경한다.
그럼 이제 코드를 살펴 보자.
// OnLButtonDown
if( point.x >= m_ptItemText.x -32 &&
point.x <= m_ptItemText.x +32 &&
point.y >= m_ptItemText.y -32 &&
point.y <= m_ptItemText.y +32 )
{// 마우스의 왼쪽 버튼이 특정 대상( m_ptItemText )의 일정 위치( 예제에서는 text의 가로, 세로 32정도의 위치를 지정해 두었다.)와 동일하다면
SetCapture();
m_bDragFlag = true; // m_bDragFlag를 On(treu)시킨다.
RedrawWindow();
}
//OnMouseMove
if( m_bDragFlag ) // m_bDragFlag가 true라면
{
m_ptItemText = point; // 드래그 대상의 위치를 마우스 x,y로 변경한다.
RedrawWindow();
}
//OnLButtonUp
if( m_bDragFlag )
{
m_bDragFlag = false; // 만약 m_bDragFlag가 true라면 단순히 false로 변경만 한다.
m_ptItemText = point; // 이 라인은 구지 해주지 않아도 상관없다.
RedrawWindow();
}
마지막으로 화면에 출력해 주어야 하기 때문에 WM_PAINT를 생성한다.
//OnPaint
dc.TextOut( m_ptItemText.x, m_ptItemText.y, TEXT("My Computer") );
이게 가장 최소한의 드래그 & 드랍의 구조이다.
물론 m_ptItemText에 대해서 View 생성자에서 초기화를 한번 해 주어야 겠지만,
기본 적으로 0, 0 정도로 초기화 하면 실행했을 경우에 My Computer라는 Text가 화면에 띄워 지고,
마우스로 드래그 & 드랍이 가능할 것이다.
하지만 여기서 끝이 아니다.
기본적인 드래그 & 드랍의 구조는 구현이 되었지만, 마우스가 윈도우 화면을 벗어 나면 더이상 마우스의 좌표값을 가져 오지 못하여( LBUTTONDOWN, LBUTTONUP 또한 ) 드래그가 중지 되거나, 원치 않는 행동들을 하게 될 것이다.
이때 문제를 해결하기 위한 부분이.
SetCapture() 라는 함수를 사용하는 것인데,
이 함수는 마우스가 현재 윈도우에서 벗어 나더라도 계속 해서 마우스 메시지를 수신하도록 하게 한다.
그리고 그 수신 메시지를 종료 시키는 것이, ReleaseCapture()이다.
이제 이 함수를 사용해서 OnLButtonDown()과, OnLButtonUp()에 각각 SetCapture와 ReleaseCapture를 추가해주자.
//OnLButtonDown
if( point.x >= m_ptItemText.x -32 &&
point.x <= m_ptItemText.x +32 &&
point.y >= m_ptItemText.y -32 &&
point.y <= m_ptItemText.y +32 )
{
SetCapture(); // 이 부분이 추가 되었다.
m_bDragFlag = true;
RedrawWindow();
}
//OnLButtonUp
if( m_bDragFlag )
{
m_bDragFlag = false;
m_ptItemText = point;
RedrawWindow();
ReleaseCapture(); // 이 부분이 추가 되었다.
}
여기 까지 완료 하였다면, 이제 마우스가 윈도우를 벗어나도 드래그하는 대상이 끝까지 따라 올 것이다.
하지만 실행 해 보면, 또 한가지 문제가 존재한다. 윈도우를 한번 벗어난 상태에서 마우스 버튼을 때면, 다시는 대상을 가져 올 수 없다는 것이다.
이럴 때를 위해 비록 마우스가 윈도우를 벗어 났다고 하더라도, 드래그 대상까지 화면을 벗어 나서는 안된다는 것을 알 수 있다.
OnLButtonUp에 대해서 한번더 코드를 수정하자.
//OnLButtonUp
CRect rect;
GetClientRect( &rect );
if( m_bDragFlag )
{
m_bDragFlag = false;
m_ptItemText = point;
if( m_ptItemText.x < rect.left ) m_ptItemText.x = rect.left;
else if( m_ptItemText.x+32 > rect.right ) m_ptItemText.x = rect.right-32;
if( m_ptItemText.y < rect.top ) m_ptItemText.y = rect.top;
else if( m_ptItemText.y+32 > rect.bottom ) m_ptItemText.y = rect.bottom-32;
RedrawWindow();
ReleaseCapture();
}
CView::OnLButtonUp(nFlags, point);
이제 드래그 & 드랍에 대한 문제점은 모두 해결 된거 같다.
(만약 대상이 마우스를 따라 오다가, 화면 끝에 가면 멈추게 하고 싶다면 OnMouseMove()에 대해서도 위의 조건문을 추가해 주자.
// 실행 화면


드래그 & 드랍이 구현 되었다.
'프로그래밍 > MFC' 카테고리의 다른 글
MFC-마우스 입력( TRACKMOUSEEVENT ) (0) | 2010.05.16 |
---|---|
MFC-새로운 클래스 추가 하기 (0) | 2010.05.16 |
MFC-마우스 입력 (0) | 2010.05.16 |
MFC-GetKeyState() (0) | 2010.05.12 |
MFC-GetWindowRect(), ScreenToClient(), SetWindowPos() (1) | 2010.05.12 |