Microsoft MVP성태의 닷넷 이야기
Mouse이벤트 관련해서 질문있습니다. [링크 복사], [링크+제목 복사]
조회: 13664
글쓴 사람
이성환 (vactorman at naver.com)
홈페이지
첨부 파일
다른 플랫폼에서 해보진 않아서 잘 모르겠습니다만

WPF에서 Mouse 관련 이벤트들이 예상과 다르게 동작하는 것이 있어서 질문드립니다.

예를 들어 Rectangle에 MouseEnter / Leave / Up / Down 이벤트 핸들러를

Preview와 함께 모두 연결했습니다.

그랬을 때 Rectangle을 한 번 클릭하면

Preview Mouse Left Button Down
Preview Mouse Down
Mouse Left Button Down
Mouse Down
Preview Mouse Left Button Up
Preview Mouse Up
Mouse Left Button Up
Mouse Up

뭐 이런 순서로 이벤트가 발생할 거라고 예상 하는데요.




네. 예상대로 잘 발생합니다.



그런데

Rectangle을 Button의 자식. 그러니까 Button의 Content로 넣은 후

다시 클릭하면



Preview Mouse Left Button Down
Preview Mouse Down
Mouse Left Button Down
Mouse Down
Mouse Leave

(이 시점에서 Mouse Up 했습니다.)
Mouse Enter



이렇게 이벤트가 발생합니다.

문제는 Rectangle에 걸어놨던 MouseUp이벤트 들이 하나도 발생하지 않는다는 것이죠.

또 저 MouseLeave가 발생하는 시점에서 Rectangle의 IsMouseOver 값을 확인하면 false가 나옵니다.

Mouse Down 상태에서 MouseLeave 이벤트가 발생한 것도 이상한데

마우스 포인터가 Rectangle을 벗어나지 않았음에도 IsMouseOver가 false로 나오는 것 역시 이해가 잘 안 됩니다.


그런데 더 이상한 건

Rectangle의 PreviewMouse 이벤트 핸들러에서 Break Point를 걸고 다시 테스트 하면

위와 다른, 정상적인 결과 (처음 예상했던 결과)가 나옵니다.

결과가 이상해서 추가한 Button에도 동일하게

PreviewMouseLeftButtonDown, PreviewMouseLeftButtonUp, PreviewMouseDown, PreviewMouseUp, MouseDown, MouseUp, MouseEnter, MouseLeave

그리고 Click 이벤트 핸들러를 연결하고 다시 테스트 해보니

Button의 PreviewMouseLeftButtonDown, PreviewMouseDown, MouseDown 이벤트들이 발생하지 않았습니다.
(물론 Button의 자식으로 들어가 있는 Rectangle은 앞서 언급한 비정상적인 결과와 동일했습니다.)

가장 마지막에 발생한 이벤트는 Click 이벤트였습니다.


제가 WPF의 Mouse 이벤트에 대해 이해를 잘못 하고 있는 건지

원래 이런 건지 잘 모르겠습니다.

당장 필요한 건 MouseUp 이벤트를 받는 건데 어떻게 해야할 지 감이 안 잡힙니다.


혹시나 해서 간단한 테스트 솔루션하나 첨부해볼게요.

확인 부탁드립니다.



[연관 글]


donaricano-btn



[최초 등록일: ]
[최종 수정일: 7/13/2011 ]


비밀번호

댓글 쓴 사람
 



2011-07-13 05시40분
[이성환] 아.. 수정하다 실수로 파일이 두개가 돼 버렸네요. 둘 다 같은 파일 입니다. 하나만 보시면 될듯...
[손님]
2011-07-15 08시23분
[이성환] 혼자 이것저것 테스트 해보면서 어설프게나마 결론에 도달했습니다.

Button 내부의 Element들에게서 MouseLeaver가 발생하는 이유는

Button의 MouseDown 이벤트가 도착할 때 Button 스스로 CaptureMouse를 하기 때문이더군요.

비단 Button 뿐만 아니라 자식을 가진 Element의 경우에도 마찬가지로

부모가 CaptureMouse를 하면 그 순간 자식들에게 모두 MouseLeave 이벤트가 떨어졌습니다.

당연히 MouseLeave 이후 MouseEnter나 MouseDown이 일어나지 않았으니 MouseUp 역시 발생하지 않은 거구요.

Button 이 CaptureMouse를 하는 지는 이번에 처음 알았습니다.

어쩔 수 없이 MouseUp을 대체하는 방법으로 돌고 돌아서 MouseUp과 유사한 형태의 이벤트 처리를 하긴 했지만

생각보다 사소하다고 여겼던 것에 한 번 당하고 나니

이벤트 처리, 특히 마우스 관련 처리는 한 번 더 고민하고 사용하게 됐네요.

[손님]
2011-07-15 08시25분
[이성환] 근데 궁금한 건.

왜 Button에는 버블링 MouseDown / Up 이벤트가 발생하지 않을까요?

암만 찾아봐도 PreviewMouseDown / Up 까지는 들어오는데 버블링 MouseDown / Up 이벤트는 발생하지 않네요.

왜 그런건가요??
[손님]
2011-07-18 07시28분
제가 WPF 손을 놓은지 꽤나 오래 되어서 ^^ 관련 지식도 희미해지는 바람에 답변이 너무 늦었습니다.

일단, 이벤트 버블링과 터널링이 있는데요.

WPF Input Events
; http://msdn.microsoft.com/en-us/library/ms742806.aspx#how_event_processing_works

버블링은 부모요소로 이벤트를 전달하는 것이기 때문에 "Button에서 버블링이 왜 안되느냐"는 질문은 올바르지 않습니다. ^^ Button의 하위요소인 Rectangle에 이벤트가 내려가는 것이므로 Tunneling 이 왜 안되냐가 맞습니다.

이성환님이 직접 살펴보신데로, 아마도 마우스의 캡쳐가 원인이지 않을까 싶습니다. ^^ Win32 시절부터 윈도우 영역을 벗어나는 경우에도 마우스 이벤트를 유지해야 하는 경우 SetCapture/ReleaseCapture 함수를 호출하는 동작이 있었습니다.

버튼의 경우, 마우스를 누른 체로 윈도우 영역을 벗어나도 여전히 마우스가 캡쳐된 상태이기 때문에 다시 누른 체로 마우스를 버튼 위로 이동해서 버튼을 떼면 Click 이벤트가 발생하게 됩니다. 즉, 다른 요소보다는 특별한 동작이 요구되는데, 이러한 처리 때문에 이벤트 터널링에 영향이 있는 것 같습니다.

일단 현상이 그러하니, 다른 방법을 찾아야 할텐데 터널링이 안되므로 자식 요소에서 직접 부모 요소의 Up 이벤트를 감시하는 방법이 어떨까 싶습니다. 이를 위해 버튼이 버블링해 주는 Up 이벤트를 가로채면 되겠지요. ^^

xButton.AddHandler(MouseUpEvent, new MouseButtonEventHandler(mouseUpEvent), true);

어쨌든, 이성환님 덕분에 저도 버튼의 이벤트 처리에 대한 생각을 다시 해볼 수 있게 되었군요. ^^

(참고로, 마지막 질문에서 헷갈리신 것 같은데 PreviewMouseDown/MouseDown은 잘 들어오는데, PreviewMouseUp/MouseUp이 안되는 것입니다. ^^)
정성태
2011-07-18 09시20분
[이성환] 답변 감사드립니다. (__)

그런데.. 제가
왜 Button에는 버블링 MouseDown / Up 이벤트가 발생하지 않을까요? 라고 질문했던 건

xButton의 MouseDown/Up 이벤트가 발생하지 않는다는 의미였습니다.

실제로 Output을 찍어보면

xButton_MouseEnter Button Captured : False
xRootGrid_MouseEnter Button Captured : False
xMainRectangle_MouseEnter Button Captured : False
== 요기까지는 클릭을 위해 MouseEnter 되는 시점.

== 요기서부터 MouseLeftButtonDown
xRootGrid_MouseLeave Button Captured : False
xButton_PreviewMouseDown Button Captured : False
xRootGrid_PreviewMouseLeftButtonDown Button Captured : False
xRootGrid_PreviewMouseDown Button Captured : False
xMainRectangle_PreviewMouseLeftButtonDown Button Captured : False
xMainRectangle_PreviewMouseDown Button Captured : False
xMainRectangle_MouseLeftButtonDown Button Captured : False
xMainRectangle_MouseDown Button Captured : False
xRootGrid_MouseLeftButtonDown Button Captured : False
xRootGrid_MouseDown Button Captured : False
xMainRectangle_MouseLeave! Button Captured : True
xRootGrid_MouseLeave Leave Button Captured : True
== 요기까지가 MouseLeftButtonDown 후 그대로 유지 상태.

== 요기서부터 MouseUp
The thread '<No Name>' (0x880) has exited with code 0 (0x0).
xButton_PreviewMouseLeftButtonUp Button Captured : True
xButton_PreviewMouseUp Button Captured : True
xMainRectangle_MouseEnter Button Captured : False
xRootGrid_MouseEnter Button Captured : False
xButton_Click Button Captured : False

요런 형태 인데요.

보시다 시피

xButton_PreviewMouseDown
xButton_PreviewMouseLeftButtonUp
xButton_PreviewMouseUp
xButton_Click 까지는 발생하고

나머지 버블링 관련 이벤트들은 하나도 발생하지 않았는데요. (당연히 핸들러는 다 걸려있구요.)

왜 xButton에 버블링 이벤트가 하나도 발생하지 않았는지는 아직 답을 찾지 못해서 질문드린 것이었습니다.
(그러고 보니 xButton_PreviewLefrButtonDown도 발생하지 않았네요..)

요거까지 확인을 해야 시원하게 원인파악을 했다고 말할 수 있을 것같아서요...;ㅅ;

[손님]
2011-07-18 09시42분
아래의 글에 별도로 답변을 달았으니 참고하세요. ^^

왜? Button 컨트롤에는 MouseDown/MouseUp 이벤트가 발생하지 않을까요?
; http://www.sysnet.pe.kr/2/0/1089

그리고, 마지막 댓글에서 xButton_PreviewLeftButtonDown 도 발생하지 않는다고 쓰셨는데... 발생합니다. 왜 발생하지 않은 듯(?) 보인 것인지, 다시 한번 소스 코드를 점검해 보세요. ^^
정성태
2011-07-18 11시01분
[이성환] 매번 친절한 답변 감사드립니다.

근데 제가 우매하여... 아직도 이해가 되질 않습니다.

일단 제가 첨부한 소스에서는 e.Handled = true; 가 없습니다.
(요건 알고 있던 거라..)

그런데 저는 제가 첨부한 소스로 해봐도, 제가 테스트 하던 소스로 해봐도

역시 xButton의 버블링 이벤트는 발생하지 않습니다.
(xButton_PreviewMouseLeftDown 역시 발생하지 않습니다.)

이벤트 전달을 막은 곳도 없고
(e.Handled = true로 막았다고 이벤트가 전달 안 되는 건 아니니까 더 이상합니다.)

해당 이벤트의 핸들러가 등록되어있지 않은 것도 아닌데

포스팅 해주신 글을 몇 번 읽어봐도

왜 이벤트가 발생 안 하는지 모르겠습니다.
(정확히는 왜 핸들러를 호출하지 않는 건지)

혹시 같은 소슨데 저만 안 되는 건가요??

;ㅅ;

[손님]
2011-07-18 11시03분
[이성환] 아.. PreviewMouseLeftDown 은 Output을 잘못 찍고 있었군요...

이건 찾았습니다...;;;

그럼 xButton의 버블링 이벤트만 확인하면 되겠군요....;;;
[손님]
2011-07-19 12시34분
음... ^^ 제가 쓴 글은, WPF의 Button 컨트롤도 같은 방식으로 되어 있다는 것을 설명해 드린 것입니다. .NET Reflector로 버튼 쪽 소스를 보면 MouseLeftButtonDown 이벤트에서 e.Handled = true를 걸고 있기 때문에 Bubbling이 발생하지 않는 것입니다.
정성태
2011-07-19 08시54분
[이성환] 아.. 그렇군요. Button 내부에서 이미 e.Handled = true 처리를 하고 있어서

버블링 이벤트가 발생 안 하는 것이었군요. ;;;;

포스팅에서 링크 걸어 놓으신 social 게시판에서도 질문자가 저와 동일한 질문을 한 번 더 했고

그 다음 답변에 Snoop을 써서 이벤트 구조를 확인해보라는 걸로 마무리가 나 있길래

이거 그냥은 모르는 거구나 했습니다.

그리고 제가 아직 그 정도까지 Reflector를 잘 쓰질 못해서 내부 소스 보는 게 꺼려지더군요.

이 기회에 공부 좀 해야겠습니다.

덕분에 많이 배웠습니다. ~ㅂ~

매번 좋은 글과 답변 주셔서 감사합니다 (__)
[손님]

... 31  32  33  34  35  36  37  38  39  40  41  42  [43]  44  45  ...
NoWriterDateCnt.TitleFile(s)
1112이대근12/18/20129476[질문] odp.net 배포 관련 궁금한게 있어서 질문좀 드릴게요 [3]
1111나그넹!12/13/20126938안녕하세요. 파일전송에 관련해서 궁금한것좀 여쭈고싶네요. [1]
1110김동현12/11/20128724안녕하세요 닷넷 신입개발자입니다 Clickonce 질문좀 하겠습니다. [6]파일 다운로드1
1109김성우12/5/20126203WCF IIS 호스팅 관련하여 질문 드립니다. [1]
1123윤용한3/13/20135067    답변글 [답변]: WCF IIS 호스팅 관련하여 질문 드립니다.
1107우라미윰11/22/201210959안녕하세요. RSA공개키 알고리즘에 나와있는 글을 보고 응용을 해야 하는데 막히는 부분이 있어서 질문드립니다. [3]파일 다운로드1
1106초급11/21/20126157WCF Server 인증서 및 Client 인증서 문의 [1]
1104hon11/17/20125920VS2008에서 디버그/릴리즈 환경중에 디버그 환경의 빌드시 배열의 자동 초기화 라는 것에 대해서 궁금합니다. [3]
1102최년호11/15/20127625[탭 브라우저의 윈도우 핸들 구하기] 예제에서 활성화 방법 [1]
1100박진영11/7/201211809[긴급] 코드 액세스 보안 정책(CASPOL.exe) 설정해도 SmartClient 보안에러가 발생합니다. [6]
1099Hyeyoung Kang10/22/20127514php에서 c file compile [4]
1095이지은10/8/201223692중단점이 현재 적중되지 않았습니다 [2]
1094고민남10/6/20125816NScreen 에 대해 어떻게 생각하십니까? [1]
1093이지수10/6/20125190vbs [1]
1092김성수9/20/20126351안녕하세요? MS Windows server 2008 R2 에서 IIS7 의 SSL 설정시에 에러 해결좀 도와주세요 [1]
1089한상욱9/13/20126112azure에 관한 질문입니다. [1]
1088김영대9/12/20128005DirectX.AudioVideoPlayBack 참조하여 wav 재생기를 제작하여 SmartClient 를 이용하여 aspx 페이지에 Embed 하는 과정의 질문 사항입니다. [2]
1087한우주9/10/20128904SSL 모든 웹페이지에 적용해야하나요? [2]
1086한우주9/4/20127447SSL 인증서 범용으로 사용하기 [3]
1085한우주9/4/20126328개발환경구성 18.3.1 에 대한 문의 [2]파일 다운로드1
1084김종하9/3/20127165team foundation express 2012에서 새 프로젝트 생성... [3]
1082김대경8/23/20126327windows2008 에서 ActiveX 사용 시 문제점. [3]
1091김대경9/20/20126414    답변글 [답변]: windows2008 에서 ActiveX 사용 시 문제점. [2]파일 다운로드1
1081SeongSu Yun8/20/20128473WCF 파일 업,다운로드 문제 [2]
1080배동선8/13/20127015정품 라이센스 인증 개발에 대해 조언을 구하고 싶습니다 [4]
1079송준호8/11/20125878basicHttpBinding stream 전송에 관하여 질문드립니다. [1]
... 31  32  33  34  35  36  37  38  39  40  41  42  [43]  44  45  ...