안녕하세요? 맨날맑음 입니다.

Visual Studio 2010 정식 버전이 나온 지 꽤 시간이 흘렀고, 저는 선물로 받은 MSDN Subscriptions을 이용하여 사용하고 있습니다. 블로그를 운영하는 개발자라면 포스팅 내용 중에 소스코드를 넣는 일이 많이 있으실 텐데요. 블로그에 소스코드를 넣는 것은 단순히 Copy & Paste하는 방법이 있겠지만 이렇게 되면 소스코드의 색이 일괄적으로 검은색으로 나타나서 보기 불편하게 됩니다.

Google code의
SyntaxHighlighter와 같은 스크립트를 이용하는 방법이 있지만 저처럼 MS Word나 Live Writter를 이용하여 포스팅 하는 경우에는 포스팅 이후에 다시 수정하여, 소스코드 부분에 스크립트를 붙여 주어야 하기 때문에 불편한 점이 많은 것이 사실입니다.


그래서 제가 사용하는 방법은 MS Word를 이용하여 포스팅 하는 것 인데요, 그림을 붙여 넣기 하기도 편하고, 워드 프로그램의 특성 상 글을 편집하고 관리하기도 편리합니다. 그런데
Visual Studio 2010을 사용하면서 문제점이 생겼습니다. 소스코드를 붙여넣기 하면 주석에 포함된 한글이나 소스코드에 포함된 한글은 모두 깨져서 붙여지는 현상인데요.  

protected void btnRegister_Click(object sender, EventArgs e)

 {

     switch (MemberAuthenticate.MemberCheck(tbID.Text, tbPassword.Text))

     {

         case -2:

             lblInfo.Text = "IöI Æ¢®OìE ú¨¡Iì©£ O¥I¥U";

             return;

         case -3:

             lblInfo.Text = "ú¨¡Iì©£¯I ¡¨¢ö¨¬¯oìa¬| ¢´¢ç¡À O¤AIù¨ù¯a";

             return;

     }

 }

해결 방법은 VS2010 플러그인을 설치하시면 됩니다.


-Fig1. Visual Studio2010 확장 관리자-

VS2010에서 새롭게 추가된 기능인 확장 관리자는 VS에 추가되는 여러 기능을 손쉽게 설치할 수 있도록 도와주는 메뉴입니다. [도구 -> 확장 관리자]를 선택하면 확장 관리자를 볼 수 있는데요. 왼쪽의 메뉴에서 온라인 갤러리를 선택하시면 다양한 플러그인을 볼 수 있습니다. 한글 깨짐을 해결 하기 위해서는 Productivity Power Tools를 설치 하시면 됩니다. 마우스 더블클릭만으로 손쉽게 설치되어 편리하게 사용 할 수 있습니다.

다른 방법으로 Productivity Power Tools를 설치 하시려면 여기에서 다운로드 받아 설치 하시면 됩니다.


-Fig2. Productivity Prower Tools 다운로드 페이지-

설치하니 소스코드의 한글이 무사하군요! 사소하지만 모르면 완전 불편한 팁이었습니다!

private void listView1_DragDrop(object sender, DragEventArgs e)
{
    string[] dropFiles = e.Data.GetData(DataFormats.FileDrop) as string[];
    if (dropFiles != null)
    {
        foreach (string fileName in dropFiles)
        {           
            //파일에서 아이콘 추출
            Icon icon = Icon.ExtractAssociatedIcon(fileName);
            //이미지리스트에 아이콘 추가
            imageList.Images.Add(icon);
            //리스트뷰에 파일명과 인덱트 추가
            listView1.Items.Add(fileName.Substring(fileName.LastIndexOf("\\") + 1), listView1.Items.Count);
        }             

}

Posted by 맨날맑음

안녕하세요? 맨날맑음 입니다.

이번 포스팅은 WPF에서 마우스 드래그를 이용한 간단한 사각형 그리기입니다. 이 예제를 응용하면 원이나 선도 그릴 수 있고, 자료구조를 이용하면 윈도우 그림판과 같은 기능도 쉽게 만들 수 있습니다.

-Fig1. 사각형을 그리는 WPF 어플리케이션-

Fig1에서 보는 바와 같이 마우스의 현재 좌표를 왼쪽 상단에 표시해 주며, 드래그를 이용하여 사각형을 그리는 기능을 합니다. WPF에서 제공하는 InkCanvas객체를 이용하면 더 간단하게 구현도 가능 하겠네요^^; 하지만 이번에는 Grid에 사각형을 그리는 방법으로 구현해 보겠습니다.

 

 

#1. 마우스 이벤트

-Fig2. WPF Window의 마우스 이벤트-

WPF의 컨트롤은 마우스 이벤트를 가지고 있습니다. 마우스 다운이나 업, 마우스 무브, 마우스 휠 등 이벤트를 지원하는데요. 우리 예제에서는 MouseLeftButtonDown과 MouseMove, MouseLeftButtonUp 세 가지 이벤트를 사용합니다. 마우스 이벤트 핸들러에서는 MouseEventArgs 객체가 인자로 넘어오고 이 이벤트객체를 이용하면 현재 마우스의 상태정보를 알 수 있습니다.

 

이름

설명

Device

이 이벤트를 시작한 입력 장치를 가져옵니다. (InputEventArgs에서 상속됨)

Handled

라우트된 이벤트가 경로를 따라 이동할 때의 현재 이벤트 처리 상태를 나타내는 값을 가져오거나 설정합니다.

LeftButton

마우스 왼쪽 단추의 현재 상태를 가져옵니다.

MiddleButton

마우스 가운데 단추의 현재 상태를 가져옵니다.

MouseDevice

이 이벤트와 연결된 마우스 장치를 가져옵니다.

OriginalSource

부모 클래스에서 Source를 조정하기 전에 순수 적중 테스트에 의해 결정되는 원본 보고 소스를 가져옵니다.

RightButton

마우스 오른쪽 단추의 현재 상태를 가져옵니다.

RoutedEvent

RoutedEventArgs 인스턴스와 연결된 RoutedEvent를 가져오거나 설정합니다. (RoutedEventArgs에서 상속됨)

Source

이벤트를 발생시킨 개체에 대한 참조를 가져오거나 설정합니다. (RoutedEventArgs에서 상속됨)

StylusDevice

이 이벤트와 연결된 스타일러스 장치를 가져옵니다.

Timestamp

이 이벤트가 발생한 시간을 가져옵니다. (InputEventArgs에서 상속됨)

XButton1

첫 번째로 확장된 마우스 단추의 현재 상태를 가져옵니다.

XButton2

두 번째로 확장된 마우스 단추의 현재 상태를 가져옵니다.

- MouseEventArgs 의 속성 (출처 : MSDN)-

이벤트 객체의 속성을 통해 마우스의 현재 상태정보를 알 수 있으며, GetPosition() 메서드를 이용하면 마우스 포인트의 좌표를 얻어 올 수도 있습니다.

 

#2. Shape객체

WPF에서 Rectangle, Ellipse, Polygon과 같은 모든 도형의 기본 클래스는 Shape입니다. Shape는 UI 요소이므로 패널이나 대부분의 컨트롤에서 사용 할 수 있습니다. Stroke 속성을 사용하면 도형의 테두리(윤곽선)의 색상을 지정 할 수 있고, StrokeThickness 속성을 이용하면 도형의 테두리 두께를 설정 할 수 있습니다. 또한 Fill 속성을 이용하면 도형의 표면 색상을 설정 할 수 있습니다.

 

-Fig3. 여러 속성을 적용하여 랜더링 된 원의 모습-

 

#3. 코드 구현

코드가 간단하여, 대부분의 설명은 주석으로 코드설명을 대신합니다. WPF 프로젝트를 생성하고, 다음과 같은 코드를 넣어 줍니다.

 

    

-Code1. MainWindow.xaml-

 

 
public partial class MainWindow : Window
 {
     /// 
     /// 드레그를 시작한 마우스 좌표;
     /// 
     Point prePosition;
     /// 
     /// 현재 그려지는 사각형
     /// 
     Rectangle currentRect;

     public MainWindow()
     {
         InitializeComponent();
         //이벤트 핸들러 생성
         this.root.MouseLeftButtonDown += new MouseButtonEventHandler(root_MouseLeftButtonDown);
         this.root.MouseMove += new MouseEventHandler(root_MouseMove);
         this.root.MouseLeftButtonUp += new MouseButtonEventHandler(root_MouseLeftButtonUp);
         
         // 좌표를 나타내는 TextBlock을 최상위로 ...
         Grid.SetZIndex(this.tbPosition, 99999);
     }

     /// 
     /// 마우스 클릭 해제 이벤트 핸들러
     /// 
     /// 
     /// 
     void root_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
     {
         //마우스 캡춰를 제거한다.
         this.root.ReleaseMouseCapture();
         SetRectangleProperty();
         currentRect = null;
     }

     private void SetRectangleProperty()
     {
         //사각형의 투명도를 100% 로 설정
         currentRect.Opacity = 1;
         //사각형의 색상을 지정
         currentRect.Fill = new SolidColorBrush(Colors.LightYellow);
         //사각형의 테두리를 선으로 지정
         currentRect.StrokeDashArray = new DoubleCollection(); ;
     }

     /// 
     /// 마우스 이동 이벤트 핸들러
     /// 
     /// 
     /// 
     void root_MouseMove(object sender, MouseEventArgs e)
     {
         
         //현재 이동한 마우스의 좌표를 얻어온다
         Point currnetPosition = e.GetPosition(this.root);
         //좌표를 표시한다.
         this.tbPosition.Text = string.Format("마우스 좌표 : [{0},{1}]", currnetPosition.X, currnetPosition.Y);
         //마우스 왼쪽 버튼이 눌려있으면
         if (e.MouseDevice.LeftButton == MouseButtonState.Pressed)
         {
             if (currentRect != null)
             {
                 //사각형이 나타날 기준점을 설정한다.
                 double left = prePosition.X;
                 double top = prePosition.Y;
                 //마우스의 위치에 따라 적절히 기준점을 변경한다.
                 if (prePosition.X > currnetPosition.X)
                 {
                     left = currnetPosition.X;
                 }
                 if (prePosition.Y > currnetPosition.Y)
                 {
                     top = currnetPosition.Y;
                 }
                 //사각형의 위치 기준점(Margin)을 설정한다
                 currentRect.Margin = new Thickness(left, top, 0, 0);
                 //사각형의 크기를 설정한다. 음수가 나올 수 없으므로 절대값을 취해준다.
                 currentRect.Width = Math.Abs(prePosition.X - currnetPosition.X);
                 currentRect.Height = Math.Abs(prePosition.Y - currnetPosition.Y);
             }
         }
     }

     /// 
     /// 마우스 왼쪽 버튼 클릭 이벤트 핸들러
     /// 
     /// 
     /// 
     void root_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
     {
         //마우스의 좌표를 저장한다.
         prePosition = e.GetPosition(this.root);
         //마우스가 Grid밖으로 나가도 위치를 알 수 있도록 마우스 이벤트를 캡처한다.
         this.root.CaptureMouse();
         if (currentRect == null)
         {
             //사각형을 생성한다.
             CreteRectangle();               
         }
     }

     private void CreteRectangle()
     {
         
         currentRect = new Rectangle();
         currentRect.Stroke = new SolidColorBrush(Colors.DarkGreen);
         currentRect.StrokeThickness = 2;
         currentRect.Opacity = 0.7;
         //사각형을 그리는 동안은 테두리를 Dash 스타일로 설정한다.
         DoubleCollection dashSize = new DoubleCollection();
         dashSize.Add(1);
         dashSize.Add(1);
         currentRect.StrokeDashArray = dashSize;
         currentRect.StrokeDashOffset = 0;
         //사각형의 정렬 기준을 설정한다.
         currentRect.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
         currentRect.VerticalAlignment = System.Windows.VerticalAlignment.Top;
         //그리드에 추가한다.
         this.root.Children.Add(currentRect);
     }
 }

-Code2. MainWindow.xaml.cs-

마우스를 드래그하는 동안은 그림판이나 포토샵에서와 같이 점선으로 사각형의 모양을 표시 해 줄 필요가 있기 때문에 테두리의 속성을 변경 할 필요가 있습니다. 테두리를 점선으로 표시하는 속성은 Rectangle객체의 StrokeDashArray를 사용하여 설정 할 수 있으며, XAML에서는 다음과 같이 표현 할 수 있습니다.

 

-Fig4. StrokeDashArray 속성이 적용 된 Ellipse-

소스 빌드 환경 : VisualStudio2010, .NET Framework4.0

Posted by 맨날맑음

작성중

일반적으로 동적인 웹 사이트 개발 시 상태관리(State Management)가 필요 합니다. 이번 포스팅에서는  상태관리가 무엇인지와 우리가 일반적으로 많이 사용하는 쿠키(Cookie)와 세션(Session)에 대해 자세히 알아 보도록 하겠습니다.

 

#1. 웹 서버 동작 원리

웹 사이트 상태관리의 필요성을 알기 위해 웹 서버와 클라이언트(웹 브라우저)가 어떠한 방식으로 동작 하는지를 먼저 알아 보겠습니다.

image-Fig1. 정적 웹 서버 동작 원리-

 

Fig1을 보면 아주 간단한 원리로 동작 하는 것을 알 수 있는데요. 클라이언트가 HTTP 프로토콜을 사용하여 웹 서버로 요청(Request)을 하게 되면 웹 서버는 해당 하는 HTML을 웹 브라우저로 전송 해 주고 웹 브라우저는 응답(Response) 받은 HTML을 파싱하여 사용자에게 보여주게 됩니다. 여기서 ‘요청’이란 우리가 웹 브라우저의 주소 표시줄에 http://crynut84.tistory.com이라고 입력 하는 행위나 웹 사이트의 링크를 마우스로 클릭하는 행위 등을 말합니다.

 

웹 사이트는 다시 정적인 웹 사이트와 동적인 웹사이트로 나눌 수 있습니다. 정적인 웹 사이트는 웹 서버에서 .HTML 파일을 완성된 .HTML 파일을 가지고 있다가 클라이언트의 요청이 있을 시 해당하는 .HTML 파일을 돌려 주는 형태입니다. 당연히 HTML 페이지의 내용들은 이미 결정 되어있어 있으므로 클라이언트의 상태, 방문정보, 시각등의 내용에 관계없이 항상 동일한 HTML 페이지를 보여줍니다. 요즘은 이런 웹사이트는 거의 없을 듯 합니다.

 

동적인 웹 사이트는 사용자의 액션에 따라 웹 사이트가 다르게 동작 하는 것을 말합니다. 예를들어 요즘 웹 사이트는 거의 로그인이라는 인증 과정을 거치게 되고, 로그인을 하면 ‘전호진님 환영합니다’라고 환영 인사도 해줍니다. 또한 게시판은 검색어에 따라 다른 결과를 보여주게 되고, 사용자 입맛에 맛게 정렬도 할 수 있습니다. 이와같이 요즘 일반적으로 볼 수 있는 사용자와 웹사이트가 서로 상호작용을 하는 웹 사이트를 동적인 웹사이트라고 합니다.

 

동적인 웹사이트를 만드는 기술은 ASP.NET, JSP, ASP, PHP, CGI등 여러 가지가 있습니다. 마이크로소프트의 동적인 웹사이트를 만드는 기술인 ASP.NET의 동작 원리(Fig2)를 보면 정적 웹사이트와 조금 다른 것을 알 수 있는데요.

image-Fig2. 동적 웹 서버 동작 원리-

 

클라이언트가 요청하게 되면 웹 서버는 요청에 대한 적절한  HTML을 새롭게 생성 합니다. 요청에 대한 일련의 처리(로직 수행)를 수행하게 되고 처리 결과를 다시 클라이언트에 돌려 주게 되는데 동적인 웹 사이트라고 해도 클라이언트가 받는 최종 응답은 정적인 HTML 페이지입니다. 예를들어 게시판에 여러 게시글이 있는데 사용자가 ASP.NET을 검색어로 입력하고 검색 버튼을 누르게 되면 이 요청을 웹서버가 받아서 게시글 중 ASP.NET이 들어간 결과만 찾아서 형식에 맞는 HTML을 구성하게 되고 클라이언트에 응답하주게 되는 것입니다. 이렇게 동적인 처리를 위해 ASP.NET과 같은 웹 기술이 필요하게 되고, 모든 처리는 웹 서버에서 수행되며, 클라이언트의 입장에서는 정적인 웹 사이트와 동일하게 웹 서버에 요청을 하고 응답받은 결과를 파싱하여 보여 주게 됩니다.

 

#2. 상태 관리(State Management)

웹 사이트를 사용하는 사용자는 HTTP GET방식이나 HTTP POST방식을 사용하여 웹 서버로 페이지를 요청하게 되고, 웹 브라우저는 웹 서버에서 응답받은 HTML을 파싱하여 렌더링하게 됩니다. 이러한 일련의 주기를 ‘라운드트립(Round Trip)’ 이라고 합니다.그런데 HTTP 프로토콜은 상태를 저장 할 수 없는 프로토콜입니다. 이 말은 클라이언트의 요청이 왔을대 웹 서버는 해당 요청에 대한 응답인 HTML을 보내주고 연결을 끊어버린다는 것입니다. 그렇기 때문에 라운드트립 시 페이지에 있는 컨트롤의 사용자 입력정보나 페이지의 정보들이 모두 손실 되게 됩니다.  예전에 사용하던 정적인 웹사이트(일방적으로 보기만 하는 웹사이트)에서는 문제가 되지 않지만 동적인 웹사이트에서는 사용자의 요청이나 컨트롤의 입력정보를 유지할 필요가 있기 때문에 ASP.NET은 상태 관리를 할 수 있는 여러가지 기능을 제공합니다.

 

상태관리의 정보를 저장하는 장소에 따라 두가지로 분류 할 수 있는데, 웹 서버에 저장하는 경우와, 클라이언트에 저장하는 경우가 있습니다.

▶ 상태 정보를 클라이언트에 저장하는 방식

  • 뷰 상태(View State)
  • 컨트롤 상태(Control State)
  • 숨겨진 필드(Hidden Field)
  • 쿠키(Cookie)
  • 쿼리 문자열(Query String)

상태 정보를 웹 서버에 저장하는 방식

  • 응용 프로그램 상태(Application State)
  • 세션(Session)
  • 프로필 속성(Profile Property)
  • 데이터베이스(Database)

두가지 방식은 장단점이 존재 하는데요. 일반적으로 데이터가 작고, 중요하지 않은(보안 등의 이유)정보는 클라이언트 측에서 관리하고, 나머지는 웹 서버에서 관리 하는 것이 좋습니다. 여러가지 상태관리 기능 중 Cookie와 Session에 관해 자세히 알아보겠습니다.

 

#3. 쿠키(Cookie)

-Fig3. 맛있는 쿠키-

 

쿠키는 요청 및 응답하는 과정에 포함되는 텍스트 정보이고 쉽게 구현하여 사용 할 수 있는 방법중에 하나입니다. 일반적인 브라우저에서 최대 4KB의 텍스트 정보를 담을 수 있으며 하나의 사이트는 20개만 허용되며, 모든 사이트를 통틀어서 300개로 제한 됩니다. 만약 이 범위를 넘어 더 많이 저장 하려고 할 경우에는 가장 오래된 쿠키부터 삭제되므로 사용의 주의해야하고, 4KB로 비교적 작은 크기만을 저장하기 때문에 적은 양의 데이터나 ID, 최근 읽은 글, 최근 본 상품과 같은 식별자를 저장할 때 사용하는 것이 적합합니다.

 

1. 쿠키의 동작 방식

쿠키는 서버에서 생성하여 클라이언트의 브라우저에서 관리하기 때문에 요청시 쿠키를 생성하고 브라우저를 닫을때 쿠키를 파괴합니다. 응답을 통해 얻어온 쿠키는 만료시간 여부에 따라 클라이언트의 PC에 파일로 저장하게 됩니다.

 

image

-Fig4. 웹 사이트를 처음 요청 할 경우 쿠키 생성 -

 

쿠키의 생성 주기를 살펴보면처음으로 페이지를 요청 할 경우 웹 서버에서는 쿠키를 생성하게 되고, 페이지를 돌려 줄때 HTTP 헤더에 쿠키를 포함하여 돌려 주게 됩니다. 이렇게 넘겨 받은 쿠키는 클라이언트에서 관리 하고 있다가, 다음번 요청때 쿠키를 함께 전송하게 되고, 서버에서는 쿠키 정보를 읽어 이전 상태 정보를 알 수 있게 됩니다. 이때 웹 서버는 Fig5에서 처럼 정보를 변경 할 필요가 있을때 쿠키를 업데이트하여 다시 변경된 쿠키와 함께 응답하게 됩니다.

image -Fig5. 쿠키를 가지고 있을 경우 쿠키 활용-

2. ASP.NET에서 쿠키 사용

쿠키는 서버로 부터 응답받은 사항이기 때문에 HttpResponse 객체를 통해 클라이언트로 전송 됩니다. 쿠키에 정보를 저장하는 방법은 두가지가 있습니다. Page클래스의 Response 객체를 사용하는 것과 HttpCookie 클래스를 사용하는 방법입니다.

//Response 사용 
Response.Cookies["쿠키명1"].Value = "쿠키 예제;
Response.Cookies["쿠키명1"].Expires = DateTime.Now.AddMinutes(30); 

//HttpCookie 클래스 사용 HttpCookie cookie = new HttpCookie("쿠키명2");
cookie.Value = "쿠키 예제";
cookie.Expires = DateTime.Now.AddSeconds(30); 
Response.Cookies.Add(cookie);

-Code1. 쿠키 저장-

쿠키명1과 쿠키명2라는 이름을 사용하는 쿠키를 생성 하였고 각각 Value 속성을 통해 상태유지에 필요한 값을 넣어 주었습니다. Expires 속성은 만료 기간인데, 이 속성을 설정하면 쿠키가 클라이언트의 컴퓨터의 파일의 형태로 저장됩니다.  만료기간을 설정하지 않은 쿠키는 브라우저의 메모리에서 관리됩니다. Code1에서 쿠키명1은 30분후에 쿠키를 지우며, 쿠키명2는 30초 후에 쿠키를 지우도록 설정 하였습니다. 만료시간이 지난 쿠키는 클라이언트가 쿠키를 생성한 웹 사이트에 다시 요청을 보낼때 삭제됩니다.

'.NET > ASP.NET' 카테고리의 다른 글

쿠키(Cookie)와 세션(Session)  (2) 2010.09.09
Posted by 맨날맑음