Surface2014.04.10 11:32

일단 스토리보드는 타겟이 있어야 한다 대부분 디자이너나 블랜드에서 만들면 타겟을

 

Storyboard.TargetName="xDetailItem"

 

이런코드가 삽입된다

 

일단 xaml에서 TargetName을 다 제거한다.. 그리고 이 타겟을 Behind에서 추가해준다.

 

일단 아래와 같이 제거

 

 <Storyboard x:Key="CalculatorOpen">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>

 

 

자 이제 code behind에서

 

  ScatterViewItem svi = new ScatterViewItem()
                {
                    Center = (e.Source as DragAndDropScatterViewItem).Center,
                    Content = CalUc,
                    Orientation = 0,
                    Width = 263,
                    Height = 311,
                    RenderTransformOrigin = new Point(0.5, 0.5),
                    CanScale = false,
                };
                TransformGroup transGroup = new TransformGroup();
                transGroup.Children.Add(new ScaleTransform());
                transGroup.Children.Add(new TranslateTransform());
                transGroup.Children.Add(new RotateTransform());
                transGroup.Children.Add(new SkewTransform());
                svi.RenderTransform = transGroup;
                xScatterView.Items.Add(svi);

 

이런식으로 오브젝트를  하나 만들었다.

xaml에 Transform을 이용하기 떄문에 오브젝트에서도 이렇게 만들어줘야 된다.

 

자 간단하게 타겟을 지정해보자.

 

   Storyboard sb = this.Resources["CalculatorOpen"] as Storyboard;

   sb.Begin(svi);

 

아... 간단하다. begin(오브젝트)만 붙이면 된다.

Posted by 동동(이재동)
Surface2014.01.14 11:00

일단 ScatterView안에서 ScatterViewItem A가 있으면 이걸 ScatterviewItem B로 끌어놓으면 없어지면서 이벤트가 발생하고 싶었다.

 

일단 Item A에 ContainerManipulationStarted 이벤트를 걸어서

 

 var svi = e.OriginalSource as ScatterViewItem;
            svi.BeginDragDrop(svi.DataContext);

 

이런식으로 BeginDragDrop 메소드를 실행해야만 한다.

 

그뒤에 끌어놓아질 Item B에는 AllowDrop = true로 하고

 

<s:ScatterViewItem s:SurfaceDragDrop.Drop="xScatterItem_Drop" AllowDrop="True"/>

 

xaml에서 s:SurfaceDragDrop.Drop="xScatterItem_Drop" 이렇게 이벤트를 걸면된다.

 

근데 이상하게 behind에는 안되는데 이유는 찾아봐야 할듯한다.

 

 

 

Posted by 동동(이재동)
포트폴리오2012.05.31 17:33

로봇캅 폴리 이후 맡은 프로젝트로써 2012년 부산 모터쇼에서 실제 surface에서 사용한 프로그램 입니다.

 

전체적인 PM은 이길복 이사님이 하셧고 저는 안에 InkCanvas (Pallete Control)과 SMS 키보드 , Email 키보드 컨트롤을 제작

 

과 팔렛트 모드일시 사진의 크기가 최대로 커지면서 수정가능하고 스탬프도 사용할수 있으며 가장자리에서 팔렛트 이동시에 오

 

른쪽 팔렛트 버튼이 보이도록 위치 수정등 여러가지 작업을 하였습니다.

 

부산 모터쇼 에서 실제 가서 여러사람들이 제가 참여한 프로젝트 프로그램을 만지는 것을 보며 좋아하니 뿌듯한 마음이~

 

부산 모터쇼 동영상은 나중에 링크로~

 

 

 

 

 

Posted by 동동(이재동)
Surface2012.05.10 17:47

사용자가 터치하는 Brush 크기를 조절하고 싶어서

SurfaceInkCanvasContainer.DefaultDrawingAttributes.Height = 7;
SurfaceInkCanvasContainer.DefaultDrawingAttributes.Width = 7;

이렇게 height,width값을 조정하였지만 적용이 되지 않았다.

문제는

SurfaceInkCanvasContainer.UsesTouchShape = false;

이것이 true로 되어 있어서였다.(기본이 True)

이걸 false로 하면 유저의 손가락 크기에 굵기가 달라지는게 아니라 일정하게 유지되도록 변경된다.

Posted by 동동(이재동)
Surface2012.05.10 11:05

우왕 이것때문에 삽질 많이 했다.

일단 내가 하고 싶었던건 ScatterViewItem내 컨트롤에서 버튼을 누르면 MaxWidth,MaxHeight로 변경하고 싶었다.

근데 이상하게 Content내에서 사이즈를 변경하면 외부 ScatterViewitem 크기는 변경되지 않고 내부의 Content만 크기가 커졌다. 그래서 그냥 확대되는 느낌? 사이즈는 그대로 두고..

그래서 Scale로 어떻게든 해볼려고 했지만 역시 리사이즈할때도 문제이고 근본적인 원인이 해결되지 않아서

길복이 형한테 물어봤더니 길복이형이 이미 구현해 놓은 코드가 있었다.

 

if (Owner != null)
           {
               var container = Owner.GetContainer(this);
               if (container != null)
               {
                   container.Width = this.MaxWidth;
                   container.Height = this.MaxHeight;
               }
           }

 

대충 이런코드다 Owner라는게 있어서 Container를 잡을수가 있다!!!!!

최고다… 이걸 몰랐으면 엄청 고생했을듯

Posted by 동동(이재동)
Surface2012.05.04 12:00

Xaml이 아닌 코드로 만들어서 범용적이고 실용적으로 사용 가능

public static class FadeAnimationControl
{
    public static void Fade(UIElement target, double ValueFrom, double ValueTo, double Duration)
    {
        DoubleAnimation da = new DoubleAnimation();
        da.From = ValueFrom;
        da.To = ValueTo;
        da.Duration = TimeSpan.FromSeconds(Duration);
        da.AutoReverse = false;

        System.Windows.Media.Animation.Storyboard.SetTargetProperty(da, new PropertyPath("Opacity"));

        System.Windows.Media.Animation.Storyboard.SetTarget(da, target);

        System.Windows.Media.Animation.Storyboard sb = new System.Windows.Media.Animation.Storyboard();
        sb.Children.Add(da);

        EventHandler eh = null;
        eh = (s, args) =>
        {
            //target.Visibility = Visibility.Collapsed;
            sb.Stop();
            sb.Completed -= eh;
            target.Opacity = ValueTo;
        };
        sb.Completed += eh;

        sb.Begin();
    }
}

참고 : http://forums.create.msdn.com/forums/p/87462/525024.aspx

Posted by 동동(이재동)
Surface2012.04.27 10:40

일반적으로 Button(ContentControl 상속)과 같이 Content를 넣으면 이를 표현해주는데 Text를 넣으면 Text를 이미지를 넣으면 Image를 이런식으로 알아서 표현해준다.

이를 구현하기 위해서

ContentControl을 상속받은 컨트롤을 하나 만들고

 public class VirtualKeyboard : ContentControl

해당 컨트롤 xaml에

<ContentPresenter Content="{TemplateBinding Content}" Width="300" Height="300"/>

이렇게 만들어 놓고

            <c:VirtualKeyboard >
                <c:VirtualKeyboard.Content>
                    <Image Source="Images/sample.jpg"/>
                </c:VirtualKeyboard.Content>
            </c:VirtualKeyboard>

 

이런식으로 Content를 주입하면 Image가 나타난다.

아주 기초적인것이지만 활용하면 편하니 활용하길~

참고: http://www.mediamob.co.kr/infoland/blog.aspx?id=278585

Posted by 동동(이재동)
Surface2012.04.26 10:08
private void Snapshot(UIElement source, double scale, int quality)
       {
           double actualHeight = source.RenderSize.Height;
           double actualWidth = source.RenderSize.Width;

           double renderHeight = actualHeight * scale;
           double renderWidth = actualWidth * scale;

           RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth, (int)renderHeight, 96, 96, PixelFormats.Pbgra32);
           VisualBrush sourceBrush = new VisualBrush(source);

           DrawingVisual drawingVisual = new DrawingVisual();
           DrawingContext drawingContext = drawingVisual.RenderOpen();

           using (drawingContext)
           {
               //drawingContext.PushTransform(new ScaleTransform(scale, scale));
               drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
           }
           renderTarget.Render(drawingVisual);

           JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
           jpgEncoder.QualityLevel = quality;
           jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

           using (FileStream stm = File.OpenWrite(@"C:\test2.png"))
               jpgEncoder.Save(stm);
       }

일단 소스는 이렇다 source에 해당 usercontrol을 넣는다.

만약 DrawingVisual에 넣어서 rectangle을 만들지 않으면 해당 유저컨트롤만 찍히는게 아니라 전체가 찍힌다.

전체가 찍히긴하지만 해당 컨트롤만 나옴

참고 :

http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/
Posted by 동동(이재동)
Surface2012.04.25 14:41

반대로 Media.Color를 Brush로 바꾸는건 쉬웠지만

 

Brush를 Color로 바꾸는건 힘들었다.

 

var temp = ((e.Source as ListBox).SelectedItem as Brush);
         SolidColorBrush c = new BrushConverter().ConvertFromString(temp.ToString()) as SolidColorBrush;

         SurfaceInkCanvasContainer.DefaultDrawingAttributes.Color = c.Color;

내가 사용한 방법이다. brush를 SolidColorBrush로 BrushConvert의 도움을 받아서 컨버팅한후 Color프로퍼티를 이용하였다.

참고 : http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/fb164db0-c169-4d0e-85dc-c79163ea3aac/

Posted by 동동(이재동)
Surface2012.04.25 11:46

보통 control을 만들때 genneric.xaml에 디자인을 구현하고 x:Name을 이용해서 해당 control의 cs안에서 컨트롤 하고 싶을때

이렇게 하면 된다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Surface.Presentation.Controls;

namespace MyControl
{
    [TemplatePart(Name = SurfaceInkCanvasName, Type = typeof(SurfaceInkCanvas))]
    public class DrawPanelControl : Control
    {
        //template
        internal const string SurfaceInkCanvasName = "xSurfaceInkCanvas";
        internal SurfaceInkCanvas SurfaceInkCanvasContainer;

        public DrawPanelControl()
        {
            DefaultStyleKey = typeof(DrawPanelControl);
        }

        public override void OnApplyTemplate()
        {
            SurfaceInkCanvasContainer = this.GetTemplateChild(SurfaceInkCanvasName) as SurfaceInkCanvas;

            SurfaceInkCanvasContainer.DefaultDrawingAttributes.Height = 10;
            SurfaceInkCanvasContainer.DefaultDrawingAttributes.Width = 10;
            SurfaceInkCanvasContainer.DefaultDrawingAttributes.Color = Colors.Red;

            base.OnApplyTemplate();
        }
    }
}

저렇게 TemplatePart를 class밖에서 잡고 OnApplyTemplate에서

SurfaceInkCanvasContainer = this.GetTemplateChild(SurfaceInkCanvasName) as SurfaceInkCanvas;

이렇게 정의 하면 된다.

generic.xaml에는 그냥 일반적으로 x:name을 썻다.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:controls="clr-namespace:MyControl"
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:Custom="http://schemas.microsoft.com/surface/2008"
                    xmlns:sf="clr-namespace:Microsoft.Surface.Presentation.Controls;assembly=Microsoft.Surface.Presentation"
                    mc:Ignorable="d">

    <Style TargetType="{x:Type controls:DrawPanelControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:DrawPanelControl}">
                    <Grid>
                        <sf:SurfaceInkCanvas x:Name="xSurfaceInkCanvas" Background="Bisque"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
Posted by 동동(이재동)
Surface2012.04.25 11:25

어휴 그냥 내가 컨트롤 프로젝트를 만들었을때 그냥 일반 c# 프로젝트를 만들어서 그런거 같다.

 

일단 많은 레퍼런스를 추가해야하고

 

꼭 AssemblyInfo.cs에

 

[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

 

이구문이 추가 되어야 한다.

이구문이 추가 되기위해서

사용한 네임스페이스는

using System.Resources;

using System.Windows;

이두개가 using되어야 한다.

이거때문에 완전 삽질함

 

참고 : http://charlass.wordpress.com/2012/02/17/wpf-onapplytemplate-is-not-getting-called/

Posted by 동동(이재동)
포트폴리오2011.10.19 16:56
Surface2011.09.14 19:18
Surface2011.05.27 11:15

휴 힘들었다. 거의 이틀만에 만들으라고해서 아직 surface 개념이 없던 나에게 철야까지 하면서

 

힘들게 만들었다. 기계가 바로 전날 와서 테스트를 못해봐서.. 에물레이터에 맞추어서 만들었는데

 

태그 인식이 잘안되고 됐다가 안됐다가를 반복해서 행사 바로 전날 다시 전체 수정을 했다..

 

Tagvisualizer를 이용해서 멋있게 만들었지만 약간 보여주기 용으로 급수정을 해서 마음이 안좋았다..

 

기계만 좋았어도 ㅠㅠ

 

간략하게 소개를 하자면

 

처음 기계를 켜면 이런 화면이 나온다.

 

image

 

그다음에 책을 올리면

 

image

 

 

 

 

image

 

image

 

image

 

이런식으로 책을 넘길때마다 화면이 바뀌고 동영상이 뜬다.

 

마지막에 Develope에 내이름이 써있다. ㅋㅋ

 

많은 사람들에게 시연하는것이라 긴장도 되었지만 재미 있었다. ㅋㅋ

 

실제 시연 동영상은 여기서 볼수 있다.

 

http://www.youtube.com/watch?feature=player_detailpage&v=ruZvqF9ynJY

Posted by 동동(이재동)
Surface2011.05.27 11:06

WPF에서 이런식으로 스토리를 보여주고 싶었다.(이건 완성된버전 ㅋㅋ)

 

image

 

이건 그냥 TextBlock으로 되는것이 아니다.

 

그래서 FlowDocument를 사용하였다..

 

일단 xaml에서 이렇게 코딩을 했다.

 

<FlowDocumentScrollViewer Grid.Row="1" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Hidden" >
    <FlowDocument Background="Transparent">                                        
        <Paragraph FontFamily="Bell MT" FontSize="24" x:Name="DescriptionParagraph">
            <Floater Width="500"  HorizontalAlignment="Left">                            
                <BlockUIContainer>
                    <Rectangle Height="250" />
                </BlockUIContainer>
            </Floater>
            One Day, most of the town’s roads are ruined by the heavy rain. On that day, school bus-Schoobi happens to be late because of constructions on the road. Worrying that children may be waiting at the bus stop, Schoobi drives through the traffic with full speed, even though other cars are starring at him in a disapproving manner. Schoobi gets to a costal road, however, the road condition there is also messy. Dilly-dallying and regreting to go back. Schoobi ends up ramming into the guardail. Schoobi is now in the danger of falling down the cliff. Can Robocar Poli and his team save Schoobi?
        </Paragraph>
    
    </FlowDocument>
   
</FlowDocumentScrollViewer>
 
보면 알겠지만 FlowDocument에서 Paragraph를 사용하고 안에 Floater를 이용해서 안에 투명한 사각형을 왼쪽에 정렬하고 바깥쪽에 글을 입력하였다.
 
그럼 이제 안에 내용 Text를 계속 유동적으로 바꿔야 한다.
그럼 어떻게 해야할까? behind에서 수정하면 된다.
 
paragrah의 x:name을 DescriptionParagraph를 정의 했으니 이걸 변경하면 된다. 소스를 보자
 
private void SetDescriptionPlaceholder(string param)
        {
            DescriptionParagraph.Inlines.Remove(DescriptionParagraph.Inlines.Where(c => c is System.Windows.Documents.Run == true).Select(c => c).FirstOrDefault());
            DescriptionParagraph.Inlines.Add(param);
        }
 

이렇게 inline을 삭제하고 다시 추가하는 형식으로 바꾸었다.

 

이렇게 하면 끝~

Posted by 동동(이재동)
Surface2011.05.19 16:06

아 이것때문에 시간 아까운데 2시간이나 까먹었다…

 

실버라이트랑 다르게 이상하게

 

Blend로 VisualState를 만들고

 

VisualStateManager.GoToState(this, "Title", true);

 

이렇게 state간의 전환을 할려고 했으나 계속 false를 return 했다. ㅡ.ㅡ!!!

 

인터넷 찾아보니…

 

WPF 버그라던데…

 

해결법은

 

VisualStateManager.GoToElementState(this.Content as FrameworkElement, "Title", true);

 

이렇게 element단위에서 해야한다.. 내참 인터넷에 왜 이런거 해결하는 법 하나도 없는거야?

Posted by 동동(이재동)