티스토리 툴바




Microsoft MVP 행사때 들었던 ASP.NET MVC 관련 세션...
이때만해도 Microsoft ASP.NET MVC에는 큰 관심을 갖고 있지 않았다. 3년이 지난 지금 내가 ASP.NET MVC를 개발
하리라곤 생각지도 못했다

그저 새로운 주제라서 세션을 들었을 뿐이었다. MVC 개념은 이미 나온지 한참 되었지만 Microsoft에서 ASP.NET에
MVC 패턴을 도입한 것은 오래 되지 않았다.

꾸준하게 몇 번의 버전업이 되고 현재는 ASP.NET MVC 3까지 나온상태이다. Visual Studio 2010에 추가해서 개발할
수 있도록 되어 있다.

이럴줄 알았으면 ASP.NET MVC가 발표되고 몇 해가 지났는데 진즉에 관심이라도 갖고 있었으면 좋았거늘... 다소 늦은
감이 있다.







ASP.NET MVC 세션을 진행했던 왼쪽부터 Phil Haack, Scott Hanselman 이다.
시간이 갈수록 개발 패러다임도 계속 바뀌는 것 같고 그 속도에 발을 맞추기 못하는 것 같다. 아무래도 개발자로서의 역량이나
열정등이 많이 떨어졌다.

디자인과 코드의 완벽한 분리 그리고 즉 예전부터 강조되었던 코드의 재사용성과 블럭(객체, 모듈, 비지니스 서비스, 도메인 등....)의
느슨한 결합을 통한 유연성 있는 개발을 할 수 있는 구조로 계속 변해 가는 것 같다.












ASP.NET 의 아버지? Scott Guthrie 이분은 정말 Microsoft에서 없어서는 안될 핵심중의 핵심이라 할 수 있다.
이때만해도 Silverlight와 WPF에 가장 큰 관심이 있었던지라 다른 분야는 생각하지 않았다.
2008년도만 해도 Silverlight는 떠오르는 기술중에 하나였다. 현재는 Silverlight 4가 나와 있는 상태고 Silverlight 5도
얼마전부터 이야기가 나오기 시작했다.

그런데 Silverlight와 WPF는 요즘 Microsoft의 서자(庶子)가 되버린 느낌이 든다.

Microsoft가 하도 많은 기술들을 쏟아 내면서 삽질을 하면서 몇 몇의 기술들은 그대로 사장되버리는 경우가 종종
있었다. Microsoft가 모바일 시장을 개척해 놓고도 거지같은 윈도우 모바일 OS 때문에 소비자들에게 외면을 받으
면서 시장을 애플과 안드로이드 진영에 모두 잠식당한 상태이다. 그런와중에 Silverlight 플랫폼을 핵심으로 하는
새로운 모바일 OS인 Windows Mobile 7 을 최근에 선보였다. 과연 이미 들어와 있는 다른 OS들을 따돌리고 다시 옛날에
잃어버린 시장을 되찾을 수 있을지 앞으로의 모바일 시장에서 관전포인트가 될 것이다.

Windows Mobile 7 을 계기로 Silverlight의 주가를 높일 수 있을지도 크 관심거리이다.






Silverlight에 대해 열정적으로 강의하는 Scott Guthrie














두서 없이 앝은 지식같지 않은 지식으로 이것저것 깨작거렸다.

PS) 시애틀이란 도시는 내게 큰 희망과 충격을 동시에 안겨준 도시이다. 정말 내가 부족한 것이 많다는 것과
앞으로 내가 무엇을 해야 할지 알게 해준 고마운 도시이다.(참고:시애틀의 마지막 여정) 그만큼 애착이
많이 가는 도시이다. 10년동안 꿈꿨고 어렵게 개발자가 되어 길다면 길고 짧다고 생각하면 짧은 시간이었지만
개발자로서의 삶을 살 수 있었다.

앞으로 얼마나 더 이 일을 할지는 모르지만... 그리 길지는 않을 것이라 생각한다. 그래서 더 지금의 시간들이
나에게 한순간 순간마나 소중할 수 밖에 없는 것이다. 이 일이 끝날때쯤 난 다시 시애틀로 발걸음을 향하고 있
을 것이다. 뜨거운 열정을 안겨준 고맙고 소중한 시애틀에서 자전거 세계일주의 시작을 고할것이다.



저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/634 관련글 쓰기

모니터 해상도(Tip)

WPF 2008/09/15 02:56

WPF에서 모니터의 실제 해상도를 가져오는 간단한 프로그램입니다.

사용자 삽입 이미지

xaml code

<Window x:Class="WPFScreen.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="165" Width="300">
    <Grid>
        <Label HorizontalAlignment="Left" Margin="23,30,0,0" VerticalAlignment="Top"
               Width="55" Height="23" Content="Width :"/>
        <Label HorizontalAlignment="Left" Margin="23,0,0,38" VerticalAlignment="Bottom"
               Width="55" Height="23" Content="Height : "/>
        <TextBlock Margin="78,35,137,0" TextWrapping="Wrap" x:Name="txWidth"
                   VerticalAlignment="Top" Height="23" />
        <TextBlock Margin="82,0,133,33" TextWrapping="Wrap" VerticalAlignment="Bottom"
                   Height="23" x:Name="txHeigh" />
    </Grid>
</Window>
 

cs code

using System.Windows;
 
namespace WPFScreen
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
 
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }
 
        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            txWidth.Text = SystemParameters.PrimaryScreenWidth.ToString();
            txHeigh.Text = SystemParameters.PrimaryScreenHeight.ToString();
        }
    }
}
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/186 관련글 쓰기

WPF에서 에어로 글래스를 사용하기 위해서는 DwmExtendFrameIntoclientAero API를 호출해야 합니다.

 참고 : DWM : DeskTop Window Manager

윈도우의 투명색은 다른 여러가지 색으로도 변경이 가능하며 무채색으로도 효과를 줄 수 있습니다. DeskTop Window Manager 사용하기 위해서는 PInvoke(Platform Invoke)를 사용해야 합니다. WPF에 관리되지 않는 코드이기 때문에 Win32의 API를 호출해야 합니다.

using System.Runtime.InteropServices;

네임스페이스에 Win32 API를 호출하기 위한 네임스페이스를 선언합니다.

[DllImport("dwmapi.dll", PreserveSig = false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
 
[DllImport("dwmapi.dll", PreserveSig = false)]
static extern bool DwmIsCompositionEnabled();

C#에서 Win32 Api 호출


xaml code
<Window x:Class="WpfAeroGlass.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="320" Width="480">
    <Grid>
       
    </Grid>
</Window>


AeroGrassHelper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
using System.Runtime.InteropServices;
using System.Windows.Interop;
 
namespace WpfAeroGlass
{
    public class AeroGlassHalper
    {
        public struct MARGINS
        {
            public MARGINS(Thickness t)
            {
                Left = (int)t.Left;
                Right = (int)t.Right;
                Top = (int)t.Top;
                Bottom = (int)t.Bottom;
            }
 
            public int Left;
            public int Right;
            public int Top;
            public int Bottom;
        }
 
        [DllImport("dwmapi.dll", PreserveSig = false)]
        static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
 
        [DllImport("dwmapi.dll", PreserveSig = false)]
        static extern bool DwmIsCompositionEnabled();
 
        public static bool ExtendGlassFrame(Window window, Thickness margin)
        {
            if (!DwmIsCompositionEnabled())
                return false;
 
            IntPtr hwnd = new WindowInteropHelper(window).Handle;
            if(hwnd == IntPtr.Zero)
                throw new InvalidProgramException("The Window must be shown before extending glass.");
 
            window.Background = Brushes.Transparent;
            HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
 
            MARGINS margins = new MARGINS(margin);
            DwmExtendFrameIntoClientArea(hwnd, ref margins);
            return true;
        }
    }
} 

window.Background = Brushes.Transparent;
HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
위의 코드는 WPF와 Win32 모두 투명한 배경으로 설정합니다.

cs code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WpfAeroGlass
{
    ///<summary>
    /// Window1.xaml에 대한 상호 작용 논리
    ///</summary>
    public partial class Window1 : Window
    {
        private bool neverRendered = true;
 
        public Window1()
        {
            InitializeComponent();
 
            this.SourceInitialized += new EventHandler(Window1_SourceInitialized);
        }
 
        void Window1_SourceInitialized(object sender, EventArgs e)
        {
            AeroGlassHalper.ExtendGlassFrame(this, new Thickness(-1));
        }
 
        protected override void OnContentRendered(EventArgs e)
        {
            if (neverRendered)
            {
                SizeToContent = SizeToContent.Manual;
 
                FrameworkElement root = this.Content as FrameworkElement;
 
                if (root != null)
                {
                    root.Width = double.NaN;
                    root.Height = double.NaN;
                }
 
                this.neverRendered = false;
            }
 
            base.OnContentRendered(e);
        }
 
    }
}
 

AeroGlassHalper 클래스의 ExtendGlassFrame메소드는 윈도우의 크기를 확장할때 그 크기에 맞추어 에어로 글래스 효과를 줄지 결정하는 역활을 합니다. 윈도우의 모든 영역을 투명창으로 하려면 -1를 넘겨줍니다. 인수타입은 Thickness 입니다.

오버라이드 된 OnContentRendered 이벤트에서 base.OnContentRendered(e);를 계속 호출하는 것은 윈도우가 랜더링 될때마다 윈도우의 전체영역에서 투명효과를 주기위해서 입니다.

사용자 삽입 이미지



사용자 삽입 이미지


저의 노트북 바탕화면을 실버라이트 심벌로 해놨습니다.^^ 그 위에 WPF 윈도우창이 에어로 글래스 효과를 주어 반투명창 효과가 나타났고 그 뒤에 윈도우의 배경화면이 보입니다.,

참고 사이트 및 도서
http://blogs.msdn.com/adam_nathan/archive/2006/05/04/589686.aspx (에덤네이선의 블로그)
에덤네이선의 WPF 언리쉬드(참고도서)

※ AeroGrassHelper 의 원본코드의 저작권은 에덤네이선(Adam Nathan)에게 있음을 알려드립니다.
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/185 관련글 쓰기

Flash Movie 실행하기

WPF 2008/08/07 03:49

사용자 삽입 이미지
사용자 삽입 이미지
WPF에서 Flash Movie를 재생하는 데모를 만들어보겠습니다. ActiveX 컨트롤 사용하는 방법과 동일하며 AxInterop.ShockwaveFlashObjects.dll 이 필요합니다. dll이 로컬에 존재한다면 참조에 추가하면 되고 없으면 여기에서 다운로드 받으시면 됩니다.


 


AxInterop.ShockwaveFlashObjects.dll이 추가되었습니다.


로컬에 있는 Flash Movie를 가져와 WPF에서 재생을 합니다.


xaml code
<Window x:Class="WPFControlSwf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="400" Width="400">
    <Grid x:Name="grid">
    </Grid>
</Window>

cs code
using System.Windows;
 
using System.Windows.Forms.Integration;
using AxShockwaveFlashObjects;
 
namespace WPFControlSwf
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
 
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }
 
        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
 
            WindowsFormsHost host = new WindowsFormsHost();
 
            AxShockwaveFlash swfPlayer = new AxShockwaveFlash();
            host.Child = swfPlayer;
 
            grid.Children.Add(host);
            swfPlayer.Movie = "c://flash.swf";
            swfPlayer.Play();
        }
    }
}

코드 설명
using AxShockwaveFlashObjects;
Flash 관련 네임스페이스를 선언합니다.

swfPlayer.Movie = "c://flash.swf";
swfPlayer.Play();
Movie프로퍼티는 Flash Movie 경로를 지정하고 Play() 메소드는 WPF 프로그램이 실행될때 Flash Movie를 자동으로 재생하도록 합니다.

Summary  
 전자문서나 전자도서 같은 프로그램에서 모든 콘텐츠를 WPF나 Silverlight로 개발하기에 한계가 있으므로 전자도서의 컨텐츠를 개발했을때 그 컨텐츠를 이용하기 위한 좋은 방법이 될것입니다. 제가 얼마전에 참여했던 디지털 교과서가 그 좋은 예라 할수 있습니다. 그리고 ActiveX로 개발된 컨텐츠라면 그 어떤것도 WPF에서 실행할 수가 있습니다.  

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/184 관련글 쓰기

WPF From 내부안에 긍즉적으로 다른 윈도우가 종속족으로 퐇마될 수 없습니다. 그러나 이를 가능하게 해주는 클래스가 지난 강좌(WPF에서 윈폼 컨트롤 클래스 사용히기)에서 다루었던 ElementClass입니다. Element 클래스를 이용하여 ActiveX를 컨트롤할 수 있는데요


ActiveX 컨트롤 추가하는 방법
1. ActiveX Importer(AXIMP.EXE)를 실행
(이 유틸리티는 윈도우즈 SDK의 닷넷컴퍼넌트에 포함되어 있습니다.)
  
2. Visual Studio에서 윈폼 프로젝트를 만든다음 [도구상자]-[항목선택]을 한다음 [도구상자선택항목]의 [COM 구성요소]템에 있는 ActiveX를 선택하여 도구상자에 추가한다음 이 컨트롤을 윈폼에 마우스로 드레그하여 추가하는 방법(추가하면 윈폼에서 자동으로 실행됩니다.)

이 강좌에서는 2번째 방법을 택하여 ActiveX를 추가해보겠습니다.

사용자 삽입 이미지



윈도우 미디어 플레이어 ActiveX를 추가하였습니다.

사용자 삽입 이미지

드레그 하여 윈폼에 추가합니다. 어쨌든 여기서 필요한 건 AxWMPLib.dll과 WMPLib.dll 이기 때문에 윈폼 프로젝트의 참조된 두개의 dll을 그대로 WPF 프로젝트의 참조에 추가해줍니다.

xaml Code

<Window x:Class="WPFActiveX.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="515" Width="450">
    <Grid x:Name="grid">
        
    </Grid>
</Window>

using System.Windows;
using System.Windows.Controls;
 
using System.Windows.Forms.Integration;
 
namespace WPFActiveX
{
    ///<summary>
    /// Window1.xaml에 대한 상호 작용 논리
    ///</summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
 
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }
 
        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
 
            grid.BeginInit();
 
            grid.Height = 500;
            grid.Width = 480;
 
            RowDefinition row = new RowDefinition();
            row.Height = new GridLength(450);
            grid.RowDefinitions.Add(row);
 
            row = new RowDefinition();
            row.Height = GridLength.Auto;
            grid.RowDefinitions.Add(row);
 
            AxWMPLib.AxWindowsMediaPlayer axWmp = new AxWMPLib.AxWindowsMediaPlayer();
            WindowsFormsHost host = new WindowsFormsHost();
            host.Child = axWmp;            
           
            TextBox txtUrl = new TextBox();
            txtUrl.Text = @"mms://wm.microsoft.com/ms/korea/etc/vs2008_1_Opening.wmv";
 
            string wmpURL = txtUrl.Text.ToString();
 
            grid.Children.Add(host);
            grid.Children.Add(txtUrl);
 
            Grid.SetRow(host, 0);
            Grid.SetRow(txtUrl, 1);
 
            axWmp.uiMode = "mini";
 
            axWmp.URL = wmpURL;
        }
    }
} 

코드설명은 ActiveX 부분만 간단히 설명하겠습니다.
AxWMPLib.AxWindowsMediaPlayer axWmp = new AxWMPLib.AxWindowsMediaPlayer();

위 코드는 윈도우 미디어 플레이어 ActiveX를 사용하기 위해 추가된 dll을 인스턴스 생성하는 부분입니다.

 axWmp.uiMode = "mini";
 
 axWmp.URL = wmpURL;

uiMode 프로퍼티는 윈도우 플레이어가 실행될때 열림상태를 정의 합니다. URL은 스트리밍 되는 동영상의 주소입니다. 로컬 및 온라인에 있는 동영상 모두 재생이 가능합니다.

Summary  
 WPF에서 ActiveX를 컨트롤 할 일은 그렇게 많지 않겠지만 기존에 개발된 ActiveX를 사용해야 한다면 좋은 대안이 될 수 있을 것입니다.

참고 사이트
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/183 관련글 쓰기
WPF에서 윈폼 컨트롤을 사용하기 위해서는 ElementHost라는 클래스를 통해서 윈폼 컨트롤을 WPF에 포함할 수 있습니다. ElementHost 클래스는 HwndSource와 같지만 임의의 HWND보다는 WPF 내부에 윈폼의 컨트롤을 포함시킬 수 있도록 특화도니 클래스입니다.  ElementHost 호스트는 using System.Windows.Controls을 상속받아 윈폼 컨트롤을 WPF 컨텐트(Content) 내부에 어떻게 보여줄지를 결정합니다.

사용자 삽입 이미지

[도구상자]-[항목선택]순으로 메뉴를 열면 [도구상자선택항목] 대화상자에서 ElementHost가 선택되어 있거나 선택하면 [도구상자]에 WindowsFormsHost 컨트롤이 추가된 것을 볼 수 있습니다.




using System.Windows;

using System.Windows.Controls;

 

using System.Windows.Forms.Integration;

 

namespace WPFWindowsFormsHost

{

    /// <summary>

    /// Window1.xaml에 대한 상호 작용 논리

    /// </summary>

    public partial class Window1 : Window

    {

        public Window1()

        {

            InitializeComponent();

 

            // WPF Expander Control 생성

            Expander expander = new Expander();

            expander.Header = "WPF WindowsFormsHost";

 

            // 컨트롤을 생성하고 이를 WindowsFormsHost에 매핑한다.

            WindowsFormsHost host = new WindowsFormsHost();

            host.Child = new System.Windows.Forms.MonthCalendar();

 

            // Expender Content프로퍼티에 WindowsFormsHost 인스턴스 생성

            expander.Content = host;

 

            // Root Element Expender을 추가한다.

            this.Content = expander;

        }

    }

}


네임스페이스에 using System.Windows.Forms.Integration를 추가하면 ElementHost 클래스를 인스턴스 할 수 있습니다. ElementHost 클래스에 있는 Child 프로퍼티는 윈폼의 컨트롤을 포함하게 하여 WPF에서 윈폼컨트롤을 보여지게 할 수있습니다.

Child 프로퍼티에 윈폼의 달력 컨트롤을 인스턴스하여 생성하면 화면에 달력이 보여지게 됩니다.

사용자 삽입 이미지


참고사이트 : http://www.danielmoth.com/Blog/2007/10/wpf-and-windows-forms-integration.html
참고도서 : 애덤 네이선의 WPF 언리쉬드
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/182 관련글 쓰기

News Reader SDK 공개

WPF 2008/01/17 17:26

Introducing the Syndicated Client Experiences Starter Kit & Reader SDK 라는 제목으로 미국마이크로소프트 공식 사이트에 소개되어 있습니다.

URL: http://windowsclient.net/wpf/starter-kits/sce.aspx

NY Times Reader와 Seattle PI Reader 의 원 소스였던, News Reader SDK가 공개되었습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/178 관련글 쓰기
WPF에서 색상을 다루기 위해서는 System.Windows.Media 네임스페이스에 정의된 Color 구조체를 사용합니다. Color 구조체는 빛의 3원색인 빨간색, 녹색, 파란색 3가지를 사용합니다. 이 3원색은 영문의 앞자를 따서 R(Red), G(Green), B(Blue)로 나타냅니다. 또 색상의 투명도를 나타내는 알파 채널을 추가하여 ARGB라고 표현합니다. 약자는 A(Alpha)로 나타내며 값이 0이면 완전한 투명하다는 의미이며 255이면 불투명임을 나타냅니다.
 
3원색을 나타내기 위해서 다음과 같이 코드를 작성합니다. Color 구조체는 인자가 있는 객체와 없는 객체가 모두 존재합니다.

인자 값이 없는 Color 객체 생성


Color color = new Color();
 
color.R = 255;
color.G = 0;
color.B = 0;

 
Color 구조체에서 지원하는 정적 메소드를 있습니다. 이 경우 3개의 인자 값이 필요하며 데이터 타입은 Byte이며 0~255까지 입력 가능합니다.  
 

Color color = Color.FromRgb(0, 255, 255);
 

다음은 알파채널 지정할 수 있는 메소드 사용법입니다. A값 역시 0~255까지 입력 가능하며 데이터타입은 Byte형입니다.


Color color = Color.FromArgb(255, 0, 255, 255);
 

지금까지 설명한 내용은 Color 구조체에 객체를 생성하여 0~255까지의 Byte 값을 인자값으로 직접 대입하는  방법을 사용하는 경우이며 System.Windows.Media에는 Colors란 이름의 클래스도 있는데, 여기에는 알파벳순으로 지정된 읽기 전용의 141개 정적 프로퍼티가 있습니다. 사용법은 다음구문과 같습니다.


Colors color = Colors.YellowGreen;
 
 
마지막으로 가장 중요한 것은 Color 객체는 색을 지정할 경우 직접 대입할 수 없기 때문에, 가장 널리 사용되는 Brush 타입의 객체를 사용합니다.
 
일반적으로 색을 대입할 때 SolidColorBrush 클래스를 이용하여 Window의 background나 각종 Control의 색을 지정할 수 있습니다. 사용방법은 다음구문과 같습니다.
 

1)
Color color = Color.FromRgb(0, 255, 255);
SolidColorBrush brush = new SolidColorBrush(color);
Background = brush;

2)
Background = new SolidColorBrush(Color.FromRgb(0, 255, 255));

3)
SolidColorBrush brush = new SolidColorBrush();
brush.Color = Color. FromRgb(0, 255, 255);
 

다음강좌에는 Gradient를 그릴 때 사용하는 RadialGradientBrush,
LinearGradientBrush 클래스에 대해여 예제를 통해 자세히 알아보겠습니다.

참고서적 : 찰스 페졸트의 WPF
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/177 관련글 쓰기

보통 Application 클래스를 상속받아 윈도우 응용프로그램을 만들 수도 있지만 Window 클래스를 상속받아 윈도우 응용프로그램을 만드는 것도 가능합니다.

 Window 클래스를 상속받아 하나의 파일에서 정의하는 것이 조금 더 일반적이며 더 쉬운 방법이라고 할 수 있습니다.

using System;
using System.Windows;
using System.Windows.Input;
 
namespace Chapter1
{
    class InheritTheWin : Window
    {
        [STAThread]
        public static void Main()
        {
            Application app = new Application();
            app.Run(new InheritTheWin());
        }
 
        public InheritTheWin()
        {
            Title = "Inherit the Win";
        }
    }
}

Main 함수에서 Application 클래스를 인스턴스 하고 Window 클래스를 상속받은 InheritTheWin 클래스를 새로 생성합니다.

Application app = new Application();
app.Run(new InheritTheWin());

위 구문을 더 간단히 할 수 있는 방법이 있습니다. 구문은 다음과 같습니다. Main 함수안에 위의 코드를 주석처리 하고 아래코드를 삽입하면 됩니다.

new Application().Run(new InheritTheWin());

new 키워드를 이용하여 Application 객체를 생성하고 Application 클래스에 들어 있는 Run 메소드 안에 Window 클래스를 상속받은 InheritTheWin 클래스를 생성하여 윈도우를 오픈합니다.

기존에 Application 클래스를 상속 받아서 처리할때보다 코드가 아주 쉽고 간편합니다.

참고서적 : 찰스 페졸트의 WPF
크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/175 관련글 쓰기
사용자 삽입 이미지
윈도우 운영체제에서 창은 화면상에 표시되는 위치와 크기를 갖는데 이를 재지정 할 수 있습니다. 크기(Size) : Width(가로), Height(세로)
 
Window 클래스는 FrameworkElement로부터 Width와 Height 프로퍼티를 상속 받습니다. 따라서 다음처럼 다음과 같이 생성자에서 이 프로퍼티의 값을 재정의 할 수 있습니다.

사용자 삽입 이미지

 
Width와 Height는 초기에는 정의돼 있지 않으며 프로그램에서 따로 정의하지 않는 한 계속 이런 상태로 남습니다. 따라서 이를 달리 표현하면 NaN(숫자가 아님:not a number)값을 갖게 합니다.
 
창의 실제 크기를 얻기 위해서는 Width와 Height 프로퍼티를 사용해서는 안 되며 ActualWdith, ActualHeight 프로퍼티를 사용해야 합니다. 초기에는 값이 0이며 창이 화면에 표시된 후에 실제 값을 갖게 됩니다.
 
WPF에서는 모든 크기나 위치를 지정할 때 장치 독립적 픽셀(device-independent pixels) 또는 논리 픽셀(logical pixels)이라고 하는 단위를 사용합니다. 이 단위는 1/96인치이며, 예를 들어서 Width가 288이고 Height가 192의 값을 갖는다면 실제로 창의 가로가 3인치이고 세로가 2인치임을 의미합니다. 이는 모든 컴퓨터의 설정에 따라 차이가 있을 수 있으며 사용자가 윈도우의 설정을 변경이 변경 가능하기 때문입니다.
 
모니터의 설정에서 기본값으로 96DPI(인치당 도트 수, dots per inch)로 설정돼 있으며 그런 경우 Width와 Height는 각각 288과 192가 그대로 픽셀 값과 일치 합니다. 그러나 120DPI로 설정이 변경한다면 Width와 Height 프로퍼티가 288, 192인 경우에 실제 픽셀 수가 360과 240이 되는 것입니다. 픽셀이 아닌 실제 창의 크기는 변함이 없습니다. 미래의 모니터는 지금보다 더 높은 해상도를 표시하므로 DPI의 수치는 높을 것이고 따라서 창의 실제 크기는 동일하게 변함이 없을 것입니다.
 
 
 
Width와 Height의 값을 매우 작은 값을 넣어 시험해보면 다음그림처럼 창의 제목표시줄은 항상 특정 크기보다 작아지지 않는다는 사실을 발견할 수 있습니다.

 
사용자 삽입 이미지
 
이런 창의 크기는 정적 읽기 프로퍼티인 SystemParameters.MinimizedWindowHeight와 SystemParameters.MinimizedWindowWidth에 저장돼 있습니다. SystemParameters 클래스에는 이 같은 몇가지 정적 프로퍼티가 있습니다.
 
화면의 위치를 결정짓는 값은 Left와 Top에 들어 있으며, 프로그램에서 이 프로퍼티를 변경하지 않으면 NaN의 값이 유지됩니다. 윈도우의 해상도에 대한 값은 정적 프로퍼티인 SystemParameters.PrimaryScreenWidth와 SystemParameters.PrimaryScreenHeight의 값을 통해 알 수 있습니다. DPI값에 따라 각각 값이 변경될 수 있습니다.
 
SystemParameterssms는 모두 크기를 장치 독립적 단위로 표현하지만 유일하게 SystemParameterssms의 프로퍼티중 SmallIconWidth와 SmallIconHeight는 픽셀 단위입니다. 대부분의 값들은 별다른 변환 없이 바로 사용할 수 있으며, 예를 들어 창을 화면의 우측하단 영역에 위치시키기 위해 다음과 같이 할 수 있습니다.

SystemParameters.PrimaryScreenWidth - Width;
Top = SystemParameters.PrimaryScreenHeight - Height;

윈도우 영역의 작업표시줄을 감안한다면 코드는 다음과 같습니다. SystemParameters.WorkArea 프로퍼티는 Rect 타입의 객체를 반환합니다. 이 타입은 왼쪽 상단의 위치와 크기로써 사각형을 정의하는 구조체입니다.

Left = SystemParameters.WorkArea.Width - Width;
Height = SystemParameters.WorkArea.Height - Height;

WorkArea를 감안하여 화면의 중앙에 창을 위치코자 한다면 코드는 다음과 같습니다.

Left = (SystemParameters.WorkArea.Width - Width) / 2 +
SystemParameters.WorkArea.Left;
Height = (SystemParameters.WorkArea.Height - Height) / 2 +
      SystemParameters.WorkArea.Top;

이 코드를 Window 클래스에 정의된 WindowStartupLocation 프로퍼티를 사용해 바꿀 수 있습니다.

사용자 삽입 이미지

WindowStartupLocation 열거형의 멤버를 이 프로퍼티에 대입합니다. 기본값은
WindowStartupLocation.Manual로, 프로그램이나 윈도우 운영체제에서 수동으로 창의 위치를 지정합니다. WindowStartupLocation.CenterScreen으로 지정하면 창을 화면의 중앙에 위치킵니다. 세 번째로 WindowStartupLocation.CenterOwner가 있는데 모달 대화상자를 그 소유자의 중앙에 위치시킵니다.

 

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/176 관련글 쓰기
윈도우용 데스크톱 프로그램은 한 번에 여러 개의 창을 띄울 수 있다는 것을 여러분은 익히 알고 있을 것입니다. 그 중 특정 윈도우를 닫으면 현재 열려있는 윈도우가 닫히고 최종적으로 프로그램이 완전히 종료하게 됩니다. 여러 개의 윈도우중 그 어느 윈도우를 닫더라도 현재 실행중인 프로그램이 종료된다면 프로그램의 성능상에 심각한 문제가 발생 할 수 있습니다. 또 프로그램에는 반드시 메인 윈도우가 존재해야 하며 서브 윈도우를 제어할 수 있어야 합니다.
using System;
using System.Windows;
using System.Windows.Input;
 
namespace Chapter1
{
    class ThrowWindowParty : Application
    {
        [STAThread]
        public static void Main()
        {
            ThrowWindowParty app = new ThrowWindowParty();
            app.Run();
        }
 
        protected override void OnStartup(StartupEventArgs e)
        {
            Window winMain = new Window();
            winMain.Title = "Main Window";
            winMain.MouseDown += new MouseButtonEventHandler(winMain_MouseDown);
            winMain.Show();
 
            for (int i = 0; i < 2; i++)
            {
                Window win = new Window();
                win.Owner = winMain;
                win.Title = "Extra Window No." + (i + 1);
                win.Show();
            }
        }
}
}

위 프로그램에서 첫 번째 중요한 사실은 OnStartup() 이벤트에서 생성된 3개의 창은 이 응용프로그램에서 모두 동등하다는 것입니다. 그 어떤 윈도우라도 클릭하게 되면 선택된 윈도우는 가장 앞에 자리하게 됩니다. 어떤 순서로도 닫을 수 있으며 가장 마지막에 윈도우가 닫히면 프로그램은 종료됩니다.

 그러나 여기서 간과할 수 없는 것은 Application 객체의 MainWindow 프로퍼티를 살펴보면, Show가 호출되는 첫 창이 그 응용프로그램에서 메인 윈도우로 간주되는 것을 알 수 있습니다.

 프로그램을 실행시켜 보면 윈도우 작업 표시줄에 3개의 윈도우가 모두 표시되 있는 것을 확인할 수 있습니다.

사용자 삽입 이미지

for 루프 안에 다음 구문을 삽입하면 "Main Window" 란 제목을 가진 윈도우만 남게 됩니다.

for (int i = 0; i < 2; i++)
{
Window win = new Window();
    win.Owner = winMain;
    win.Title = "Extra Window No." + (i + 1);
    win.ShowInTaskbar = false;
    win.Show();
}

그러나 이 같은 경우 "Main Window" 윈도우를 닫을 경우 윈도우 작업표시줄에 있던 항목은 사라지지만 여전히 응용 프로그램은 계속 실행중 입니다. 물론 2개의 다른 창도 그대로 프로세스에 남아있겠지요 ~~~

 일반적으로 윈도우 프로그램은 Run 메소드가 반환될 때 프로그램이 종료되는데, 마지막 윈도우를 닫을 경우 Run메소드가 반환됩니다. 만약 메인윈도우가 지정되고 이 윈도우가 닫힐 경우만 프로르램이 종료되도록 설정하고 싶다면 Application 클래스의 ShotdownMode 프로퍼티를 OnMainWindowClose로 설정하면 됩니다. (기본값은 OnLastWindowClose 입니다)

ShutdownMode
프로퍼티


ShutdownMode

OnLastWindowClose

마지막 윈도우가 닫힐 경우

OnMainWindowClose

메인 윈도우를 닫을 경우

OnExplicitShutdown

Shutdown 메소드를 명시적으로 호출할 경우

 윈도우 응용프로그램의 시작점인 Main() 메소드에서 상속받은 Application 클래스안에 있는 ShutdownMode 프로퍼티를 사용하면 됩니다. 여기서 중요한 것은 Run메소드가 실행되기 전에 ShutdownMode 프로퍼티가 설정되어야 합니다.

[STAThread]
public static void Main()
{
ThrowWindowParty app = new ThrowWindowParty();
    app.ShutdownMode = ShutdownMode.OnMainWindowClose;
    app.Run();
}

반면 재정의(override) OnStartup 이벤트 안에서는 this 키워드만 붙이면 이벤트 안의 어느곳이든 ShutdownMode 프로퍼티 설정이 가능합니다. (this 키워드는 생략할 수 있으므로 그냥 프로퍼티 이름만 적어도 됩니다.)

protected override void OnStartup(StartupEventArgs e)
{
     Window winMain = new Window();
     winMain.Title = "Main Window";
     winMain.MouseDown += new MouseButtonEventHandler(winMain_MouseDown);
     // this.ShutdownMode = ShutdownMode.OnMainWindowClose;
     ShutdownMode = ShutdownMode.OnMainWindowClose;
     winMain.Show();
 
    ……… 생략
 }

이제 메인 윈도우가 닫힐 때만 Run 메소드가 반환되고 프로그램이 종료됩니다. 마지막으로 메인윈도우를 지정하는 구분을 알아보면 다음과 같습니다. 다음 구문을 OnStartup 이벤트의for 루프 안에 추가합니다.

MainWindow = win;

마지막으로 지금까지 추가된 모든 구문을 제거하고 여러 윈도우들에 대한 계층 구조를 만드는 또 다른 방법을 알아보겠습니다. For 루프 안에 다음 구문을 추가합니다. Window 클래스에 정의된 Owner 프로퍼티를 이용하여 메인으로 지정할 윈도우를 지정하는 합니다. Owner은 소유자라는 뜻으로 기본값은 null 이며 나머지 윈도우를 소유하고 제어할 수 있습니다. 소유자 윈도우를 최소화하면 모든 윈도우가 화면에서 사라지고 소유자 윈도우를 닫으면 나머지 모든 윈도우도 자동으로 닫히게 됩니다.

Win.Owner = winMain;

 참고서적 : 찰스 페졸트의 WPF

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/174 관련글 쓰기

WPF 이벤트 안에서 현재의 윈도우 객체 구하기

※ 코드예제는 찰스 페졸트의 WPF에서 참고하였습니다.

using system;
using system.windows;
using system.windows.input;
 
namespace chapter1
{
    class handleanevent
    {
        [stathread]
        static void main()
        {
            application app = new application();
 
            window win = new window();
            win.title = "handle an event";
            win.mousedown += new mousebuttoneventhandler(win_mousedown);
 
            app.run(win);
        }
 
        static void win_mousedown(object sender, mousebuttoneventargs args)
        {
            // window win = sender as window;
 
            // application 클래스의 특정 프로퍼티를 사용
            // application에는 current란 정적 프로퍼티가 있는데, 이 프로퍼티는
            // 프로그램이 생성한 application 클래스를 반환한다.
            // 또한 application은 window 객체를 반환하는 mainwindow란 이름의 인스턴스 프로퍼티를 갖고 있다.
            // 따라서 이벤트 핸들러에서 다음과 같은 방법으로 window 타입의 지역 변수를 할당할 수 있다.
            window win = application.current.mainwindow;
            string strmessage =
                string.format("window clicked with {0} button at point ({1})",
                    args.changedbutton, args.getposition(win));
            messagebox.show(strmessage, win.title);
        }
    }
}

이벤트의 얻은 현재의 윈도우 object의 값 sender을 변환하는 방법도 있으나 동일한 Window 객체를 이벤트 핸들러 안에서 구하는 방법도 있습니다.

object
값의 senderWindow로 변환하는 방법

Static void win_mousedown(object sender, mousebuttoneventargs args)
{
    window win = sender as window;
}

Main에서 생성된 Window 객체는 정적 필드로 저장돼, 이벤트 핸들러에서 이를 사용할 수 있습니다.

동일한 Window 객체를 이벤트 핸들러 안에서 구하는 방법

Static void win_mousedown(object sender, mousebuttoneventargs args)
{
window win = application.current.mainwindow;
}

Application 클래스의 특정 프로퍼티를 사용해도 되는데 Application에는 Current란 정적 프로퍼티가 있는데, 프로퍼티는 프로그램이 생성한 Application 클래스를 반환합니다. 또한 Application Window 객체를 반환하는 MainWindow란 이름의 인스턴스 프로퍼티를 갖고 있습니다. 따라서 이벤트 핸들러에서 위와 같은 방법으로 Window 타입의 지역 변수를 할당할 수 있습니다.

이벤트 안에서 현재의 윈도우 객체를 얻을 때 아주 유용한 코드입니다.

※참고
프로퍼티 : 오브젝트가 가지고 있는 속성


참고서적 : 찰스 페졸트의 WPF

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/173 관련글 쓰기

WPF 응용 프로그램에서 Application 클래스의 이벤트들을 처리할 필요가 있다면 해당하는 이벤트에 대한 이벤트 핸들러를 설치해야 하지만, 가장 편리한 방법은 Application 클래스를 상속하는 클래스를 정의하는 방법입니다.

using System;

// Application 클래스를 포함하는 Namespace 선언
using System.Windows;
using System.Windows.Input;
 
namespace Chapter1
{
    // Application 클래스 상속
    class InheritApp : Application
    {
        [STAThread]
        public static void Main()
        {
InheritApp app = new InheritApp ();
            app.Run();
        }
 
        // Application을 상속받은 클래스에서는 발생된 이벤트를
        // 처리하는 기본 메소드들을
오버라이딩 할 수 있다.
        protected override void OnStartup(StartupEventArgs e)
        {
            // 처리 루틴
        }
 
        protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
        {
            // 처리 루틴
        }
    }
}

 

크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/172 관련글 쓰기

클래스 계층 구조

WPF 2007/12/12 17:07
WPF의 모든 클래스는 Object 로부터 상속을 받으며 Application이 실행되면 onStartup() 이벤트가 override되어 프로그램이 시작됩니다. 실제 우리 눈에 보이는 Window 클래스까지 여러단계를 거쳐... Window에 여러 Control을 표시합니다.

WPF 공부를 하시는 모든분들은 위 그림의 계층구조를 계속해서 접하시게 될겁니다. 하나하나 구조를 파악하면서 프로그래밍을 하다보면 WPF 클래스의 계층간 관계나 구조를 자연스럽게 파악하실 수 있을것입니다. 1년전에는 기본 컨트롤 위주로 Markup Language 즉 XAML을 가지고 강좌를 진행했습니다.

조만간에 진행될 WPF 강좌는 XAML과 실제 동적으로 C#코드로도 구현하는 방법을 통하여 WPF 프로그래밍을 하는 방법을 강좌로 통하여 진행해 보도록 하겠습니다.

사용자 삽입 이미지
크리에이티브 커먼즈 라이선스
Creative Commons License

'WPF' 카테고리의 다른 글

Application의 window 제어하기  (0) 2007/12/21
이벤트 안에서 현재의 윈도우 객체 구하기  (0) 2007/12/14
응용프로그램 Application 클래스 이벤트 처리  (0) 2007/12/13
클래스 계층 구조  (0) 2007/12/12
[XPS] Fxied Documents  (0) 2007/08/10
[XPS] View and Generate XPS  (0) 2007/08/10
[Controls] 25. BulletDecorator  (0) 2007/08/10
[3D] STARWARS NABOO  (0) 2007/07/09
http://www.taedi.kr/trackback/171 관련글 쓰기

국내에 개인적으로 WPF에 대해 공부하셨던 분들에게 희소식이 나왔습니다. 국내에는 커뮤니티와 관련 블로그외에 거의 참고할 만한게 전무했습니다 해외 원서만 하더라도 저처럼 영어에 대한 압박때문에 엄두를 내지 못했던 분들이 많았던 것도 사실입니다. 이런 와중에 국내에서 제대로 된 번역서가 출간된다는 소식은 정말 희소식이 아닐수 없습니다. 무척이나 기뻐할 일이구요...

사용자 삽입 이미지
 


찰스 페졸드의 WPF: C#과 XAML을 이용한 .NET 3.0 윈도우 프로그래밍

찰스 페졸드 지음 | 최세영 황상철 김인기 신희철 옮김 | 1304페이지 |
하드커버 양장 | 2007년 10월 1일 출간 | 50,000원





단... 책이 너무 두꺼워서... 버거우나 생활에서 다용도(?)로 활용하기엔 제격입니다. ^^

책에 대한 자세한 소개는 아래의 블로그 주소를 참고하세요

http://www.acornpub.co.kr/blog/152


크리에이티브 커먼즈 라이선스
Creative Commons License
http://www.taedi.kr/trackback/170 관련글 쓰기