'Stroke'에 해당되는 글 2건
InkPresenter 방명록 만들기 - 6. Stroke Size Controler User Control 만들기

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에 관련된 설정을 해줍니다.
_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) 이벤트가 발행합니다.
{
// 스트로크 사이즈를 업데이트
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의 생성자에서 다음과 같이 초기화를 해줍니다.
_oStrokeSize.StokeSize = _dInitialStrokeSize;
_oStrokeSize.Color = _oPalette.Color;
_oStrokeSize.SizeChanged += new EventHandler(_oStrokeSize_SizeChanged);
SizeChanged 이벤트를 구현해 줍니다.
{
_oInkEditor.StrokeSize = new Size(_oStrokeSize.StokeSize, _oStrokeSize.StokeSize);
}
팔레트의 색상이 변경될 때마다 Stroke Size Controler에서도 자기가 보여주고 있는
Stroke 미리보기의 색상을 변경해 줍니다.
{
_oInkEditor.StrokeColor = color;
_oStrokeSize.Color = color;
}
이제 Stroke Size Controler 추가가 끝났습니다.
간단하죠?
5. 보너스 팁
<부제 : 그리는 도중 InkPresenter 영역을 벗어났다 들어와도 계속 그려지게 하는 방법>
UCInk.xaml.cs에 간단히 bool 변수 하나를 이용해서 구현합니다.
일단 아래와 같이 변수를 하나 추가해 주십시오.
private bool _bDrawContinue = false;
전에 없던 MouseEnter 이벤트를 추가합니다.
{
(전략...)
// 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로 설정합니다.
{
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;
}
이렇게 하면 그리는 도중 영역 밖을 나갔다 들어와도 계속해서 그림이 그려집니다.
이것으로 이번 강좌를 마칩니다.
감사합니다.
InkPresenter 방명록 만들기 - 2. 간단한 샘플 만들어보기 (작동완구)

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 만들기
오늘은 아래와 같은 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.Background>
<ImageBrush ImageSource="BG_InkPresenter.jpg"/>
</InkPresenter.Background>
</InkPresenter>
그 결과 프로그램 실행시 작동은 잘합니다만, Blend의 Design모드로 보면 이렇게 표시됩니다.
더 이상의 디자인이 불가능해지는 것이지요.
Blend2가 지금은 Preview 버전이라 InkPresenter 객체에한 위지위그 기능은 아직 지원을
못하고 있는 것 같습니다.
그래서 일단 아래 상태로 놔두고 나중에 동적으로 ImageBrush를 설정해 주도록 하였습니다.
2. InkPresenter에 ImageBrush로 Background 깔기
Page.xaml.cs 파일 Page_Loaded(...) 함수 안에
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(...) 함수 안에
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 생성해주기에서 설명하겠습니다.
{
ink.CaptureMouse();
StartNewStroke();
}
2) MouseMove 이벤트
긋고 있는 획이 있다면, 움직임에 대한 Stylus Points를 얻어서 획(Stroke)에 누적추가해
줍니다. 즉, 획이 그어집니다.
참고> 타블렛 PC에서 Stylus 펜을 사용할 때는 이 GetStylusPoints 함수가
좀더 많은 Points를 얻어다 줍니다.
{
if (_strokeCurrent != null)
{
_strokeCurrent.StylusPoints.AddStylusPoints(e.GetStylusPoints(ink));
}
}
3) MouseLeftButtonUp 이벤트
ReleaseMouseCapture를 호출하고, 현재 긋고 있는 획에 null을 할당합니다.
즉, 그만 그립니다.
{
ink.ReleaseMouseCapture();
_strokeCurrent = null;
}
4) MouseLeave 이벤트
혹시 획을 긋다가 InkPresenter 영역 밖으로 나가면,
현재 긋고 있는 획에 null을 할당합니다. 즉, 그만 그립니다.
참고> 이 이벤트를 생략하시면, 영역 바깥까지 그림이 그려집니다.
{
_strokeCurrent = null;
}
5. 새 Stroke 생성해주기
MouseLeftButtonDown 이벤트에서 StartNewStroke를 호출합니다.
그러면 새 Stroke를 만들어서, 현재 획(_strokeCurrent)라고 할당을 해주고,
ink의 Stroke Collection에 추가해 줍니다.
Stroke의 스타일은 1부의 XAML 설명에서 보셨듯이, DrawingAttributes를 통해
설정하시면 됩니다.
{
_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부 기대해 주세요.
InkPresenterSample6.zip
이올린에 북마크하기
이올린에 추천하기



Prev

Rss Feed