C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[56652] Re:Mouse Cursor가 바뀌질 않습니당
smallpotato [] 1131 읽음    2009-04-16 10:56
아... 6년전 질문에 답을 올리게 되네요...
저도 서비님과 같은 문제로 고생을 좀 했습니다.
복잡한것도 아니고 굉장히 간단한 코드인데도 의도한대로 동작하지 않으니까 환장하겠더군요 -_-;;
여튼 이게 왜 안되는지 추적을 해봤고요 먼저 그 답부터 얘기하면요

SetCursor(LoadCursor(NULL,IDC_HAND));
와 같은 방식으로 직접 윈도 API 로 커서를 바꾸시던가

ReleaseCapture();
라는 역시 윈도 API 를 쓰셔서 윈도우에서 마우스 캡쳐를 푸시고 VCL 의 Cursor 에 값을 할당하셔야 합니다.
이 방법은 마우스 캡쳐를 이용하시는 기능을 만드시는 분들에게는 문제가 생길수 있으니
그냥 적절한 SetCursor 를 쓰시는게 좋을거 같네요...

이제 저게 왜 저러는가 설명을 할게요
급하신분은 위만 보시고 뒤로 누르시면 됩니다
...
...
...

아래는 우리가 커서를 바꿀때 쓰는 Cursor 의 명세입니다.

__property TCursor Cursor = {read=FCursor, write=SetCursor, default=0};

잘 아시듯이 VCL 체계에서 TForm 등등의 많은 컨트롤들이 TControl 에게서 많은것을 물려받습니다
저 Cursor 도 그 중 하나고요
보시다시피 커서를 바꾸는 일은 SetCursor 가 하고 있군요
그럼 TControl 의 SetCursor 를 보겠습니다

procedure TControl.SetCursor(Value: TCursor);
begin
  if FCursor <> Value then
  begin
    FCursor := Value;
    Perform(CM_CURSORCHANGED, 0, 0);
  end;
end;

보시다시피 바로 윈도우에 WM_SETCURSOR 메세지를 쏘지 않습니다.
CM_CURSORCHANGED 라고 VCL 내부에서 지네끼리 돌려쓰는 메세지를 쏘죠
그래서 그 메세지를 처리하는 녀석은...

procedure TWinControl.CMCursorChanged(var Message: TMessage);
var
  P: TPoint;
begin
  if GetCapture = 0 then
  begin
    GetCursorPos(P);
    if FindDragTarget(P, False) = Self then
      Perform(WM_SETCURSOR, Handle, HTCLIENT);
  end;
end;

이녀석입니다. 얘는 TWinControl 에 정의되어 있네요.
네. 여기서 WM_SETCURSOR 를 쏘게 되네요...
그런데...
GetCapture = 0
이게 문제입니다.
GetCapture 라는건 윈도우 API 인데 설명을 볼게요.

The GetCapture function retrieves the handle of the window (if any) that has captured the mouse.

라는데 창이 마우스를 capture 했다는 개념을 정확하게는 모르겠는데
검색을 해보니 창을 클릭했을때 잡히게 되는 그런 정도의 얘기인거 같습니다.
여기서 이제 결론이 나오는데요..
좌클릭이 되어 capture 된 상태에서는 Cursor 를 바꾸려 해도 결국 여기에서 모든게 씹히고 맙니다.
왜 밑의 코드가 Shift.Contains(ssRight) 가 되면 잘 되는지도 여기서 알 수 있는것 같습니다.

따라서 ReleaseCapture() 를 통해 capture 상태를 풀던가
아니면 더러운 VCL 들이 메세지를 돌리는 과정을 건너뛰고 직접 윈도우에 커서를 바꾸겠다고 하시면 됩니다.



서비 님이 쓰신 글 :
: void __fastcall Tfrm_Main::PB_ImageMouseMove(TObject *Sender,
:       TShiftState Shift, int X, int Y)
: {
:     if(Shift.Contains(ssLeft)){
:         PB_Image->Cursor = crHand2;
:     }
:     else
:         PB_Image->Cursor = crHand1;
:
:          LB_Cursor->Caption = PB_Image->Cursor;
: }
: //---------------------------------------------------------------------------
:
: 리소스에 추가한 마우스 커서를 crHand1, crHand2로 지정했는데
:
: 마우스 왼쪽 버튼을 누르고 있을때는 crHand2가
:
: 마우스 버튼을 누르지 않을때는 crHand1이 나와야 되는데
:
: LB_Cursor->Caption의 Cursor값은 맞게 표시되는데
:
: 실제로 Cursor Icon은 바뀌질 않습니다.
:
: 에고 어케 해결해야 하나용 ㅠ.ㅠ

+ -

관련 글 리스트
23752 Mouse Cursor가 바뀌질 않습니당 서비 727 2003/01/20
56652     Re:Mouse Cursor가 바뀌질 않습니당 smallpotato 1131 2009/04/16
31590     Re:Mouse Cursor가 바뀌질 않습니당 하느리 802 2003/01/20
31589     Re:Mouse Cursor가 바뀌질 않습니당 하느리 833 2003/01/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.