오늘은 마우스 커서를 바꾸는 방법을 알아보겠습니다.
- 대화상자 내에서만 커서 바꾸는 법
- 컨트롤 위에 마우스가 있을 때만 바꾸는 법
- 대화상자 밖에서도 커서 바꾸는법
을 알아보겠습니다.
우선 그전에 아래 Cursor.zip 파일을 다운받아서 압축 해제 후 res 폴더에 넣어주세요.

그리고 리소스 뷰에서 3개의 커서 파일을 추가해줍니다.



각 리소스의 아이디는 색에 맞게 IDC_CURSOR_RED, IDC_CURSOR_GREEN, IDC_CURSOR_BLUE로설정합니다.

1. 대화상자 내에서만 커서 바꾸는 법
아래와 같이 버튼 하나를 만든 후 더블클릭으로 이벤트 처리 함수를 만들어줍니다.

헤더파일에 대화상자 내에 표시할 HCURSOR m_hCursorIn, 그리고 BOOL m_bMouseSet을 선언해 줍니다.
HCURSOR m_hCursorIn; // 대화상자 내
BOOL m_bMouseSet; // 플래그
OnInitDialog에 아래와 같이 코딩해줍니다.
m_hCursorIn = AfxGetApp()->LoadCursor( IDC_CURSOR_RED ); // 대화상자 내
아래와 같이 OnSetCursor를 만들어 줍니다.

OnSetCursor 내부에 아래와 같이 코딩해줍니다.
BOOL CCursorTestDlg::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
if ( m_bMouseSet )
{
::SetCursor( m_hCursorIn );
return TRUE;
}
return CDialogEx::OnSetCursor( pWnd, nHitTest, message );
}
위에서 만든 버튼 이벤트 처리 함수에 아래와 같이 코딩해 줍니다.
void CCursorTestDlg::OnBnClickedButton1()
{
m_bMouseSet = !m_bMouseSet;
}
실행시켜서 확인해 봅니다.

이 마우스는 대화상자 바깥을 나가면 원래대로 돌아옵니다.
2. 컨트롤 위에 마우스가 있을 때만 바꾸는 법
헤더파일에 HCURSOR m_hCursorMouseOn을 선언합니다.
HCURSOR m_hCursorMouseOn; // 마우스 버튼위에 올렸을 때
아래와 같이 버튼 하나를 더 추가하고 더블 클릭을 눌러 이벤트 처리 함수를 만듭니다.

OnInitDialog에 아래와 같이 추가로 코딩합니다.
m_hCursorIn = AfxGetApp()->LoadCursor( IDC_CURSOR_RED ); // 대화상자 내
m_hCursorMouseOn = AfxGetApp()->LoadCursor( IDC_CURSOR_GREEN ); // 마우스가 올라갔을 때
위에서 만든 버튼 이벤트 처리 함수에 아래와 같이 코딩합니다.
void CCursorTestDlg::OnBnClickedButton2()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
SetClassLongW( ::GetDlgItem(this->GetSafeHwnd(), IDC_BUTTON2), GCL_HCURSOR ,(LONG)m_hCursorMouseOn);
}
실행 시켜 확인해 봅니다.

3. 대화상자 밖에서도 커서 바꾸는법
버튼을 하나 더 추가합니다.

헤더파일에 기존 커서를 저장할 HCURSOR m_hCursorPre와 바꿀 커서 HCURSOR m_hCursorOut을 선언합니다.
HCURSOR m_hCursorPre; // 기존 모양
HCURSOR m_hCursorOut; // 대화상자 바깥
OnInitDialog에 아래와 같이 초기화를 합니다.
m_hCursorIn = AfxGetApp()->LoadCursor( IDC_CURSOR_RED ); // 대화상자 내
m_hCursorMouseOn = AfxGetApp()->LoadCursor( IDC_CURSOR_GREEN ); // 마우스가 올라갔을 때
m_hCursorPre = CopyCursor( LoadCursor( NULL, IDC_ARROW ) ); // 기존 커서
m_hCursorOut = (HCURSOR)LoadImageW( // 바깥에서 사용할 커서
AfxGetInstanceHandle(),
MAKEINTRESOURCE( IDC_CURSOR_BLUE ),
IMAGE_CURSOR,
32, 32,
LR_DEFAULTCOLOR );
위에서 만든 버튼을 더블 클릭하여 이벤트 처리 함수를 만든 후 아래와 같이 코딩합니다.
void CCursorTestDlg::OnBnClickedButton3()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
HCURSOR hcursor = CopyCursor( m_hCursorOut );
::SetSystemCursor( hcursor, 32512/*OCR_NORMAL*/ );
}
::SetSystemCursor를 사용하면 첫번째 인자로 들어간 HCURSOR는 소멸되니 항상 CopyCursor로 복사를 해서 SetSystemCursor에 사용 합니다.
::SetSystemCursor로 마우스를 만들어주면 대화상자가 종료되어도 그 상태로 유지하므로 대화 상자가 소멸 할 때 원래 상태로 복귀하게 OnDestroy을 선언합니다.

그리고 아래와 같이 코딩합니다.
void CCursorTestDlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
::SetSystemCursor( m_hCursorPre, 32512/*OCR_NORMAL*/ );
::DestroyCursor( m_hCursorOut );
::DestroyCursor( m_hCursorIn );
::DestroyCursor( m_hCursorMouseOn );
}
그리고 실행하여 확인합니다.

참고로 ::SetSystemCursor에서 32512는 기본 마우스 모양(IDC_ARROW)에 대한 값으로 다른 상태일 경우에 커서를 바꾸고 싶으시면 WinUser.h을 참고 하셔서 값을 넣어주시면 됩니다.
#define IDC_ARROW MAKEINTRESOURCE(32512)
#define IDC_IBEAM MAKEINTRESOURCE(32513)
#define IDC_WAIT MAKEINTRESOURCE(32514)
#define IDC_CROSS MAKEINTRESOURCE(32515)
#define IDC_UPARROW MAKEINTRESOURCE(32516)
#define IDC_SIZE MAKEINTRESOURCE(32640) /* OBSOLETE: use IDC_SIZEALL */
#define IDC_ICON MAKEINTRESOURCE(32641) /* OBSOLETE: use IDC_ARROW */
#define IDC_SIZENWSE MAKEINTRESOURCE(32642)
#define IDC_SIZENESW MAKEINTRESOURCE(32643)
#define IDC_SIZEWE MAKEINTRESOURCE(32644)
#define IDC_SIZENS MAKEINTRESOURCE(32645)
#define IDC_SIZEALL MAKEINTRESOURCE(32646)
#define IDC_NO MAKEINTRESOURCE(32648) /*not in win3.1 */
#if(WINVER >= 0x0500)
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif /* WINVER >= 0x0500 */
#define IDC_APPSTARTING MAKEINTRESOURCE(32650) /*not in win3.1 */
#if(WINVER >= 0x0400)
#define IDC_HELP MAKEINTRESOURCE(32651)