메뉴 닫기

MFC에서 마우스 커서 변경하는 법, SetCursor와 OnSetCursor 완벽 가이드


MFC에서 마우스 커서 변경하는 법, SetCursor와 OnSetCursor 완벽 가이드

🖱️ 마우스 커서 변경으로 사용자 경험까지 업그레이드해보세요!

마우스 커서는 사용자가 프로그램을 조작할 때 가장 먼저 눈에 띄는 시각적 요소 중 하나입니다.
그래서 어떤 상황에 어떤 커서를 보여주느냐에 따라 사용자의 인지 속도와 사용성 만족도가 확연히 달라질 수 있어요.
특히 MFC 기반 데스크톱 애플리케이션에서는 SetCursorOnSetCursor 함수를 적절히 활용하면 특정 조건에 따라 커서를 자유롭게 바꿀 수 있고, 그 결과로 더 직관적이고 부드러운 사용자 경험을 제공할 수 있습니다.
이번 글에서는 커서 변경이 필요한 대표적인 예시부터 함수 사용법, 상황별 구현 팁까지 실무에 바로 적용할 수 있도록 상세히 정리해드릴게요.

지금부터 MFC에서 커서 변경을 처리하는 두 가지 대표적인 방식, SetCursorOnSetCursor의 차이와 용도부터 커서 리소스 등록, 커스텀 커서 적용, 마우스 이벤트에 따른 동적 전환까지 모두 알려드릴게요.
개발 중 “이 영역은 클릭할 수 있어요!”, “지금은 작업 중입니다!” 같은 메시지를 시각적으로 주고 싶으셨다면 오늘 이 글이 딱 필요하실 거예요.







🧭 MFC에서 커서 변경이 필요한 이유

MFC 애플리케이션에서 커서 변경은 단순한 시각적 효과를 넘어, 사용자 경험(UX)을 극대화하는 중요한 수단이 됩니다.
사용자가 마우스를 움직일 때 커서가 상황에 따라 변화하면 어떤 동작이 가능한지, 혹은 현재 상태가 어떤지 직관적으로 전달할 수 있기 때문이죠.

예를 들어 사용자가 버튼 위에 마우스를 올렸을 때 손가락 모양의 커서로 바뀐다면 “클릭 가능하다”는 신호를 주는 것이고,
로딩 중에는 모래시계 또는 회전 커서로 현재 시스템이 바쁜 상태임을 전달할 수 있습니다.
이러한 시각적 피드백은 프로그램 신뢰도와 직관성을 높이는 데 큰 도움이 됩니다.

  • 👆클릭 가능한 요소 위에서 커서를 손가락 모양으로 변경
  • 파일 처리나 통신 중일 때 대기 중 커서로 전환
  • 📐드래그나 리사이즈 시 방향성 커서로 전환

이처럼 마우스 커서 하나만으로도 프로그램의 상태와 가능 동작을 전달할 수 있으며,
그 결과 사용자는 더 빠르게 반응하고, 실수를 줄이며, 앱 사용에 만족하게 됩니다.
이런 이유로 MFC에서 커서 변경 처리는 단순 옵션이 아닌, 꼭 신경 써야 할 요소라고 할 수 있어요.


🛠️ SetCursor 함수의 사용법과 특징

MFC에서 마우스 커서를 바꾸는 가장 기본적인 방법은 SetCursor 함수를 사용하는 것입니다.
이 함수는 현재 커서 위치나 상태와 관계없이 즉시 커서를 변경할 수 있는 강력한 방법이에요.
보통 메시지 루프나 특정 조건문 내에서 커서를 직접 제어하고 싶을 때 자주 쓰입니다.

CODE BLOCK
// IDC_WAIT는 대기 상태 커서
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));

위의 예시처럼 LoadStandardCursor를 통해 윈도우에서 제공하는 기본 커서를 불러온 뒤, SetCursor로 지정하면 즉시 커서가 바뀝니다.
IDC_ARROW, IDC_HAND, IDC_WAIT, IDC_CROSS 등 다양한 커서 타입을 사용할 수 있어 상황에 맞게 조합이 가능합니다.

  • 즉각적인 커서 변경이 필요한 경우
  • 🧩로직 내부에서 커서 상태 제어가 필요한 경우
  • ⚙️UI 제어 흐름과 독립된 커서 조작이 필요한 경우

단, SetCursor는 일시적인 커서 변경이라는 점에 주의해야 해요.
OS 메시지 루프에 따라 다시 기본 커서로 돌아갈 수 있으므로, 지속적인 커서 제어가 필요할 땐 OnSetCursor를 활용하는 것이 더 안정적입니다.







🔄 OnSetCursor 함수의 역할과 활용법

OnSetCursor는 MFC에서 커서를 지속적으로 제어할 수 있게 해주는 가상 함수입니다.
이 함수는 마우스가 클라이언트 영역 위에 위치하거나 이동할 때마다 자동으로 호출되므로, 특정 컨트롤이나 영역 위에 커서를 올렸을 때 커서를 변경하고 싶다면 가장 적합한 방법이에요.

기본적으로 CWnd 또는 CView를 상속받은 클래스에서 OnSetCursor()를 오버라이드하면 됩니다.
이 함수는 WM_SETCURSOR 메시지를 처리할 때 호출되며, 반환값에 따라 시스템 커서 설정 여부가 결정됩니다.

CODE BLOCK
BOOL CMyView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
    return TRUE;
}

위 코드처럼 OnSetCursor 내에서 SetCursor를 호출하고 TRUE를 반환하면,
기본 커서 설정을 무시하고 개발자가 지정한 커서가 화면에 표시됩니다.
이 방식은 특정 윈도우 내부에서 지속적이고 반복적인 커서 변경을 구현할 수 있어요.

  • 📌윈도우 영역 내에서 커서를 지속적으로 제어하고 싶을 때
  • 👆사용자 입력 위치나 마우스 좌표에 따라 커서를 다르게 설정하고 싶을 때
  • 🔄윈도우 메시지 처리 흐름 안에서 커서를 관리하고 싶을 때

반복적으로 커서를 바꾸거나, 영역별로 다른 커서를 보여줘야 한다면 SetCursor보다 OnSetCursor가 훨씬 유리합니다.
단, 뷰 클래스 또는 컨트롤 클래스에 직접 구현해야 하므로 구조적인 접근이 필요해요.


🎨 커스텀 커서 리소스 등록 및 적용

기본 제공 커서 외에도 MFC에서는 직접 만든 커스텀 커서를 사용할 수 있어요.
로고, 아이콘, 특수 기능 등을 시각적으로 표현하고 싶을 때 커스텀 커서는 유용한 선택이 될 수 있습니다.
단, 올바른 리소스 등록과 로딩 절차를 따라야 원하는 대로 동작합니다.

🖼️ 리소스 등록하기

Visual Studio의 리소스 편집기에서 커서(Cursor) 항목을 추가한 뒤, .cur 또는 .ani 파일을 등록합니다.
등록한 커서에는 리소스 ID를 부여해야 하며, 예를 들어 IDR_CURSOR_CUSTOM 같은 이름을 사용합니다.

🧩 커서 로딩 및 적용

CODE BLOCK
// 커스텀 커서 리소스 로딩
HCURSOR hCustomCursor = AfxGetApp()->LoadCursor(IDR_CURSOR_CUSTOM);
::SetCursor(hCustomCursor);

이처럼 커서 리소스를 불러와 SetCursor에 넣으면 바로 사용할 수 있어요.
OnSetCursor에서도 동일하게 사용 가능하며, 다양한 위치에 적용할 수 있습니다.

⚠️ 주의: 커스텀 커서 파일은 프로젝트에 포함시켜야 하고, 릴리즈 빌드에서도 누락되지 않도록 리소스 설정을 확인하세요.

UI에 통일감을 주고 싶거나, 특정 기능을 시각적으로 차별화하고 싶을 때 커스텀 커서만큼 확실한 표현 수단은 없습니다.
이왕이면 자체 제작한 커서 이미지를 활용해 보는 것도 좋은 방법이에요.







⚡ 실전 예제: 상황별 마우스 커서 전환

커서 변경 기능은 단순히 보여주기 위한 요소가 아니라 사용자와의 소통 도구입니다.
실제 상황에서 어떤 조건에 어떤 커서를 적용해야 직관적인 UX를 만들 수 있는지, 대표적인 사례들을 함께 살펴볼게요.

🖱️ 버튼 또는 클릭 가능한 영역

마우스가 버튼이나 링크 위에 올라왔을 때는 IDC_HAND 커서를 사용하는 것이 일반적입니다.
이 커서를 통해 사용자는 “이 영역은 클릭할 수 있어요”라는 메시지를 자연스럽게 받아들일 수 있어요.

⏳ 처리 중 또는 작업 대기 상태

파일을 로딩하거나 네트워크 통신 등으로 프로그램이 바쁜 경우에는 IDC_WAIT 커서를 표시합니다.
이렇게 하면 사용자는 현재 상태를 이해하고 무의미한 클릭을 줄이게 됩니다.

📐 리사이즈 또는 드래그 영역

창 크기 조절이나 드래그 가능한 구역 위에서는 방향을 나타내는 IDC_SIZENWSE, IDC_SIZEWE 등의 커서를 사용하면 보다 명확한 조작 안내가 됩니다.

💎 핵심 포인트:
커서를 바꾸는 타이밍은 사용자가 마우스를 이동하거나 특정 동작을 수행하려 할 때가 가장 적절합니다. 불필요한 커서 변경은 오히려 혼란을 줄 수 있으니, 꼭 필요할 때만 활용하는 것이 좋아요.

MFC에서 이런 동적 전환은 OnSetCursor에서 영역 조건을 if 문으로 판별해 처리하거나, 메시지 핸들러 내부에서 SetCursor를 활용해 조건부 변경하는 방식으로 구현할 수 있어요.
커서가 상황을 설명하도록 만들면, 사용자는 도움말 없이도 프로그램을 자연스럽게 사용할 수 있게 됩니다.


❓ 자주 묻는 질문 (FAQ)

SetCursor와 OnSetCursor는 언제 각각 사용하는 게 좋을까요?
SetCursor는 즉각적인 커서 변경에, OnSetCursor는 지속적이고 상황에 맞는 커서 유지에 적합합니다.
한 번만 바꾸면 되는 경우는 SetCursor, 특정 영역 위에서 반복적으로 유지해야 하는 경우는 OnSetCursor가 좋아요.
기본 커서 외에 내가 만든 커서도 사용할 수 있나요?
네, Visual Studio 리소스 편집기를 통해 커스텀 커서를 등록한 뒤 LoadCursor로 불러와 사용할 수 있습니다.
.cur 또는 .ani 형식의 커서 파일을 사용할 수 있어요.
커서가 변경됐다가 다시 원래대로 돌아가요. 왜 그런가요?
SetCursor로만 커서를 변경하면 시스템 메시지 처리에 따라 기본 커서로 되돌아갈 수 있습니다.
이럴 땐 OnSetCursor를 오버라이드하여 지속적으로 변경된 커서를 설정해 주세요.
OnSetCursor에서 여러 영역에 따라 다른 커서를 설정할 수 있나요?
가능합니다.
마우스 좌표를 기준으로 조건문을 활용하면 위치별로 다른 커서를 지정할 수 있어요.
예를 들어 특정 영역 안에 있을 때만 손 모양 커서를 보여줄 수도 있습니다.
커서가 바뀌었는지 디버깅하려면 어떻게 해야 하나요?
일시적으로 메시지박스를 띄우거나, Output 디버그 로그에 커서 변경 시점을 출력하면 됩니다.
GetCursor() 함수를 통해 현재 커서 핸들을 확인할 수도 있어요.
커서 이미지가 너무 작거나 흐릿하게 보여요. 이유가 뭘까요?
고해상도 디스플레이(HIDPI)에서 커서 파일이 저해상도면 흐릿하게 보일 수 있습니다.
32×32 이상의 고해상도 .cur 파일을 사용하는 것이 좋습니다.
애니메이션 커서도 사용할 수 있나요?
네, .ani 형식의 애니메이션 커서도 사용할 수 있습니다.
LoadCursor 대신 LoadImage 함수를 사용하면 애니메이션 커서도 로딩이 가능합니다.
OnSetCursor 함수 안에서 조건문으로 다른 커서를 쓸 수 있나요?
물론 가능합니다.
마우스 위치, 윈도우 핸들, hit test 정보 등을 기준으로 다양한 커서를 조건별로 설정할 수 있어요.



🧭 MFC 커서 변경, UX를 살리는 실전 기술

MFC에서 마우스 커서를 변경하는 기능은 단순한 장식이 아니라 사용자와 프로그램이 소통하는 시각적 수단입니다.
SetCursor로 즉각적인 피드백을 줄 수 있고, OnSetCursor를 활용하면 특정 영역 내에서 지속적이고 조건부 커서 제어가 가능합니다.
또한, 커스텀 커서를 활용하면 브랜딩 요소나 고급 사용자 경험까지 확장할 수 있죠.

이번 글에서 다룬 내용을 정리하자면,
기본 커서 변경 방법인 SetCursor,
윈도우 영역 제어에 적합한 OnSetCursor,
그리고 커스텀 커서 리소스 등록 방법,
상황별 실전 예제까지 실제 MFC 프로젝트에 바로 활용 가능한 팁들을 모두 안내해드렸습니다.
앞으로 여러분의 프로그램이 더 친절하고, 더 스마트해지는 데 도움이 되었길 바랍니다!


🏷️ 관련 태그 : MFC, 마우스커서, SetCursor, OnSetCursor, 커서변경, 사용자경험, 윈도우프로그래밍, 커스텀커서, C++, GUI개발