'Stroke'에 해당되는 글 2건

  1. 2007/12/14 InkPresenter 방명록 만들기 - 6. Stroke Size Controler User Control 만들기 (4)
  2. 2007/10/11 InkPresenter 방명록 만들기 - 2. 간단한 샘플 만들어보기 (작동완구)
2007/12/14 16:19

InkPresenter 방명록 만들기 - 6. Stroke Size Controler User Control 만들기

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

사용자 삽입 이미지


5주만에 강좌를 재계합니다. 정말 바빴습니다. 믿어주십시오!

그 사이 Silverlight Demo 사이트 쉬버라이트닷넷을 약간 단장하였구요.
저희 회사 휴즈플로우의 웹사이트도 간단하게 만들어서 오픈을 하였습니다.

0. Sample Project

체험장 :  http://shiverlight.net/InkPresenterSample/InkPresentationSample_StrokeSize


1. Stroke Size Controler User Control 디자인 (UCStrokeSize.xaml)

진행하기에 앞서 다음 포스트를 읽어보실 것을 권장합니다.

   Blend를 통해 User Control 추가하기

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

위와 같이 디자인이 되었습니다.
이제 XAML 엘리먼트 트리만 보셔도 감이 팍팍 오시죠?

XAML 엘리먼트 트리 맨 아래의 HFSlider _oSizeSlider는 아래와 같은 모습의
녀석으로 Slider 역할을 소화하는 녀석입니다. 자세한 사항은 소스를 참고해 주십시오.

사용자 삽입 이미지


3. Stroke Size Control 비하인드 코드 작성 (UCStrokeSize.xaml.cs)

기본적인 것들은 이전 강좌와 비슷하므로 설명하지 않겠습니다. (소스를 보시면 아실 겁니다. ^^)
여기서는 Slider와 관련된 부분만 설명을 드리도록 하겠습니다.

XAML에 추가한 Slider를 참조하기 위해서 클래스에 다음 변수를 추가합니다.

// 슬라이더
HFSlider _oSizeSlider;

생성자나 Loaded 함수에 아래와 같은 코드를 추가하여,
실제 객체를 찾아 연결해주고 Slider에 관련된 설정을 해줍니다.

// 슬라이드를 2~40까지의 정수 값을 가지게 하고, Current Value를 1/2 하여 Stroke 사이즈로 사용한다.
_oSizeSlider = _cvMyself.FindName("_oSizeSlider") as HFSlider;
_oSizeSlider.NumberType = NumberType.Integer;
_oSizeSlider.MinValue = 2;
_oSizeSlider.MaxValue = 40;
_oSizeSlider.ValueChanging += new EventHandler(_oSizeSlider_ValueChanging);
_oSizeSlider.ValueChanged += new EventHandler(_oSizeSlider_ValueChanged);


결과적으로 Slider는 2~40 사이의 범위 안에서 정수를 반환해 주게 됩니다.
이것은 0.5 단위의 Stroke Size를 얻어내기 위해서 사용한 꼼수 입니다. (주석 참조)

이벤트가 2가지 보이는데,
ValueChanging은 사용자가 Slider의 Handle을 잡고 움직이는 동안(MouseMove)에도 이벤트가 발생하고,
ValueChanged는 사용자가 Slider를 움직이다가 손을 때었을 때(MouseLeftButtonUp) 이벤트가 발행합니다.

void _oSizeSlider_ValueChanging(object sender, EventArgs e)
{
    // 스트로크 사이즈를 업데이트
    StokeSize = GetStrokeSizeFromSlider();
}

void _oSizeSlider_ValueChanged(object sender, EventArgs e)
{
    // 스트로크 사이즈를 업데이트
    StokeSize = GetStrokeSizeFromSlider();

    // 이벤트 발생
    OnSizeChanged();
}

그럼, StokeSize 프로퍼티의 set을 살펴보면 값이 할당되면 동적으로 어떤 일들을 하는지 보실 수 있습니다.

// 스트로크 사이즈
double _dStrokeSize;
public double StokeSize
{
    get { return _dStrokeSize; }
    set
    {
       _dStrokeSize = value;
       _oSizeSlider.CurrentValue = _dStrokeSize * 2;

       // Outline Thickness 고려
       _elSize.Width = _dStrokeSize + 4;
       _elSize.Height = _dStrokeSize + 4;

       _elSize.SetValue(Canvas.LeftProperty, (_cvCurSize.Width - _elSize.Width) / 2);
       _elSize.SetValue(Canvas.TopProperty, (_cvCurSize.Height - _elSize.Height) / 2 - 3);

       _tbSize.Text = string.Format("{0:F1}", _dStrokeSize);
       _tbSize.SetValue(Canvas.LeftProperty, (_cvCurSize.Width - _tbSize.ActualWidth) / 2);
    }
}


4. 샘플 프로젝트에 적용


Page.xaml을 Blend에서 Open 합니다.

Asset Library를 통해서 UCStrokeSize User Control을 Page.xaml에 추가합니다.
(만약 모르시는 부분이면 다음 포스트를 먼저 읽으십시오. http://gilverlight.net/2674)

사용자 삽입 이미지

이름을 _oStrokeSize라고 줍니다.

Page.xaml.cs의 생성자에서 다음과 같이 초기화를 해줍니다.

// Stroke Size Controler 설정
_oStrokeSize.StokeSize = _dInitialStrokeSize;
_oStrokeSize.Color = _oPalette.Color;
_oStrokeSize.SizeChanged += new EventHandler(_oStrokeSize_SizeChanged);

SizeChanged 이벤트를 구현해 줍니다.

void _oStrokeSize_SizeChanged(object sender, EventArgs e)
{
    _oInkEditor.StrokeSize = new Size(_oStrokeSize.StokeSize, _oStrokeSize.StokeSize);
}

팔레트의 색상이 변경될 때마다 Stroke Size Controler에서도 자기가 보여주고 있는
Stroke 미리보기의 색상을 변경해 줍니다.

void _oPalette_ColorChanged(Color color)
{
    _oInkEditor.StrokeColor = color;
    _oStrokeSize.Color = color;
}

이제 Stroke Size Controler 추가가 끝났습니다.

사용자 삽입 이미지

간단하죠?


5. 보너스 팁

<부제 : 그리는 도중 InkPresenter 영역을 벗어났다 들어와도 계속 그려지게 하는 방법>

UCInk.xaml.cs에 간단히 bool 변수 하나를 이용해서 구현합니다.

일단 아래와 같이 변수를 하나 추가해 주십시오.

// 영역 밖에 나갔다 들어와도 그려지게 해줌
private bool _bDrawContinue = false;

전에 없던 MouseEnter 이벤트를 추가합니다.

public UCInk(Size sz, bool bEditable)
{
    (전략...)

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

void _ink_MouseEnter(object sender, MouseEventArgs e)
{
    if (_bDrawContinue == true)
    {
       StartNewStroke(e.GetStylusPoints(_ink));
    }
}

_bDrawContinue의 값을 MouseLeftButtonDown에서 true, MouseLeftButtonUp에서 false로 설정합니다.

void ink_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
    if (Editable == false)
 return;

    _ink.CaptureMouse();
    StartNewStroke(e.GetStylusPoints(_ink));
    _bDrawContinue = true;
}

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

이렇게 하면 그리는 도중 영역 밖을 나갔다 들어와도 계속해서 그림이 그려집니다.

이것으로 이번 강좌를 마칩니다.

감사합니다.




 

이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 Comment 4

Trackback : http://gilverlight.net/trackback/2673 관련글 쓰기

  1. 구피 2008/02/27 12:02 address edit & del reply

    정말 잘만드셨네요

    디자인도 너무 깔끔해...ㅠㅠ요

  2. BlogIcon 길버트 2008/02/28 00:11 address edit & del reply

    안녕하세요! 길버트 이길복입니다.
    그렇게 말씀해 주시니 감사합니다!
    강좌를 아직 마무리 짓지 않아서 죄송할 따름입니다.

  3. ^^ 2008/10/14 13:20 address edit & del reply

    나머지 강좌 어서해주세용 ㅠㅠ
    감사히 잘 볼게요 ~

    • BlogIcon 길버트 2008/10/15 09:44 address edit & del

      죄송합니다. ㅜ_ㅠ
      요즘 눈코뜰새없이 바빠서
      강좌를 못쓰겠네용...

2007/10/11 13:10

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부 기대해 주세요.






이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 Comment 0

Trackback : http://gilverlight.net/trackback/2601 관련글 쓰기