InkPresenter 방명록 만들기 - 2. 간단한 샘플 만들어보기 (작동완구)


1. InkPresenter 객체 겉핥기 (InkPresenter XAML 구조)
2. InkPresenter를 사용한 간단한 샘플 만들어보기 (작동완구)
3. Undo & Redo 구현하기
4. InkPresenter User Control 만들기
5. Color Palette User Control 만들기
6. Ink Thickness Palette User Control 만들기
7. HTTP Request와 Response를 이용하여 정보 교환하기 (Get, Post 전송)
8. Page Navigation User Control 만들기


안녕하세요. 강좌 2부네요!


오늘은 아래와 같은 Sample 예제를 만드는 과정을 설명하고자 합니다.

사용자 삽입 이미지























샘플을 작동해보실 수 있는 모델하우스 :
http://www.shiverlight.net/InkPresenterSample/InkPresenterSample


1. Page.xaml

Xaml은 Expression에서 다음과 같이 디자인을 했습니다.

사용자 삽입 이미지


사용자 삽입 이미지

















cvContent - 일단 화면 리사이즈 시 화면 중앙으로 쉽게 센터링 해주기 위해 캔버스를 만들고
이후에 만드는 모든 객체를 이 안에 넣었습니다.

ink - 강좌1부에서 설명드린 방법으로 InkPresenter 객체를 하나 추가해 두었습니다.

나머지 - 카페 링크들을 달 버튼으로 별로 중요한 것이 아닙니다.

여기서 중요한 점은 InkPresenter 위를 덮는 객체가 없게 하는 것입니다.
나머지는 별로 상관없습니다.

또, 나중에 InkPresenter객체에 Mouse Event를  추가하게 되는데, 이때 InkPresenter객체가
투명하면, Mouse Event들이 발생하지 않기 때문에 아래와 같은 방법들을 생각해 볼 수
있습니다.

1. InkPresenter에 Background를 설정해준다.
   - Background Property 에 색상만 할당
   - 또는, ImageBrush, VideoBrush 등의 Brush로도 가능


2. 사이즈와 위치가 똑같은 다른 객체(Canvas, Rectangle 따위)를 만들어 놓고,
   그 객체로부터 Mouse Event를 발생시켜서 사용한다.
  
조금 풀어서 설명을 드리면 예제처럼 배경에 사진 영역 위에 InkPresenter를 사용하고 싶을땐,
투명 InkPresenter에 ImageBrush를 이용해서 처리를 하고 InkPresenter의 Mouse Event를
사용하거나, 임의의 Canvas에 Image 넣고, InkPresenter도 넣은 다음 그 Canvas의 Mouse
Event를 사용하시면 됩니다.

2번 방법이 직관적이고 쉽다고 생각합니다만, 엄한 Canvas에서 Mouse Event를
받는 게 맘에 안들어 이 강좌에서는 1번 방법으로 해보겠습니다.

일단, 사진을 배경으로 깔기 위해 ImageBrush를 XAML 파일에 바로 적용하는 방법이 있습니다.
XAML 편집기에서 아래와 같이 적는 것이지요.

<InkPresenter x:Name="ink" Width="600" Height="400" Canvas.Left="5" Canvas.Top="5">
   <InkPresenter.Background>
      <ImageBrush ImageSource="BG_InkPresenter.jpg"/>
   </InkPresenter.Background>
</InkPresenter>


그 결과 프로그램 실행시 작동은 잘합니다만, Blend의 Design모드로 보면 이렇게 표시됩니다.

사용자 삽입 이미지
















더 이상의 디자인이 불가능해지는 것이지요.
Blend2가 지금은 Preview 버전이라 InkPresenter 객체에한 위지위그 기능은 아직 지원을
못하고 있는 것 같습니다.
그래서 일단 아래 상태로 놔두고 나중에 동적으로 ImageBrush를 설정해 주도록 하였습니다.

<InkPresenter x:Name="ink" Width="600" Height="400" Canvas.Left="5" Canvas.Top="5"/>


2. InkPresenter에 ImageBrush로 Background 깔기

Page.xaml.cs 파일 Page_Loaded(...) 함수 안에

// ink에 이미지 브러쉬로 Fill
ImageBrush ib = new ImageBrush();
ib.ImageSource = new Uri("BG_InkPresenter.jpg", UriKind.Relative);
ink.Background = ib;


3. 필요한 멤버 변수

Page 클래스의 멤버 변수로 아래 변수들을 추가합니다.
Page.xaml.cs 파일 Page 클래스 구현 상단에

// 스트로크
Stroke _strokeCurrent = null;

_strokeCurrent : 현재 사용자가 긋고 있는 획입니다.


4. MouseEvent

InkPresenter 위에 획을 긋기 위해서는 아래와 같은 Event 5종 세트를 사용하여야 합니다.

Page.xaml.cs 파일 Page_Loaded(...) 함수 안에

// InkPresenter Mouse Event 필수 4종세트
ink.MouseLeftButtonDown += new MouseEventHandler(ink_MouseLeftButtonDown);
ink.MouseMove += new MouseEventHandler(ink_MouseMove);
ink.MouseLeftButtonUp += new MouseEventHandler(ink_MouseLeftButtonUp);
ink.MouseLeave += new EventHandler(ink_MouseLeave);

각 이벤트에서 하는 일을 살펴 보면,

1) MouseLeftButtonDown 이벤트

마우스 버튼이 클릭되면 CaptureMouse를 해주고,
새 획(Stroke)를 미리 생성합니다.
새 획 생성 방법은 5. 새 Stroke 생성해주기에서 설명하겠습니다.

void ink_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
    ink.CaptureMouse();
    StartNewStroke();
}

2) MouseMove 이벤트

긋고 있는 획이 있다면, 움직임에 대한 Stylus Points를 얻어서 획(Stroke)에 누적추가해
줍니다. 즉, 획이 그어집니다.

참고> 타블렛 PC에서 Stylus 펜을 사용할 때는 이 GetStylusPoints 함수가
좀더 많은 Points를 얻어다 줍니다.

void ink_MouseMove(object sender, MouseEventArgs e)
{
    if (_strokeCurrent != null)
    {
        _strokeCurrent.StylusPoints.AddStylusPoints(e.GetStylusPoints(ink));
    }
}

3) MouseLeftButtonUp 이벤트

ReleaseMouseCapture를 호출하고, 현재 긋고 있는 획에 null을 할당합니다.
즉, 그만 그립니다.

void ink_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
    ink.ReleaseMouseCapture();
    _strokeCurrent = null;
}

4) MouseLeave 이벤트

혹시 획을 긋다가 InkPresenter 영역 밖으로 나가면,
현재 긋고 있는 획에 null을 할당합니다. 즉, 그만 그립니다.

참고> 이 이벤트를 생략하시면, 영역 바깥까지 그림이 그려집니다.

void ink_MouseLeave(object sender, EventArgs e)
{
    _strokeCurrent = null;
}


5. 새 Stroke 생성해주기

MouseLeftButtonDown 이벤트에서 StartNewStroke를 호출합니다.
그러면 새 Stroke를 만들어서, 현재 획(_strokeCurrent)라고 할당을 해주고,
ink의 Stroke Collection에 추가해 줍니다.
Stroke의 스타일은 1부의 XAML 설명에서 보셨듯이, DrawingAttributes를 통해
설정하시면 됩니다.

void StartNewStroke()
{
   _strokeCurrent = AllocStroke();
   ink.Strokes.Add(_strokeCurrent);
}

Stroke AllocStroke()
{
    // 흰색 스트로크
    Stroke stroke = new Stroke();
    stroke.DrawingAttributes.Color = Colors.White;
    stroke.DrawingAttributes.OutlineColor = Colors.Black;
    stroke.DrawingAttributes.Width = 3;
    stroke.DrawingAttributes.Height = 3;

    return stroke;
}

감사합니다.

3부 기대해 주세요.







설정

트랙백

댓글

  • 키신 2009.11.09 08:51 신고 ADDR 수정/삭제 답글

    죄송하게도 뭔말인지 하나도 모르겠네요.
    제가 따라해보니까요. Stroke라는 클래스가 없던데.. 어디서 참조해야하지요??
    전체 소스는 보여줄수 없나요?
    -아무것도 모르는 절절매는 신입이..-

    • BlogIcon 길버트 2009.11.09 09:35 신고 수정/삭제

      Stroke는 System.Windows.Ink 네임스페이스에
      포함되어있지요.

      [Visual Studio Tip]
      using을 선언 안 한 클래스를 처음 사용하실 때는
      Stroke라고 타이핑 하자마자 'e'자 아래에
      납작한 갈색 사각형이 생길 겁니다. 그러면
      1) 그 갈색 사각형을 마우스로 클릭하여
      using 문을 자동으로 추가하시거나.
      2) Ctrl + . 단축키를 이용하여
      using 문을 자동으로 추가하시면 편합니다.

  • 키신 2009.11.09 08:55 신고 ADDR 수정/삭제 답글

    위에 소스가 있긴한데.. 다운받아서 프로젝트 열기를 해볼라니 안되네요. 잘못된 주소를 import한다고 합니다.

    • BlogIcon 길버트 2009.11.09 09:40 신고 수정/삭제

      2007년도에 작성된 이 포스트는 실버라이트 1.1을
      기준으로 하고 있구요.

      실버라이트 1.1과 실버라이트 3사이에는 엄청난
      Breaking Changes가 존재하기 때문에 프로젝트
      변환이 불가능합니다.

      결국 현재 실버라이트 3 개발환경에서는
      위 프로젝트를 여실 수가 없습니다.

      대신 실버라이트 3의 새 프로젝트를 만드시고,
      위 프로젝트가 포함하고 있던 파일을 일부 옮겨 놓으신 다음,
      부분적으로 손보시면 큰 어려움 없이 되살려
      내실 수 있을 것 같습니다.