2010. 3. 18. 00:03

C#에서 Managed Gesture API 이용.

안녕하세요,


저 같이 헤메이시는 분을 위한 팁 공유 합니다.

혹시 C# 에서 Managed Gesture API 사용하신 분들.. 낭패 보신분 없으신지요.

저의 경우, 제스쳐가 걸린 패널이 포커스를 잃은 후 일정 시간 이후 (랜덤하게.) 해당 패널로 돌아왔을때 제스쳐 이벤트가 제대로 발생 하지 않는 문제가 있었습니다. 도무지 원인을 알 수가 없었죠.
(마찬가지로, msdn 포럼 내에서도, 버튼을 더블 클릭하고 나면 제스쳐 이벤트가 뜨지 않는다는지 하는 비슷한 문제들이 다수 있었습니다. 다 같은 원인이었겠죠.)

그래서 관련 포럼글을 찾아보던 중에 문제 해결법을 찾았습니다.

관련 문제 글 링크:

이곳에 가시면 Download 탭에서 Gesture.dll 의 소스를 구하실 수 있습니다.
소스에서 일부분 수정하여 dll 을 다시 만드시면 됩니다. 내용 하단에 옮겨둡니다.

------------------------------------------------------------------------------------------------------------
댓글 내용:
The automatically generated delegates (using the implicit casts from a method to a delegate) can be garbage collected at any time, after the first garbage collection the gesture detection will stop working. To fix this problem a reference to the delegate must be stored in the GestureRecognizer class (AutoGestureContext also suffers from the same problem).
applying this patch should fix the problem.

자동으로 생성되는 delegate 들은 언제라도 가비지 콜렉팅 될 수 있기에, 처음 가비지 콜렉션이 실행되고 나면 제스쳐 탐지가 작동하지 않는다. 이 문제 해결을 위해서는 delegate의 참조객체가 GestureRecognizer 클래스 안에 있어야만 한다. 아래와 같이 하면 문제가 해결된다.

--- GestureRecognizer.cs 2009-08-26 11:53:24.000000000 -0000
+++ GestureRecognizer.cs 2010-02-26 09:46:33.000000000 -0000
@@ -30,12 +30,13 @@
private static readonly object EndEvent = new object();
private static readonly object SelectEvent = new object();
private static readonly object DoubleSelectEvent = new object();
private static readonly object HoldEvent = new object();
private static readonly object PanEvent = new object();
private static readonly object ScrollEvent = new object();
+ private WndProcHook wndProcHook = null;

private Control targetControl;

///


/// Initializes a new instance of the GestureRecognizer class
///


@@ -36,27 +37,31 @@

private Control targetControl;

///


/// Initializes a new instance of the GestureRecognizer class
///


{
if (value != this.targetControl)
{
if (this.targetControl != null)
{
// remove the WndProc hook for the previous targetControl
- Hook.RemoveHook(this.targetControl, WndProc);
+ if (wndProcHook != null)
+ {
+ Hook.RemoveHook(this.targetControl, wndProcHook);
+ }
this.targetControl = null;
}

if (value != null)
{
// add the WndProc hook for the current targetControl
this.targetControl = value;
- Hook.AddHook(this.targetControl, WndProc);
+ wndProcHook = new WndProcHook(WndProc);
+ Hook.AddHook(this.targetControl, wndProcHook);

}
}
}

}
------------------------------------------------------------------------------------------------------------

보시면 아시다시피, GestureRecognizer.cs 파일을 여시고, 일부 소스를 추가합니다. (댓글 내용대로, WndProc 딜리게이터의 참조 변수가 추가됩니다.) 제가 파란색으로 색깔구분 해 두었습니다. + 표시가 된 라인이 추가 및 수정 라인입니다.

결론은.... 제 프로그래밍 미스가 아니었다는 겁니다. -_- 분명 내가 뭘 잘못 했지라며 저처럼 헤메이고 계신 분들 많으리라 생각하면서 꼭 도움이 되길 바랍니다. 흑흑.