2D Geometry in WPF

  
    
      
    
  

Path를 이용한 Geometry를 렌더링 하는 가장 간단한 코드이다. Rectangle Geometry를 나타내고 있다. Path Element의 속성으로써 Stroke와 Fill을 줄 수 있는데, Stroke는 외곽선의 색상을 의미하고 Fill은 채움색을 의미한다. StrokeThickness는 외곽선의 굵기값이다.

   
     
       
         
         
         
       
     
   

Path를 이용한 Geometry를 렌더링하는 코드로써 여러개의 Geometry를 하나의 Geometry로 묶기 위해 GeometryGroup Element를 사용하였다. GemoetryGroup는 FillRule 속성을 가지고 있으며 EvenOdd와 Nonzero 값을 가질 수 있다. FillRule는 Geometry가 서로 겹치는 부분을 어떻게 처리할 것인지를 결정하는 것으로써 Nonzero는 그냥 채움이고 EvenOdd는 빈공간으로 채우지 않는다.

  
  
     
       
       
       
     
  
  

FillRule를 EvenOdd인 경우이다.

  
  
     
       
         
           
             
               
                 
                 
               
             
           
           
             
               
                 
                 
               
             
           
         
       
     
  
  

Path를 생성하는 방법으로써 직접 직선이나 다양한 곡선을 이용해 구성하는 방법이다. 직선을 이용한 예로써 LineSegment를 사용하였다.

  
  
     
       
         
           
             
               
                 
               
             
           
         
       
     
  
  

곡선을 이용한 예로써 ArcSegment를 이용하였다. Stroke를 완전하게 폐합하고자 한다면 PathFigure Element의 IsClosed 속성을 True로 주면 된다. 기본값은 False이다.

  
  
     
       
         
           
             
               
                 
               
             
           
         
       
     
  
  

곡선을 이용한 또 다른 예로써 QuadraticBezierSegment를 사용하였다.

  
  
     
       
         
           
             
               
                 
               
             
           
         
       
     
  
  

곡선을 이용한 또 다른 예로써 BezierSegment를 사용하였다.

  
  
     
       
       
       
       
       
         
           
             
               
                 
                   
                   
                 
               
             
           
         
       
     
  
  

Geometry를 이용하여 Image를 Clip하는 코드이다. 이미지를 화면에 나타내기 위해 가장 먼저 Image Element를 사용하였고 Source로 이미지 파일을 지정하였다. 이후에 Clip하기 위한 Geometry를 지정하기 위하는데, 두개 이상의 Geometry를 지정하기 위해 GeometryGroup Element를 사용하였으며 Geometry로써 단순 Geometry와 Path를 이용한 복합 Geometry를 사용하여 Clip을 위한 Geometry를 생성한다.

  
  
     
       
       
       
       
       
         
           
             
               
                 
                   
                   
                 
               
             
           
         
       
     
  
  

Path를 생성하기 위해 두개 이상의 Geometry를 사용할 경우 GeometryGroup로 묶게 되는데, 하나의 Geometry로써 PathGeometry를 사용하여, 이 PathGeometry Element 안쪽에 여러개의 Geometry 격인 PathFigure를 넣는 경우에 대한 코드이다.

  
  
     
       
         
           
             
           
           
             
               
               
               
               
               
                 
                   
                     
                       
                         
                           
                           
                         
                       
                     
                   
                 
               
             
           
         
       
     
  
  

Path 자체를 채움을 위한 Brush의 Pattern으로 사용하는 코드이다.

Path를 생성하는 세번째 경우로써 가장 최적화되고 함축적인 방법이다. Path Element의 Data 속성을 이용하여 좌표를 직접 하나 하나 지정한다. M은 Move, L은 Line, Z는 폐합을 의미한다. Data로써 Data=”M 10,10 A 100,50,45,1,0,200,100″와 Data=”M 10,100 C35,0 135,0 160,100 S285,200 310,100″, Data=”M 10,100 Q 200,200 300,100″, Data=”M 10,100 C 100,0 200,200 300,100″, Data=”M 10,50 V 200″, Data=”M 10,50 H 200″를 사용하여 그 결과를 확인해보기 바란다.

  
  
     
       
         
       
       
         
       
     
  
  

Path를 구상하는 Geometry에 대한 결합규칙을 지정하는 방법 중 Xor 규칙에 대한 코드와 그 결과이다. 겹치는 부분에 대해서 채움을 무시한다.

  
  
     
       
         
       
       
         
       
     
  
  

Path를 구성하는 Geometry를 하나의 Geometry로 합하는 것으로 겹합규칙을 Union을 사용하였다.

  
  
     
       
         
       
       
         
       
     
  
  

Path를 구성하는 Geometry들이 교차하는 부분만을 남기고 나머지는 무시하는 것으로 결합규칙으로써 Intersect를 사용하였다.

  
  
     
       
         
       
       
         
       
     
  
  

Path를 구성하는 Geometry들에서 첫번째에서 두번째 Geometry를 뺀 부분만을 남기는 것으로 결합규칙은 Exclude이다.

Non-Rectangle Window in WPF

오늘 작성해본 WPF에서 직사각형이 아닌 창을 나타내는 코드이다. UI 부분이므로 모든 주요 코드는 XAML에서 작성되며 드레그했을시에 창이 이동되는 이벤트 처리는 Behind Code(.CS 파일)에서 작성하였다. 먼저 XAML 코드는 아래와 같다.


  
    
      
        
          
          
          
          
        
      

      
        
          
            
            
            
            
            
            
            
            
          
        
      
    

    

창을 원하는 모양으로 만들기 위해서 반드시 설정해야할 Window의 속성은 위의 코드에서 분홍색으로 나타낸 WindowStyle, AllowTransparency, Background 속성이다. 그리고 Path Element를 이용해 원하는 모양을 그려주면 끝이다. 참으로 간단하면서도 명확하다. 실행 결과는 다음과 같다.

드레그를 하면 창이 이동을 하는데 그와 관련된 코드는 다음과 같다. 마우스의 왼쪽 버턴을 눌렸을 경우 발생하는 이벤트이다.

void eventMouseLeftButtonDown(object sender, 
                              MouseButtonEventArgs e) {
     DragMove();
}

WPF 어플리케이션 라이프 사이클(Application Life Cycle)


MSDN에 있는 WPF의 라이프 사이클에 대한 그림이다. 가운데 Application Object 상자 안이 코어 부분인데, 하나의 Application은 Run 매서드로 시작해서 Shutdown 매서드의 호출로 끝나게 된다. Shoutdown 매서드의 호출은 ShutdownMode의 값에 따라서 Application이 자동으로 호출해주는 경우와  사용자가 반드시 호출해주는 경우로 구분된다. 그리고 Activated, Deactivated, DispatcherUnhandledException, SessionEnding, Exit는 Application에 발생하는 이벤트이다. SessionEnding의 경우는 사용자가 OS를 Shutdown하거나 Logoff 시에 호출되는데 이 이벤트 안에서 OS의 종료를 취소시킬 수 있다. 또한 DispatcherUnhandledException 이벤트는 Application에서 처리되지 않는 예외가 발생했을 경우에 발생하는 범용 예외 처리가 가능한 곳으로 지정하지 않았을 경우 예외가 발생하면 Application은 자동으로 종료된다.


위의 그림은 WPF Window Application에 대한 또 다른 Life-Cycle이다. 모두 이벤트 명이다.

Singleton Pattern in C#

대다수의 패턴이 그런 것처럼 Singleton Pattern(이하 Singleton) 역시 언어에 독립적인 부분이 많기는 하지만 갑작스레 다소 익숙치 않은 C#으로 Singleton을 구현할 필요가 생겨 하나의 템플릿의 목적으로 작성해 놓는다.

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}

Singleton은 클라이언트 측에서 오직 하나의 Instance만을 생성하도록 제한해야 하므로 임으로 클라이언트가 생성하지 못하도록 생성자를 private로 선언하고 있음을 알 수 있다. 대신 Instance를 C#의 편리한 Property 문법을 사용해서 만들고 이를 통해 오직 하나의 Instance만을 만든다. Instance Propery의 get의 구현을 보면 static으로 선언된 자신의 클래스 타입인 instance 변수가 null인 경우, 즉 생성되지 않은 경우 단 한번 생성해 주고 반환하고 있음을 알 수 있다. 한번 생성된 경우라면 생성과정 없이 그저 반환만 이루어진다. 다른 Pattern에 비해 그 목적과 구현하는 것에 어려움이 없을 것이다. 하지만 한발작 더 접근해서 Multi Thread 환경에서 Singleton을 바라보면 오류의 근원이나 다름없다. 즉 여러개의 Thread에서 Singleton 클래스를 사용할 경우 충돌이 생긴다. 이유는 단 하나의 인스턴스 변수를 여러개의 스레드에서 사용하려 하기 때문이다. 고속화된 CPU나 Singleton 클래스가 무척 작은 코드조각이라면  충돌에의한 오류가 발생 확률이 다소 줄겠지만, 여전이 충돌 확율은 높다. 이에 대한 개선된 코드가 다음과 같다.

public class Singleton
{
   private static Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         lock (syncRoot) {
             if (instance == null) 
             { 
                 instance = new Singleton();

             }

             return instance;
          }
      }
   }
}

lock이라는 C#의 예약어를 사용함으로써 Critical Section을 만들어 주고 있다. 이 섹션 구간의 코드들은 원자성을 갖게 되어 오직 단 하나의 스레드만이 이 구간의 코드를 연속적으로 실행하는 것을 보장하게 된다.

Canon G7 오늘 주문..

2006년 계획 중의 하나였던 디지털카메라 구입을 드디어 실행시켰다. DSLR로 구입하려고 했으나, 내가 무슨 DSLR이냐라는 생각만 들어서 G 시리즈 중 최신인 G7을 주문했다.