통합검색
· 마을서비스란?  · 포럼마을  · 일반마을  · 테마마을  · 마을랭킹  · 활동왕
· 덱스퍼트란?  · TECBOX   · PRSBOX   · 이용안내  
· DEXT제품군  · 솔루션베이  · S/W & ESD 컴포넌트
· 프로그램베이
· LiveSeminar  · LiveConference
WPF & Silverlight 포럼마을입니다.
  마을등급 WPF & Silverlight   이 마을은 포럼마을 입니다이 마을은 자유가입제 마을 입니다 마을소개 페이지로 이동 전입신청
마을촌장촌장 서학수 주민 728 since 2008-07-17
우리마을 공지사항
질문&답변
강좌&팁
자유게시판
자료실
앨범
[마을 게시판]
WPF 강좌
랑데브 게시판
칼럼 게시판
개발자 고충상담
Dev Talk
자유토론방
벼룩시장
재나미 우스개
구인/프로젝트 정보
사람인 채용 게시판
  고객지원 게시판
마이 데브피아
 나의 e-Money 내역
 활동왕 My Page
 스크랩한 게시글보기
 쪽지관리
 주소록관리

 WPF 강좌
 나만의 패널을 만들어보자 ## FishEyePanel 2008-12-07 오후 9:06:16
 inasie  inasie님께 메시지 보내기inasie님을 내 주소록에 추가합니다.inasie님의 개인게시판 가기 번호: 39717  / 읽음:11,847

안녕하세요 ^^

 

처음으로 강좌란에 글을 써봅니다.

 

강좌라고 하기엔 미천할 지 모르지만.. 좋게 봐주셨으면 좋겠습니다 ^^;

 

======================================================================================

 

WPF에는 Canvas나 WrapPanel, Grid 등과 같은 패널들이 존재하죠 ~

 

이러한 패널들을 상속받아 저만의 패널을 만들어 보는 방법을 소개합니다 ^^

 

Fish Eye라고 하면.. 물고기 눈이죠~

 

만들고자 했던 패널은

 

마우스 움직임을 감지하여 마우스 주변의 아이템들의 사이즈를 늘리는 패널입니다.

(맨아래부분에 스샷이 있으니 먼저 참고하셔도 좋을듯 합니다)

 

WrapPanel을 상속받아 사용해 보았습니다.

 

 

나름 상세한 주석을 달아놓았으니 부연설명은 필요 없을것입니다.

 

 

using System;

using System.Collections.Generic;

using System.Windows.Controls;

using System.Windows;

using System.Windows.Media;

using System.Windows.Input;

 

namespace PanelTest

{

    class FishEyePanel : WrapPanel

    {

        List<FrameworkElement> childList;   // 아이템들의 ZIndex를 조절하기 위해 만든 리스트

        double ItemLength = -1; // 아이템(Chilren객체의 대각선 길이)

        double maxArrange = 2;    // 아이템에 마우스가 다가갔을 때의 Max크기(기본값: 2)

 

        public double MaxArrange

        {

            set { maxArrange = value; }

        }

 

 

        #region EventHandler

        /// <summary>

        /// MouseMove 이벤트 핸들러

        /// </summary>

        /// <param name="e"></param>

        protected override void OnMouseMove(MouseEventArgs e)

        {

            AnimateChilds();

            base.OnMouseMove(e);

        }

 

        /// <summary>

        /// MouseLeave 이벤트 핸들러

        /// </summary>

        /// <param name="e"></param>

        protected override void OnMouseLeave(MouseEventArgs e)

        {

            foreach (UIElement child in Children)

            {

                FrameworkElement content = child as FrameworkElement;

                ScaleAnimate(content.RenderTransform as ScaleTransform, 1, 1);

            }

            base.OnMouseLeave(e);

        }

        #endregion

 

        #region Methods

        /// <summary>

        /// Children 객체들의 크기 조정

        /// Children 객체들의 ZIndex 조정

        /// </summary>

        private void AnimateChilds()

        {

            if (childList == null) childList = new List<FrameworkElement>();

           

            childList.Clear();

 

            foreach (UIElement child in Children)

            {

                FrameworkElement content = child as FrameworkElement;

 

                //

                // 크기를 조정하기 위해 아이템의 대각선 길이를 가져옴

                //

                if (ItemLength == -1) ItemLength = GetLength(content.Width, content.Height);

 

                //

                // ScaleTransform이 지정되어있지 않다면 생성

                // RenderTransform이 아닌 LayoutTransform으로 할 경우 애니메이션에 해당하지 않는 객체들까지 움직이게 할 수 있음

                //

                if (content.RenderTransform as ScaleTransform == null)

                {

                    content.RenderTransform = new ScaleTransform(1, 1, content.Width / 2, content.Height / 2);

                }

 

                //

                // 현재 마우스 위치와 아이템간의 거리를 구하고 아이템 크기의 maxScale배수 이하일 때 크기를 조정

                //

                double length = GetLength(Mouse.GetPosition(content).X - (content.Width / 2),  Mouse.GetPosition(content).Y - (content.Height / 2));

                length = maxArrange - (length / (maxArrange * ItemLength));

                if (length < 1) length = 1;

               

                //

                // 크기 조정

                //

                ScaleTransform st = content.RenderTransform as ScaleTransform;

                ScaleAnimate(st, length, length);

               

                //

                // ZIndex를 조절하기 위해 리스트에 추가

                //

                childList.Add(content);

            }

 

            //

            // ZIndex를 조절하기 위해 메소드 호출

            //

            SetChildZIndex();

        }

 

        /// <summary>

        /// 아이템들의 ZIndex를 조절

        /// 마우스에 가까운 아이템이 상단에 올라오도록

        /// </summary>

        private void SetChildZIndex()

        {

            //

            // ScaleTransform ScaleX를 가지고 정렬

            //

            childList.Sort(new CompScale());

 

            //

            // Scale이 클수록 ZIndex에 큰 값이 들어감

            //

            for (int i = 0; i < childList.Count; i++)

            {

                Panel.SetZIndex(childList[i], i);

            }

        }

 

        /// <summary>

        /// 거리를 재기 위해 만든 메소드

        /// </summary>

        /// <param name="x">x포지션</param>

        /// <param name="y">y포지션</param>

        /// <returns>(0, 0)부터 (x, y)좌표 까지의 길이</returns>

        private double GetLength(double x, double y)

        {

            return Math.Sqrt(x * x + y * y );

        }

 

        /// <summary>

        /// ScaleTransform ScaleX ScaleY를 셋팅

        /// </summary>

        /// <param name="st">ScaleTranfrom객체</param>

        /// <param name="scaleX">X Scale(배수)</param>

        /// <param name="scaleY">Y Scale(배수)</param>

        private void ScaleAnimate(ScaleTransform st, double scaleX, double scaleY)

        {

            st.ScaleX = scaleX;

            st.ScaleY = scaleY;

        }

        #endregion

    }

 

    /// <summary>

    /// ScaleTransform ScaleX를 이용해 리스트를 정렬시키기 위해 IComparer를 구현한 클래스

    /// </summary>

    class CompScale : IComparer<FrameworkElement>

    {

        #region IComparer<FrameworkElement> 멤버

 

        public int Compare(FrameworkElement x, FrameworkElement y)

        {

            return (x.RenderTransform as ScaleTransform).ScaleX.CompareTo((y.RenderTransform as ScaleTransform).ScaleX);

        }

 

        #endregion

    }

}

 

 

FishEyePanel이라는 클래스를 WrapPanel을 상속받아 만들어보았습니다.

 

사용 예제입니다.

 

 

=== xaml

<Window x:Class="PanelTest.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="clr-namespace:PanelTest"

    Title="Window1" Height="300" Width="300">

    <local:FishEyePanel x:Name="LayoutRoot" />

</Window>

 

== 코드비하인드

public Window1()

{

    InitializeComponent();

    this.Loaded += new RoutedEventHandler(Window1_Loaded);

}

 

void Window1_Loaded(object sender, RoutedEventArgs e)

{

    LayoutRoot.MaxArrange = 2.5; // 이건 옵션

    for (int i = 0; i < 400; i++)

    {

        Rectangle rect = new Rectangle();

        rect.Fill = new SolidColorBrush(Color.FromArgb(30, 0, 125, 255));

        rect.Stroke = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));

        rect.Margin = new Thickness(5);

        rect.Width = 50;

        rect.Height = 50;

        LayoutRoot.Children.Add(rect);

    }

}

 

 

실행된 결과는 다음과 같습니다.(동영상을 올리고 싶지만... 귀차니즘으로... 사진으로 대체합니다)

 

 

 

[코멘트] 좋음
2011-01-20 17:53
 redelec  redelec님께 메시지 보내기redelec님을 내 주소록에 추가합니다.redelec님의 개인게시판 가기 
좋은 강좌 감사합니다.
저장 취소
코멘트쓰기
  좋음   놀람   궁금   화남   슬픔   최고   침묵   시무룩   부끄럼   난감
* 코멘트는 500자 이내(띄어쓰기 포함)로 적어주세요.
목록 보기   지금 보고 계시는 글을 회원님의 my Mblog >> 스크랩에 넣어두고 다음에 바로 보실 수 있습니다.  
회사소개  |   개인정보취급방침  |  제휴문의  |   광고문의  |   E-Mail 무단수집거부  |   고객지원  |   이용안내  |   세금계산서
사업자등록번호 안내: 220-81-90008 / 통신판매업신고번호 제 2017-서울구로-0055호 / 대표: 홍영준, 서민호
08390, 서울시 구로구 디지털로32길 30, 1211호 / TEL. 02_6719_6200 / FAX. 02-6499-1910
Copyright ⓒ (주) 데브피아. All rights reserved.