SilverLight

마우스 Drag and Drop 탐색記 (2편)

손병환 2007. 12. 20. 22:02

실버라이트는 Canvas에 객체를 담고 있다. 일반적으로 객체를 담아두는 부모객체로서 Canvas를 사용한다. 지난번에 언급했듯이 객체가 부모에 담겨 있는 경우 부모와 객체가 같은 이벤트를 가질 경우 어떤 상태가 되는지에 대해서 썰을 풀어보자.

 

Canvas에 객체를 담아두고 동일한 이벤트를 구현했을 경우에는 각각 이벤트의 종류에 따라서 조금씩 차이가 나는 것 같다. MouseLeftButtonClick 부모의 이벤트가 먼저 실행되고 나중에 자식의 이벤트가 실행된다. 그리고 MouseMove는 동일한 이벤트의 메소드명을 자식과 부모가 가지게 되면 항상 부모만 실행된다.

 

아직 왜 그런지에 대해서 정확하게 답을 할 수 있을 정도로 대답을 하기 힘들다. 조만간에 조금씩 이런 부분들에 대해서 다른 사이트를 통해서 해답을 찾게 되면 다시 글을 작성하겠다. (정말 부끄럽다~~ *^^*)

 

이전 강좌의 샘플을 이용해서 조금씩 변경을 해 보기 바란다.

그러면 대략적인 마우스 이벤트에 대해서 어느 정도 내공이 생길 것이다.

 

한가지 주의할 점이 있는데 Canvas의 사이즈 이다. 녹색 사각형을 클릭하고 클릭을 유지한 상태로 마우스를 최대만 멀리 이동시켜 보자. 여기서 최대한 멀리란 xxxxx.html내부에 설정된 silverlight의 사이즈를 벗어나는 것을 말한다. 이 Canvas를 벗어나는 순간 모든 마우스 이벤트는 사라진다. captureMouse() 메소드도 사라지고 더이상 좌표 계산도 안된다. 아주 당연한 이야기 같지만 만약 프레임이 구분된 곳에서 드래그 앤 드롭을 구현할려면 아마도 이런 문제가 가능 큰 이슈가 될 것 같은 느낌이 든다. 즉, 현재 작업중인  SilverLight의 Canvas를 벗어나면 모든 마우스 이벤트가 초기화 되어 버리는 것이다. 이것도 해결 방법을 아마도 찾아봐야 할 것 같다. (웬지 숙제만 잔뜩 남기는 듯한 느낌이 든다. 에궁..!~@@!~@~)

 

아래에는 지난 번 강좌의 샘플을 조금 수정해서 응용을 해 본 내용을 올린다.

 

XAML소스 코드

Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Height="180" Width="300"
  Background="PowderBlue">

 

 <Rectangle
   x:Name="Green"
   MouseMove=onMouseMove"
   MouseLeftButtonDown=onLeftButtonDown"
   MouseLeftButtonUp=onLeftButtonUp"

   Width="100" Height="100"
   Fill="Green" />

 

 <!-- The MouseMove event handler function is shared with the first rectangle -->
 <Canvas Canvas.Left="120" Width="100" Height="100"
   MouseLeftButtonDown=onMouseClick" MouseMove="onParentMouseMove" x:Name="ParentRedCanvas">
  <Rectangle
    x:Name="Red"
    MouseMove="onMouseMove"
    Canvas.Left="0"
    Width="100" Height="100"
    Fill="Maroon" MouseLeftButtonDown=onMouseClick" />
 </Canvas>

 

 <TextBlock
   x:Name="statusTextBlock"
   FontSize="18"
   Canvas.Top="120" />

 

 <TextBlock
   x:Name="statusTextBlock2"
   FontSize="18"
   Canvas.Top="140" />
</Canvas>

 

아래의 코드는 자바 스크립트 이다.

 

// Display the current mouse position for the Rectangle object.
function onMouseMove(sender, mouseEventArgs)
{
    var msg = "x:y = " + mouseEventArgs.getPosition(null).x + ", " + mouseEventArgs.getPosition(null).y;
    sender.findName("statusTextBlock").Text = sender.Name + ": " + msg;
}

// Enable mouse capture when the mouse is depressed over the green Rectangle object.
function onLeftButtonDown(greenRect, mouseEventArgs)
{
    greenRect.captureMouse();
}

// Disable mouse capture when the mouse is released over the green Rectangle object.
function onLeftButtonUp(greenRect, mouseEventArgs)
{
    greenRect.releaseMouseCapture();
}

function onParentMouseMove(sender, eventArgs)
{
    var msg = "x:y = " + eventArgs.getPosition(null).x + ", " + eventArgs.getPosition(null).y;
    sender.findName("statusTextBlock2").Text = sender.Name + ": " + msg;
}

function onMouseClick(sender, eventArgs)
{
    alert!(sender.Name + ' : Clicked!!');
}

 

끝으로 드래그 앤 드랍 전체 소스를 올린다. 이 소스는 검정원이 사각형을 벗어나지 않도록 마우스 왼쪽 버튼을 눌렀을 때의 마우스 좌표를 변수에 담아서 사각형의 위, 아래, 왼쪽, 오른쪽과의 거리를 계산한다. 계산하는 코드는 MouseMove이벤트에 담고 있다.

 

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Rectangle Width="300" Height="150" Stroke="Orange" StrokeThickness="15" />
        <Ellipse Width="50" Height="50" Fill="Black" Canvas.Left="20" Canvas.Top="20"
                MouseLeftButtonDown="mouseInit”
                MouseLeftButtonUp="mouseRelease”
                MouseMove="mouseMove” />
</Canvas>


var startX, startY, lastX, lastY;
var minX = 15;
var maxX = 235;
var minY = 15;
var maxY = 85;
var moving = false;

 

function mouseInit(sender, eventArgs) {
    sender.captureMouse();
    startX = sender['Canvas.Left'];
    startY = sender['Canvas.Top'];
    lastX = eventArgs.getPosition(null).x;
    lastY = eventArgs.getPosition(null).y;
    moving = true;
}

 

function mouseRelease(sender, eventArgs) {
    sender.releaseMouseCapture();
    moving = false;
    var x = sender['Canvas.Left'];
    var y = sender['Canvas.Top'];
    if (x < minX || x > maxX || y < minY || y > maxY) {
        sender['Canvas.Left'] = startX;
        sender['Canvas.Top'] = startY;
    }
}

 

function mouseMove(sender, eventArgs) {
    if (moving) {
        var x = eventArgs.getPosition(null).x;
        var y = eventArgs.getPosition(null).y;
        sender['Canvas.Left'] += x - lastX;
        sender['Canvas.Top'] += y - lastY;
        lastX = x;
        lastY = y;
    }
}

 

점점 해결해야할 숙제들만 늘어나는 것만 같아서 무척 부담스럽다. 에궁...~~!~ 공부할 시간도 많이 없는데...(핑계)


참고도서 : Essential SilverLight (O'REILLY), SilverLight 1.0 - Development with JavaScript.chm