2010.01.12 09:00

1.RichTextArea Part 1
2.RichTextArea Part 2
3.Accessing Web Camera and Microphone
4.Right Click Mouse Events
5.MouseWheel API

6.Using Silveright Controls As Drop Targets
7.DataGrid Enhancements
8.Printing API Basics 
9.Hosting HTML Content
10.Accessing the Global Clipboard Programmatically 
11.Using the ViewBox Control 
12.Asynchronous Data Validation 
13.BiDi and Right-to-Left Support 
14.Notification API
15.Local File Access 
16.RIA Services support in Visual Studio 2010  

블로그 이미지 김영욱 차장 Microsoft Korea  .NET Evangelist
Enterprise UX 를 위한  UI 기술과 SOA, Cloud Computing, NUI등 다양한 분야의 접목과 응용을 통해 최적의 IT 인프라 구축을 위해서 노력하고 있다.
Email: iwinkey@hotmail.com
Blog: http://winkey.tistory.com

 

일반적인 Windows 응용 프로그램들과 웹 프로그램의 가장 큰 차이점이 무엇일까요? 여러 가지 이야기를 할 수 있지만 인터페이스적인 면으로 보면 가장 큰 차이가 바로 마우스 오른쪽 버튼의 사용 여부가 가장 큰 차이점이라고 할 수 있습니다. 웹이 아닌 일반적은 응용 프로그램에서는 마우스 오른쪽 버튼을 사용해서 상황에 맞는 기능들을 호출 할 수 있지만 웹에서는 웹 브라우저에 관련된 기능들이 실행되거나 Flash나 혹은 Silverlight의 경우는 그냥 해당 런타임 정보를 보여주는 용도로만 활용되고 있는 실정입니다.

 

Silverlight 4에서는 마우스 오른쪽 버튼을 사용할 수 있게 해주었는데 그냥 마우스 오른쪽 버튼을 사용할 수 있게 되었다는 정도의 의미가 아니라 웹에서 데스크 탑 응용 프로그램의 경험을 체험할 수 있게 해 주었다는 점에서 접근하게 되면 훨씬 많은 아이디어와 좋은 방법들을 구성할 수 있을 것 같습니다.

 

서두는 이렇게 시작하지만 실제로 구현하는 방식은 아주 간단하다.

 

1. 오른쪽 마우스 버튼을 사용하기 위해서는 이벤트 핸들러를 활성화 시켜야 한다.

 

버튼과 관련된 처음 작업은 바로 이벤트 핸들러를 작성하는 것입니다.

 

ChangingRectangle.MouseRightButtonDown += new MouseButtonEventHandler(RectangleContextDown);
ChangingRectangle.MouseRightButtonUp += new MouseButtonEventHandler(RectangleContextUp);

SimpleButton.MouseRightButtonDown += new MouseButtonEventHandler(ButtonContextDown);
SimpleButton.MouseRightButtonUp += new MouseButtonEventHandler(ButtonContextUp);

 

이렇게 마우스 오른쪽 버튼의 이벤트 두 개를 모두 핸들링 합니다. 마우스와 키보드 관련 이벤트는 항상 Down, Up 이렇게 두 개가 함께 있는데 누를 때가 Down 버튼을 놓을 때가 Up 이렇게 두 가지가 함께 공존하기 때문에 그렇습니다.

마우스 오른쪽 버튼을 사용하기 위해서 주로 사용되는 방법은 Down 이벤트시에 오른쪽 마우스 버튼 이벤트를 활성화 시키는 방법입니다.

 

e.Handled = true;

 

이벤트 핸들러의 MouseButtonEventArgs 객체로 리턴되는 e의 Handled 속성을 true 로 설정하는 순간 오른쪽 마우스 버튼을 누를 때 Silverlight라는 조그만 버튼이 나타나지 않게 됩니다.

 

 

2. 팝업 메뉴를 사용하기 위해서는 팝업 메뉴를 만들어야 한다.

 

일반적인 Windows 응용 프로그램에서 오른 쪽 마우스를 사용해서 팝업 메뉴를 불러 낼 경우에는 대부분 기본으로 제공하는 메뉴 객체를 사용해서 표현하는 경우가 대부분 입니다. 하지만 Silverlight에서는 팝업과 관련된 용도로 제공하는 컨트롤은 없습니다. 기본적으로 관련된 컨트롤을 제공하지 않는 이유는 Silverlight의 높은 자유도와 관련되어 있습니다.

팝업 메뉴를 특정 형태로 제공하지 않고 원하는 디자인으로 쉽게 구성해서 사용할 수 있게 있게 해 준 것입니다.

 

팝업과 관련된 클래스를 하나 추가해야 하는데 여기서는 가장 간단한 디자인으로 구성하고 있지만 실 프로젝트에서는 디자이너의 손을 거치면 좀 더 간지나는 팝업 메뉴로 만들 수 있습니다.

 

public class ColorChangeContextMenu : Dialog
{
    Rectangle _rectangle;

    public ColorChangeContextMenu(Rectangle rectangle)
    {
        _rectangle = rectangle;
    }

    protected override void OnClickOutside()
    {
        Close();
    }

    protected override FrameworkElement GetContent()
    {
        Grid grid = new Grid() { Width = 100, Height = 115 };
        Border border = new Border() { BorderBrush = new SolidColorBrush(Colors.Black), BorderThickness = new Thickness(1), Background = new SolidColorBrush(Colors.LightGray) };
        grid.Children.Add(border);

        TextBlock red = new TextBlock() { Text = "Red", Width = 90 };
        red.MouseLeftButtonUp += new MouseButtonEventHandler(ChangeColorRed);

        TextBlock blue = new TextBlock() { Text = "Blue", Width = 90 };
        blue.MouseLeftButtonUp += new MouseButtonEventHandler(ChangeColorBlue);

        TextBlock green = new TextBlock() { Text = "Green", Width = 90 };
        green.MouseLeftButtonUp += new MouseButtonEventHandler(ChangeColorGreen);

        TextBlock yellow = new TextBlock() { Text = "Yellow", Width = 90 };
        yellow.MouseLeftButtonUp += new MouseButtonEventHandler(ChangeColorYellow);

        TextBlock cancel = new TextBlock() { Text = "Cancel Menu", Width = 90 };
        cancel.MouseLeftButtonUp += new MouseButtonEventHandler(CancelContextMenu);

        ListBox options = new ListBox();
        options.Items.Add(red);
        options.Items.Add(blue);
        options.Items.Add(green);
        options.Items.Add(yellow);
        options.Items.Add(cancel);

        grid.Children.Add(options);

        return grid;
    }

    void CancelContextMenu(object sender, MouseButtonEventArgs e)
    {
        Close();
    }

    void ChangeColorYellow(object sender, MouseButtonEventArgs e)
    {
        SolidColorBrush solidColor = new SolidColorBrush();
        solidColor.Color = Colors.Yellow;
        _rectangle.Fill = solidColor;
        Close();
    }

    void ChangeColorGreen(object sender, MouseButtonEventArgs e)
    {
        SolidColorBrush solidColor = new SolidColorBrush();
        solidColor.Color = Colors.Green;
        _rectangle.Fill = solidColor;
        Close();
    }

    void ChangeColorBlue(object sender, MouseButtonEventArgs e)
    {
        SolidColorBrush solidColor = new SolidColorBrush();
        solidColor.Color = Colors.Blue;
        _rectangle.Fill = solidColor;
        Close();
    }

    void ChangeColorRed(object sender, MouseButtonEventArgs e)
    {
        SolidColorBrush solidColor = new SolidColorBrush();
        solidColor.Color = Colors.Red;
        _rectangle.Fill = solidColor;
        Close();
    }
}

 

좀 내용이 길기는 하지만 간단한 내용입니다. ListBox 컨트롤에 TextBlock을 추가해서 버튼처럼 사용할 수 있게 하고 있습니다. 그리고 이벤트 핸들러를 걸어 놓은 형태 입니다. 처음에는 이렇게 좀 길게 소스를 써야 하겠지만 자주 사용되는 기능인 만큼 컨트롤로 잘 만들어 두면 편리하게 사용할 수 있을 것 같습니다.

 

이 클래스를 불러와서 사용하기 위해서는 아래와 같이 사용할 수 있습니다.

 

ColorChangeContextMenu contextMenu = new ColorChangeContextMenu(ChangingRectangle);
contextMenu.Show(e.GetPosition(LayoutRoot));

 

e.GetPosition( )을 사용하는 이유는 현재 마우스 위치를 파악해서 해당 되는 위치에 팝업 메뉴를 보여 주기 위해서 입니다. 여기까지 했다면 다음과 F5번을 눌러서 실행 시켜 보면 다음과 같은 결과를 볼 수 있습니다.

 



신고
2010.01.11 09:00

1.RichTextArea Part 1
2.RichTextArea Part 2
3.Accessing Web Camera and Microphone
4.Right Click Mouse Events
5.MouseWheel API

6.Using Silveright Controls As Drop Targets
7.DataGrid Enhancements
8.Printing API Basics 
9.Hosting HTML Content
10.Accessing the Global Clipboard Programmatically 
11.Using the ViewBox Control 
12.Asynchronous Data Validation 
13.BiDi and Right-to-Left Support 
14.Notification API
15.Local File Access 
16.RIA Services support in Visual Studio 2010 

 

 

블로그 이미지 김영욱 차장 Microsoft Korea  .NET Evangelist
Enterprise UX 를 위한  UI 기술과 SOA, Cloud Computing, NUI등 다양한 분야의 접목과 응용을 통해 최적의 IT 인프라 구축을 위해서 노력하고 있다.
Email: iwinkey@hotmail.com
Blog: http://winkey.tistory.com

 

Silverlight 4 에서 추가 된 기능 중에서 가장 재미있는 기능을 하나 뽑으라고 한다면 저는 주저 없이 Web Camera와 Microphone의 지원이라고 이야기 할 수 있을 만큼 Web Camera와 Microphone의 추가는 많은 가능성을 가지고 있는 기능 중에 하나 입니다. Flash에서도 이미 지원되고 있지만 효율 및 신뢰성 측면에서는 Silverlight 4가 좀 더 안정된 기능을 제공 할 수 있을 것으로 기대하고 있습니다.

 

Web Camera를 활용할 수 있는 분야라면 어떤 것이 있을 까요? 우선 화상회의 와 같은 부분들도 생각할 수 있고 또 Web Camera를 사용한 사진 촬영으로 각종 프로필 사진을 대치 한다든지 하는 용도로 요긴하게 사용할 수 있습니다. 하지만 무엇보다도 어학 및 기타 교육 관련 사이트에서 적극적으로 활용해 볼 만한 기능인 것 같습니다.

 

이번 강좌에서는 아래와 같은 기능을 완성해 볼 예정입니다.

먼저 Web Camera나 Microphone이 하나 이상 있을 수 있기 때문에 해당 되는 장치의 목록을 보여주고 원하는 장치를 선택할 수 있게 할 예정입니다. 장치를 선택하고 나서 바로 Web Camera 영상을 볼 수도 있고 스넵셧 컷도 찍을 수 있게 만들어 볼 예정입니다.

 

1. 출력은 Rectangle로 한다.

 

Silverlight 4가 Web Camera의 출력을 위해서 새로운 컨트롤을 제공하지는 않습니다. 대신 기존의 컨트롤에 출력할 수 있도록 Brush 형태로 제공할 수 있습니다. 이번 샘플에서는 사각형을 나타내는 Rechtangle 컨트롤에 출력할 예정입니다.

 

<Rectangle x:Name="WebcamCapture" Width="320" Height="240" Fill="White"/>

 

UI를 나타내는 XAML에 위와 같이 Rectangel을 하나 추가해서 여기에서 Web Camera의 출력을 보여줄 예정입니다.


2. Video & Audio 장치는 복수개가 있을 수 있다.

 

노트북을 사용하는 사용자 혹은 데스크탑을 사용한 다 하더라도 시스템에 기본 장착되어 있는 Video & Audio 장치 이외에도 추가로 다양한 장치들이 설치되어 있는 경우들이 많이 있습니다. Silverlight에서는 어떤 장치를 사용하게 될까요? 기본적인 대답은 ‘골라 쓰는 재미가 있다’ 정도 일 것입니다.

Silverlight에서는 기본적으로 해당 PC에서 설치된 장치 목록을 가져올 수 있는 System.Windows.Media.CaptionDeviceConfiguration 객체를 제공합니다. 이 객체의 주요 메소드는 다음과 같습니다.

 

GetAvailableAudioCaptureDevices( ) 시스템에 설치되어 있는 오디오 장치 목록을 가져온다.
GetAvailableVideoCaptureDevices( ) 시스템에 설치되어 있는 비디오 장치 목록을 가져온다.
GetDefaultAudioCaptureDevice( ) 시스템에서 기본 장치로 설정되어 있는 오디오 장치를 가져온다.
GetDefaultVideoCaptureDevice( ) 시스템에서 기본 장치로 설정되어 있는 비디오 장치를 가져온다.

 

화면에 해당 Video & Audio 장치 목록을 보여줄 ListBox 컨트롤을 두 개 추가해야 합니다.

 

<TextBlock Margin="5" HorizontalAlignment="Center" Foreground="White" Text="Available AUDIO Sources" Grid.Column="0" Grid.Row="0" />
<ListBox x:Name="AudioSources" Grid.Row="1" Grid.Column="0">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding FriendlyName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

<TextBlock Margin="5" HorizontalAlignment="Center" Foreground="White" Text="Available VIDEO Sources" Grid.Column="1" Grid.Row="0" />
<ListBox x:Name="VideoSources" Grid.Row="1" Grid.Column="1">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding FriendlyName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

 

두 개의 ListBox 컨트롤의 이름은 각 각 AudioSource와 VideoSourde로 지었습니다. ListBox 안에는 DataTemplate으로 바인딩 하기 좋은 형태로 구성했는데 TextBlock을 출력하는 형태로 만들었습니다. Binding FriendlyName이라고 해서 해당 장치의 FrinedlyName을 바인딩 할 수 있게 구성했습니다. FriendlyName은 이름 그대로 해당 장치 명을 의미합니다.

 

사용하는 방법은 간단해서 아래와 같이 두 개의 ListBox에 CatureDeviceConfiguratuion 객체를 사용해서 장치 목록을 가져와서 넣기만 하면 바로 바인딩 된 결과를 볼 수 있습니다.

 

// get list of audio sources
AudioSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();

// get list of the video sources
VideoSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();

 

3. Web Camera의 내용을 출력하자.

 

장치 목록을 선택했다면 이제 화면에 Web Camera의 내용을 출력할 수 있는 준비가 거의 끝났습니다. 이제 캡쳐 버튼을 누르게 되면 호출 될 이벤트 핸들러의 내용을 채워 보도록 하겠습니다.

 

private void CaptureButton_Click(object sender, RoutedEventArgs e)
{
    if (_captureSource != null)
    {
        _captureSource.Stop(); // stop whatever device may be capturing

        // set the devices for the capture source
        _captureSource.VideoCaptureDevice = (VideoCaptureDevice)VideoSources.SelectedItem;
        _captureSource.AudioCaptureDevice = (AudioCaptureDevice)AudioSources.SelectedItem;

        // create the brush
        VideoBrush vidBrush = new VideoBrush();
        vidBrush.SetSource(_captureSource);
        WebcamCapture.Fill = vidBrush; // paint the brush on the rectangle

        // request user permission and display the capture
        if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
        {
            _captureSource.Start();
        }
    }
}

 

먼저 if문에서 캡쳐 소스가 널 값인지 아닌지 먼저 체크를 합니다. 뜬금없이 _captureSoure가 나왔는데 Silverlight 4에서는 Web Camera나 혹은 Microphone의 내용을 저장할 수 있는 객체로 CaptureSoure라는 객체를 제공하고 있습니다.

여기 소스에서는 보이지 않지만

 

CaptureSource _captureSource;

 

와 같은 문장으로 해당 객체를 이미 맴버 변수로 정의해 두었습니다.

캡쳐를 시작할 때 이미 해당 객체가 캡쳐를 하고 잇으면 해당 캡쳐 장치들이 응답하지 못하기 때문에 _captureSource.Stop()을 호출해서 먼저 정지를 시킵니다.

 

아래의 두 줄은 캡쳐 할 장치를 선택할 수 있게 해주는 소스 입니다.  

_captureSource.VideoCaptureDevice = (VideoCaptureDevice)VideoSources.SelectedItem;
_captureSource.AudioCaptureDevice = (AudioCaptureDevice)AudioSources.SelectedItem;

 

위에서도 언급했지만 Web Camera를 위한 특별한 컨트롤은 제공되지 않는다고 했습니다. 대신 Brush를 사용 할 수 있다고 했는데 아래 내용은 Brush를 설정하는 부분입니다.

 

VideoBrush vidBrush = new VideoBrush();
vidBrush.SetSource(_captureSource);
WebcamCapture.Fill = vidBrush; // paint the brush on the rectangle

 

VideoBrush를 정의하고 해당 VideoBrush의 소스를 _captrueSoure로 설정하고 있습니다. 그리고 앞에서 Web Camera의 출력용으로 사용하기 위해서 미리 정의해둔 Rectangle 객체인 WebcamCaptrue의 Fill 속성에 해당 VideoBrush를 설정 합니다.

 

이제 장치들이 접근 가능하다면 _captureSource.Start()를 호출하는 것으로 Web Camera의 연결이 끝났습니다.

참 쉽죠 ^^

 

  4. 사진을 찍어 보자.

 

Web Camera를 사용해서 스냅 셧을 찍는 기능을 구현 하는 작업이 이전에는 그리 단순한 작업이 아니었지만 Silverlight 4에서는 아주 심플하게도 아래 한 줄이 해당 기능을 다 구현해 줍니다. 

 

_captureSource.AsyncCaptureImage((snapImage)

 

나머지 소스는 첨부된 샘플을 참조하시면 이해하시리라 믿고 일단 패스 합니다.

신고
2010.01.07 09:00

1.RichTextArea Part 1
2.RichTextArea Part 2
3.Accessing Web Camera and Microphone
4.Right Click Mouse Events
5.MouseWheel API

6.Using Silveright Controls As Drop Targets
7.DataGrid Enhancements
8.Printing API Basics 
9.Hosting HTML Content
10.Accessing the Global Clipboard Programmatically 
11.Using the ViewBox Control 
12.Asynchronous Data Validation 
13.BiDi and Right-to-Left Support 
14.Notification API
15.Local File Access 
16.RIA Services support in Visual Studio 2010  
 

블로그 이미지 김영욱 차장 Microsoft Korea  .NET Evangelist
Enterprise UX 를 위한  UI 기술과 SOA, Cloud Computing, NUI등 다양한 분야의 접목과 응용을 통해 최적의 IT 인프라 구축을 위해서 노력하고 있다.
Email: iwinkey@hotmail.com
Blog: http://winkey.tistory.com


RichTextArea 를 설명하는 두 번째 시간입니다. 지난 강좌에서는 RichTextArea를 활용하는 기본적인 방법을 설명했습니다. 이번 강좌에서는 조금 더 진도를 나가 보도록 하겠습니다.

아래 화면은 이번 강좌의 결과물로서 얻어지는 샘플입니다.  RichTextArea안에서 다양한 형태(크기, 폰트, 속성)을 가진 문단들이 한꺼번에 사용되었으며 원하는 부분만 선택해서 속성을 변경할 수 있게 되어 있습니다. 또 RichTextArea 안에 버튼을 삽입해서 동작 시키는 것도 가능하다는 것을 볼 수 있는 샘플입니다.

 

 

먼저 RichTextArea를 구성하는 방법에 대해서 설명해 드립니다. RichTextArea안에서 내용을 표현하기 위해서 사용하는 Paragraph을 사용해야 한다. Paragraph는 RichTextArea안의 내용을 표현하기 위해서 제공되는 객체이다.

 

<Paragraph x:Name="H1"
                       FontFamily="Georgia"
                       FontSize="36"
                       FontWeight="Bold"
                       TextAlignment="Center"
                       TextDecorations="Underline">
                <LineBreak />
                Rich Text Demonstration
                <LineBreak />
</Paragraph>

위의 내용은 H1이라고 명명된 문단에 Georgia  폰트 36pt 볼드체에 가운데 정렬과 언더라인 속성을 지정했습니다. 위의 그림에서 Rich Text Demonstration라고 표시된 헤더 부분을 나타내고 있는 문단을 Paragraph로 표현한 것입니다. 중간에 LineBreak는 이름 그대로 한 줄 내려가는 Line Break 입니다.

 

또 다른 형태로 사용되는 Paragraph 형태를 보면 다음과 같습니다.

<Paragraph x:Name="p3"
                       TextAlignment="Left"
                       FontFamily="Georgia"
                       FontSize="18">
                <Run Text="This is another paragraph. Oh look, a button: " />
                <InlineUIContainer>
                    <Button x:Name="inLineButton"
                            Background="Green"
                            Content="Change line 4!"
                            FontFamily="Georgia"
                            FontSize="14"
                            Height="30"
                            Width="Auto" />
                </InlineUIContainer>
                <LineBreak />
                You can click the button or
                <Run Text=" " />
                <Hyperlink NavigateUri="http://silverlightGeek.me"
                           TargetName="">this link</Hyperlink>
</Paragraph>

Paragraph 안에서 사용되는 Run은 문단 안에서 문장의 요소를 표현하기 위해서 사용되는 것으로 BreakLine과 같은 종류로 볼 수 있습니다. 또 재미있는 것은 InlineUIContainer 객체인데 이 객체를 통해서 각종 UI Control을 RichTextArea안에 포함시킬 수 있다. 위의 소스에서는 버튼을 삽입 한 것을 볼 수 있습니다.

마지막에 포함되어 있는 Hyperlink 객체는 링크를 표현하기 위해서 사용했습니다.

 

전체 XAML코드는 다음과 같습니다.

<UserControl x:Class="RTA.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:doc="clr-namespace:System.Windows.Documents;assembly=System.Windows"
             mc:Ignorable="d"
             d:DesignHeight="500"
             d:DesignWidth="600">

    <Grid x:Name="LayoutRoot"
          Background="White"> 
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="5*" />
        </Grid.RowDefinitions>
        <StackPanel Name="stackPanel1"
                    HorizontalAlignment="Stretch"
                    Margin="0"
                    VerticalAlignment="Stretch"
                    Orientation="Horizontal">
            <CheckBox  Name="IsReadOnly"
                       Content="ReadOnly"
                       FontFamily="Georgia"
                       FontSize="14"
                       VerticalAlignment="Bottom"
                       HorizontalAlignment="Left"
                       Height="20"
                       Width="Auto"
                       Margin="5"
                       IsChecked="False" />
            <Button x:Name="Bold"
                    Content="Bold"
                    FontFamily="Georgia"
                    FontSize="14"
                    Margin="5"
                    VerticalAlignment="Bottom"
                    HorizontalAlignment="Left"
                    Height="Auto"
                    Width="60" />
        </StackPanel>
        <RichTextArea x:Name="rta"
                      Grid.Row="1" 
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      TextWrapping="Wrap"
                      IsReadOnly="False">

            <Paragraph x:Name="H1"
                       FontFamily="Georgia"
                       FontSize="36"
                       FontWeight="Bold"
                       TextAlignment="Center"
                       TextDecorations="Underline">
                <LineBreak />
                Rich Text Demonstration
                <LineBreak />
            </Paragraph>
            <Paragraph x:Name="P1"
                       FontFamily="Georgia"
                       FontSize="14"
                       TextAlignment="Left">
                The text in this first paragraph is left aligned, Georgia 14.
            </Paragraph>
            <Paragraph x:Name="P2"
                       FontFamily="Georgia"
                       FontSize="12" 
                       TextAlignment="Right">
                <LineBreak />
                This is line one of the second paragraph (right aligned)
                <LineBreak />
                This is line two of the second paragraph
                <LineBreak />
                <Italic>
                    This is line three and it is in italic
                </Italic>
                <LineBreak />
                <Run x:Name="run1"
                     Text="This is line four and it is in a run!" />
                <LineBreak />
            </Paragraph>
            <Paragraph x:Name="p3"
                       TextAlignment="Left"
                       FontFamily="Georgia"
                       FontSize="18">
                <Run Text="This is another paragraph. Oh look, a button: " />
                <InlineUIContainer>
                    <Button x:Name="inLineButton"
                            Background="Green"
                            Content="Change line 4!"
                            FontFamily="Georgia"
                            FontSize="14"
                            Height="30"
                            Width="Auto" /> 
                </InlineUIContainer>
                <LineBreak />
                You can click the button or
                <Run Text=" " />
                <Hyperlink NavigateUri="http://silverlightGeek.me"
                           TargetName="">this link</Hyperlink>
            </Paragraph>

        </RichTextArea>
    </Grid>
</UserControl>

 

UI가 완성되었으니 C# 코드를 추가할 차례 입니다.  MainPage() 안에서 Loaded 이벤트 핸들러를 작성합니다.

public MainPage()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(MainPage_Loaded);
}

 

Loaded 이벤트 핸들러에서 UI과 관련된 초기화 작업과 추가적인 이벤트 핸들러를 작성해 봅니다.

 

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
   rta.IsReadOnly = false;
   Bold.Click += new RoutedEventHandler( Bold_Click );
   IsReadOnly.Click += new RoutedEventHandler( IsReadOnly_Click );
   inLineButton.Click += new RoutedEventHandler( inLineButton_Click );
}

 

먼저 rta.IsReadOnly = false를 통해서 RichTextArea를 쓰기 가능한 상태로 만들어 놓습니다. 그리고 Bold 속성을 추가하는 버튼과 ReadOnly 상태로 전환할 체크박스 그리고 RichTextArea 안에 추가해 두었던 버튼 등의 이벤트 핸들러를 설정합니다.

 

void inLineButton_Click( object sender, RoutedEventArgs e )
{
   run1.Text = "Whoa! I just changed this text dynamically!";
   run1.FontSize = 18;
   run1.FontWeight = FontWeights.Bold;
}

 

RichTextArea안에 추가 되어 있는 inLineButton에 대한 이벤트 핸들러에서는 Run 객체인 run1의 Text를 변경하고 FontSize와 Bold 속성을 변경할 수 있는 코드가 추가 되어 있다.

 

마지막으로 RichTextArea 안에서 선택한 영역을 Bold 속성으로 변경해 주는 기능을 추가 해 봅니다.

 

void Bold_Click( object sender, RoutedEventArgs e )
{
   if ( !string.IsNullOrEmpty( rta.Selection.Text ) )
   {
      rta.Selection.SetPropertyValue(
         TextElement.FontWeightProperty, FontWeights.Bold );
   }
}

 

string.IsNullOrEmpty( )를 사용해서 선택한 영역이 없을 경우를 먼저 체크하고 선택된 영역이 있을 경우에 Selection.SetPropertyValue( )를 사용해서 원하는 속성으로 변경하는 것을 볼 수 있습니다.

 

전체 소스는 첨부 된 소스 파일을 참조하시기 바랍니다. ^^


신고
2010.01.06 12:00

1.RichTextArea Part 1
2.RichTextArea Part 2
3.Accessing Web Camera and Microphone
4.Right Click Mouse Events
5.MouseWheel API

6.Using Silveright Controls As Drop Targets
7.DataGrid Enhancements
8.Printing API Basics 
9.Hosting HTML Content
10.Accessing the Global Clipboard Programmatically 
11.Using the ViewBox Control 
12.Asynchronous Data Validation 
13.BiDi and Right-to-Left Support 
14.Notification API
15.Local File Access 
16.RIA Services support in Visual Studio 2010  
 

블로그 이미지 김영욱 차장 Microsoft Korea  .NET Evangelist
Enterprise UX 를 위한  UI 기술과 SOA, Cloud Computing, NUI등 다양한 분야의 접목과 응용을 통해 최적의 IT 인프라 구축을 위해서 노력하고 있다.
Email: iwinkey@hotmail.com
Blog: http://winkey.tistory.com

첫 번째 강좌를 시작하기 전에 먼저 몇 가지 체크해야 하는 것 들입니다. 우선 개발 툴과 디자인 툴에 관해서 입니다.

Silverlight 4를 개발하기 위해서는 기본적으로 Visual Studio 2010이 필요합니다. 이 이야기는 Visual Studio 2008에서는 불편하다는 이야기가 아니라 할 수 없다는 이야기 입니다. 따라서 이 강좌를 따라 해 보기 위해서는 Visual Studio 2010을 설치해 주어야 한다는 점을 강조 해 드립니다.

또 디자인 툴도 Expression Blend 4 Preview 버전을 사용하셔야 Silverlight 4 프로젝트를 사용할 수 있습니다. 이와 관련된 환경 설정은 http://www.silverlight.net/getstarted/silverlight-4-beta/ 에 가셔서 필요한 구성 요소들을 설치 할 수 있습니다.

 

개발에 필요한 문서

 

모든 환경을 설치하는데 다소 시간이 걸리기 때문에 마음 편히 먹고 진행하는 것이 정신 건강에 이롭습니다. 특히 Visual studio 2010의 경우는 시간이 꽤 많이 걸립니다. 이제 필요한 환경이 다 구축되었으면 Silverlight 4의 세계에 입문할 준비가 끝났습니다.

 

첫 번째 강좌는 RichTextArea에 관한 내용입니다. Silverlight 4에서 새롭게 추가된 RichTextArea(흔히 다른 툴이나 언어에서는 RichTextBox로 많이 부르고 있습니다.) Silverlight 4의 RichTextArea는 그 기능 만으로 보면 새로울 것 없지만 기존에 제공되지 않던 것이 이번 버전부터 제공 될 수 있게 되었다는 점에서 의미가 있습니다.

 

Silverlight 4 프로젝트를 생성하기 위해서 Visual Studio 2010을 실행 시키고 Silverlight Application 템플릿을 선택해서 프로젝트를 시작합니다. 프로젝트 이름은 RichText로 정했습니다.

 

프로젝트가 생성되고 나면 약간의 디자인 작업을 해야 합니다. Visual Studio 2010에서는 Silverlight 개발 시에 디자인 모드가 지원되지 않았지만 Visual Studio 2010 부터는 디자인 모드가 지원되기 때문에 편리하게 디자인 할 수 있습니다. 하지만 전문적인 디자인은 역시 Expression Blend를 사용해야 합니다.

 

화면에 나타난 폼 중에서 상단에 나타난 상하좌우 화살표를 클릭하면 Grid를 나눌 수 있는 상태가 됩니다.

Grid 분할 영역을 클릭하면 Grid 영역이 분할됩니다. 여기에 간단하게 소스 코드를 입력해서 디자인을 완성해 봅니다. RichTextArea와 버튼을 추가합니다. 각 각의 버튼은 볼드, 이텔릭, 크게, 작게 등 폰트와 관련된 속성을 변경하는 기능을 가지고 있습니다.

 

<UserControl x:Class="RichText.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
      <RowDefinition Height="1*" />
      <RowDefinition Height="7*" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal"
                VerticalAlignment="Stretch"
                HorizontalAlignment="Stretch"
                Grid.Row="0"
                Background="Beige">
      <Button x:Name="boldButton"
              Content="Bold"
              FontWeight="Bold"
              VerticalAlignment="Center"
              HorizontalAlignment="Left"
              Margin="5"
              Background="LightBlue" />
      <Button x:Name="italicsButton"
              Content="Italics"
              FontStyle="Italic"
              VerticalAlignment="Center"
              HorizontalAlignment="Left"
              Margin="5"
              Background="LightBlue" />
      <Button x:Name="biggerButton"
              Content="Bigger"
              FontSize="14"
              VerticalAlignment="Center"
              HorizontalAlignment="Left"
              Margin="5"
              Background="LightBlue" />
      <Button x:Name="smallerButton"
              Content="Smaller"
              FontSize="10"
              VerticalAlignment="Center"
              HorizontalAlignment="Left"
              Margin="5"
              Background="LightBlue" />
    </StackPanel>
      <RichTextArea x:Name="rtArea"
                  Grid.Row="1"
                  Background="Beige"
                  FontFamily="Georgia"
                  FontSize="12"
                  HorizontalContentAlignment="Left"
                  MinHeight="50"
                  MinWidth="50"
                  TextWrapping="Wrap"
                  VerticalContentAlignment="Top"
                  VerticalScrollBarVisibility="Auto" />
  </Grid>
</UserControl>

 

이제 각 각의 버튼에 대한 C#코드를 작성해서 해당되는 기능을 완성하려고 합니다. 먼저 샘플 텍스트를 넣어줄 간단한 메소드를 추가 합니다.

 

private void FillText()
{
    rtArea.Selection.Text = "Lrem ipsum dolor sit amet, consectetur adipiscing elit. Aenean"
        + "congue, orci ut placerat dignissim, nibh odio imperdiet diam, in porta libero lacus sit amet risus."
        + "Nullam ultrices purus nec sapien pellentesque at dignissim leo facilisis. Phasellus congue convallis metus, "
        + "eu ultrices augue malesuada sit amet. Nam varius, leo ac pretium pharetra, arcu turpis varius tellus, "
        + "vitae lacinia turpis dolor vitae mauris. Maecenas lacinia laoreet justo, eget imperdiet nulla porta eu. "
        + "Etiam nec elit vel lacus rhoncus vehicula at rutrum elit. Nunc cursus, erat vel rhoncus porta, leo ipsum venenatis "
        + " nisi, nec eleifend ligula quam non massa. Sed neque odio, euismod at egestas ac, scelerisque et nisl. Cum sociis "
        + "natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam ornare risus augue, nec semper  "
        + "mauris. Nam feugiat suscipit arcu, sit amet mattis purus lacinia at. Sed ut purus at arcu rhoncus elementum ac at  "
        + "enim. Morbi at quam ac magna rutrum gravida eu lacinia neque. Mauris purus augue, ornare sed vestibulum ac, lacinia  "
        + "in sapien. Ut sit amet vehicula augue. Donec a dictum felis. In hac habitasse platea dictumst.  "
        + "Pellentesque id hendrerit diam. ";
}

 

길어서 그렇지 그냥 문장을 계속 더해서 rtArea에 넣는 문장입니다. ^^ 그리고 각 버튼의 클릭 이벤트에 대한 이벤트 핸들러를 작성해 주어야 합니다.

 

boldButton.Click += new RoutedEventHandler(buttonClickHandler);
italicsButton.Click += new RoutedEventHandler(buttonClickHandler);
biggerButton.Click += new RoutedEventHandler(buttonClickHandler);
smallerButton.Click +=new RoutedEventHandler(buttonClickHandler);

 

네 개의 버튼 모두 buttonClickHandler라는 이벤트 핸들러를 호출하게 되어 있습니다. buttonClickHandler에서 다음과 같은 부분들을 추가 합니다.

 

void buttonClickHandler(object sender, RoutedEventArgs e)
{
    Button b = sender as Button;

    const double MaxFontSize = 36;
    const double MinFontSize = 10;
    const double IncrementFontSize = 2;

    if (b != null)
    {
        switch (b.Content.ToString().ToUpper())
        {
            case "BOLD":
                if (rtArea.FontWeight == FontWeights.Bold)
                {
                    rtArea.FontWeight = FontWeights.Normal;
                    b.FontWeight = FontWeights.Bold;
                }
                else
                {
                    rtArea.FontWeight = FontWeights.Bold;
                    b.FontWeight = FontWeights.Normal;
                }
                break;
            case "ITALICS":
                rtArea.FontStyle = rtArea.FontStyle == FontStyles.Italic ? FontStyles.Normal : FontStyles.Italic;
                b.FontStyle = rtArea.FontStyle == FontStyles.Italic ? FontStyles.Normal : FontStyles.Italic;
                break;
            case "BIGGER":
                rtArea.FontSize = rtArea.FontSize > MaxFontSize ? MaxFontSize : rtArea.FontSize + IncrementFontSize;
                break;
            case "SMALLER":
                rtArea.FontSize = rtArea.FontSize < MinFontSize ? MaxFontSize : rtArea.FontSize - IncrementFontSize;
                break;

        }
    }

}

어느 버튼에서 이 이벤트 핸들러를 클릭했는지 알기 위해서 sender를 버튼으로 받고 최대 글자 크기와 최소 글자 크기를 설정 하기 위해서 상수를 정의 했습니다. 그리고 증가치도 함께 설정 했습니다.

 

버튼이 null이 아닐 경우에 b.Content.ToString().ToUpper()를 거쳐서 버튼의 텍스트를 읽어 와서 어떤 버튼이 클릭 되어서 여기에 왔는지 구분 할 수 있게 했습니다.

 

BOLD의 경우 FontWeight가 Bold이면 Normal로 Normal 이면 Bold로 속성을 바꾸게 되어 있으며

ITALICS도 마찬가지로 동작을 하지만 ?를 이용한 삼항 연산자를 통해서 좀더 간결하게 표현할 수 있게 했습니다.

BIGGER와 SMALLER의 경우 폰트 크기의 최대 혹은 최소 크기가 아니면 증가값을 더하거나 뺄 수 있게 했습니다.

 

벌써 RichTextArea를 활용하는 샘플이 완성되었습니다. 이제 F5만 눌러 보시면 다음과 같은 결과물을 보실 수 있습니다.

 



여기까지 완성된 샘플 파일입니다.


신고


티스토리 툴바