2012.06.03 22:05

메인 클래스의 combo box 를 socket 쓰레드에서 받은 메시지들로 채워 주려고 하였다. 

하지만 WPF 에서는 각 UI가 전부 스레드로 동작 된다. 스레드간의 변수 공유는 WPF 에서 기본적으로 막아 놨기 때문에 다른 방법을 써서 이 둘을 이어 줘야 한다. 


우선 singletonepattern 방식을 이용하여 하나의 클래스를 다시 생성해주고, 그 클래스에 combobox 형태의 객체를 static 으로 선언해 주자. 


Singletone.cs

 using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Controls;



static class Singletone

{


    public static ComboBox combo; 

}



이후 메인 클래스 에서는 이 combo 라는 변수에 comboBox 를 대입해 준다. 


 Singletone.combo = combo_query; 



이렇게 대입해 준뒤, 외부 스레드(여기서는 소켓 스레드) 의 코드는 dispacher 라는 방법으로 이어준다.



      Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate

     {

          Singletone.combo.Items.Add(msg);

      }));

Dispatcher.Invoke 는 비동기식으로 변수를 사용 하겠다는 선언 같은 것이다. 

이 Dispatcher.Invoke 는 Window 클래스를 상속 받고 있어야 한다. 


소켓 클래스 구현부는 다음과 같다.


 

    public class ServerSock : Window

    {

        public void ServerRun()

        {

            //  IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];

            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");



            Console.WriteLine("ipAddress" + ipAddress);

            TcpListener tcp_Listener = new TcpListener(ipAddress, 5555);

            tcp_Listener.Start();

            while (true)

            {

                Console.WriteLine("1. EchoServer 대기상태.......");


                TcpClient client = tcp_Listener.AcceptTcpClient();      //클라이언트와 접속

                Console.WriteLine("2. Echo Client 접속....");


                NetworkStream ns = client.GetStream();

                StreamReader reader = new StreamReader(ns);

                string msg = reader.ReadLine();                     //메시지를 읽어 옴


                Console.WriteLine("3. [클라이언트 메시지]:" + msg);     //메시지 출력


                reader.Close();

                client.Close();




                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate

                {

                    Singletone.combo.Items.Add(msg);

                }));


            }


        }

    }





Posted by k1rha
2012.06.03 18:09

[출처 : http://blog.naver.com/mankeys?Redirect=Log&logNo=138953202 ]


1. TCP Server


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

using System.Net;

using System.Net.Sockets;


namespace ConsoleApplication_TCPEcho01

{

    class TCP_Server

    {

        static void Main(string[] args)

        {

                IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];

                Console.WriteLine("ipAddress"+ipAddress);

                TcpListener tcp_Listener = new TcpListener(ipAddress, 5555);

                tcp_Listener.Start();

                while (true)

                {

                    Console.WriteLine("1. EchoServer 대기상태.......");


                    TcpClient client = tcp_Listener.AcceptTcpClient();      //클라이언트와 접속

                    Console.WriteLine("2. Echo Client 접속....");

                    

                    NetworkStream ns = client.GetStream();

                    StreamReader reader = new StreamReader(ns);

                    string msg = reader.ReadLine();                     //메시지를 읽어 옴

                    

                    Console.WriteLine("3. [클라이언트 메시지]:" + msg);     //메시지 출력

                    

                    StreamWriter writer = new StreamWriter(ns);

                    writer.WriteLine(msg);                              //네트워크 스트림에 쓰는 듯 함

                    writer.Flush();


                    Console.WriteLine("4. [Echo1]:" + msg);

                    writer.WriteLine(msg);

                    writer.Flush();

                    

                    Console.WriteLine("5. [Echo2]:" + msg);

                    Console.WriteLine("6. 스트림과 TcpClient Close");

                    

                    writer.Close();

                    reader.Close();

                    client.Close();


                }

        }

    }

}


2. TCP Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace ConsoleApplication_TCPEcho01
{
    public class TCP_Client
    {
        public static void Main(string[] arg)
        {
            string args0 = "localhost";     //ip
            string args1 = "5555";          //포트 번호
            string args2 = "안녕";            //메시지

            TcpClient client = new TcpClient(args0, Int32.Parse(args1));    // (ip주소 , 포트 번호)
            NetworkStream ns = client.GetStream();
            StreamWriter writer = new StreamWriter(ns);

            writer.WriteLine(args2);
            writer.Flush();
            Console.WriteLine(args2 + "를 전송합니다. ");

            StreamReader reader = new StreamReader(ns);

            string msg1 = reader.ReadLine();                //네트워크에서 스트림을 읽음
            Console.WriteLine("[Echo1]: " + msg1);
            string msg2 = reader.ReadLine();
            Console.WriteLine("[Echo2]: " + msg2);
            
            writer.Close();
            reader.Close();
            client.Close();

            Console.ReadLine();

        }// Main


    }// class

Posted by k1rha
2012.06.03 18:09

소켓 통신을 할때 서버부분을 Thread 로 따로 돌려주고 메인클래스는 따로 돌리고 싶은 경우에 C# 에서는 thread 를 아주 간단하게 구현하고 메소드를 넣고 실행 할수 있다. 


Thread thrServer;


를 선언해주고, 

            

thrServer = new Thread(new ThreadStart(ServerClass.ServerRun)); //ServerClass.ServerRun 메소드 이다. 

thrServer.IsBackground = true;  //프로그램이 정상적으로 종료될 수 있다.

 thrServer.Start();



아주 간단한 방법..

            

Posted by k1rha
2012.06.03 11:40

WPF로 프로젝트를 하다가 안드로이드의 fill_parents 처럼 화면을 가득 체우게 하는 효과를 주고 싶은 일이 생겼다.


너무 안드로이드에 익숙 한 탓이 였을까? height 와 width 의 값으로 주려고 하거나 코드단에서 처리해야 하는 경우만 생각 했는데, 역시 UI 왕 WPF는 이런 문제를 전체 화면 모드로 제공 해주고 있었다. 




WindowState="Maximized" 로 인하여 전체 화면을 줄수 있고 minimized 도 가능하다. 

hrizontalAlignment 와 verticalAlignment 로 초기 위치를 상위 탑으로 잡아 줄 수도 있다. 



Posted by k1rha
2012.05.28 14:11

WPF 투명 airo 효과 주기를 위해 opacity를 설정해 주었지만 배경이 그냥 까만색으로 바뀌기만 한다. 

이는 배경과 융화될수 있는 AllowsTransparency 설정이 필요하기 때문이다.

또한 windowStyle 이 none 인 상태만 투명한 효과를 가진다.


어찌나 삽질을 했던지.. 


아래와같이 추가해 주면 된다. 



<Window x:Class="PictureViewer.ExplorerWindow"

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

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

    xmlns:panels3D="clr-namespace:Visual3DControls;assembly=Visual3DControls" 

    xmlns:pres="clr-namespace:Microsoft.WindowsAPICodePack.Controls.WindowsPresentationFoundation;assembly=Microsoft.WindowsAPICodePack.Shell"

  Title="ExplorerWindow" Height="400" Width="850"

        Background="Black"

        WindowStyle="None"

        AllowsTransparency="True"

        Opacity="0.5"

        Name="aaaa"

        

        >

Posted by k1rha
2012.05.28 12:33

우선 WPF 참조에서 microsoft_presentation 을 추가해 줘야 한다.

이후 아래와 같은 코드.. 


 

namespace PPT_test

{

    /// <summary>

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

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            OpenFileDialog open = new OpenFileDialog();


           

            open.InitialDirectory=@"C:\";

            open.Title = "불러올 PPT를 선택해 주세요";

       //     open.Filter="All FILE(*.*)|*.*;

            open.RestoreDirectory = true;

            

     

            open.ShowDialog();

           

     

            if (open.FileName=="")

            {

                Debug.WriteLine("File error");

                return;


            }

            else

            {

               

               chkFolder("C:\\FRESENTATION");



               Microsoft.Office.Interop.PowerPoint.Application app = new Microsoft.Office.Interop.PowerPoint.Application();

               try

               {

                   Presentation ppt = app.Presentations.Open(open.FileName, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse);

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

                   {

                       ppt.Slides[i + 1].Export(@"C:\FRESENTATION\" + i + ".png", "PNG", (int)ppt.Slides[i + 1].Master.Width, (int)ppt.Slides[i + 1].Master.Height);

                   }

                   ppt.Close();

                   app.Quit();

               }

               catch (Exception e)

               {

                   Debug.WriteLine(e);

               }


         

            InitializeComponent();

            }

        }                


//폴더여부를 체크하는 부분 

        private void chkFolder(string sPath)

        {

            DirectoryInfo di = new DirectoryInfo(sPath);

            if (di.Exists == false)

            {

                di.Create();

            }

        }


  

    }




Posted by k1rha
2012.05.06 02:21

Main 에 있는 RadioButton 은 모드 하나의 속성으로 묵여서 전체중에 한개밖에 선택을 할 수 없다.

만약 특정 그룹에서 라디오 속성을 먹이고 싶다면 그룹 이름을 같이 설정만 해주면된다. 


예제 코드는 아래와 같다. 



<StackPanel>

    <GroupBox Header = "Select Your Music Media" BorderBrush ="Black">

        <StackPanel>

            <RadioButton GroupName = "Music" >CD Player</RadioButton>

            <RadioButton GroupName = "Music" >MP3 Player</RadioButton>

            <RadioButton GroupName = "Music" >8-Track</RadioButton>

        </StackPanel>

    </GroupBox>

    <GroupBox BorderBrush ="Black">

        <GroupBox.Header>

            <Label Background = "Blue" Foreground = "White"

                FontSize = "15" Content = "Select your color choice"/>

        </GroupBox.Header>

        <StackPanel>

            <RadioButton>Red</RadioButton>

            <RadioButton>Green</RadioButton>

            <RadioButton>Blue</RadioButton>

        </StackPanel>

    </GroupBox>

</StackPanel>





Posted by k1rha
2012.05.06 02:06

[출처 : http://hoons.kr/Lecture/LectureMain.aspx?BoardIdx=45143&kind=54&view=0 ]

이번껀 너무 그대로 퍼와서.. 그냥 개인 소장용으로 퍼왔고 악의는 없다. 좀더 자세한 내용은 위에 출처를 참조..


이벤트 라우팅의 이해


WPF는 기존의 닷넷 프로그래밍 모델을 그대로 물려받아 사용하고 있다. 그 중에서 CLR의 이벤트 모델에 대한 정교한 동작들 또한 XAML의 객체 트리에서 비슷하게 동작되는 것을 볼 수 있다. 그럼 WPFControlEvents라는 새로운 WPF 프로젝트를 생성하여 이벤트 동작에 대해서 자세하게 살펴보도록 하자. WPF 프로젝트를 생성하였다면 처음에 생성된 <Grid> 개체 안으로 다음과 같은 버튼을 삽입하여 보도록 하자.



 <Button Name="btnClickMe" Height="75" Width = "250" Click ="btnClickMe_Clicked">

    <StackPanel Orientation ="Horizontal">

    <Label Height="50" FontSize ="20">Fancy Button!</Label>

    <Canvas Height ="50" Width ="100" >

        <Ellipse Name = "outerEllipse" Fill ="Green" Height ="25"

            Width ="50" Cursor="Hand" Canvas.Left="25" Canvas.Top="12"/>

        <Ellipse Name = "innerEllipse" Fill ="Yellow" Height = "15" Width ="36"

        Canvas.Top="17" Canvas.Left="32"/>

    </Canvas>

</StackPanel>

</Button>


여기서 <Button> 태그를 열어 Click 이벤트를 지정해 주었고 버튼이 클릭될 때 지정한 메서드가 호출될 것이다. Click 이벤트는 RoutedEventHandler 델리게이트를 기반으로 동작되기 때문에 첫 번째 파라메터로 Object를 두 번째 파라메터로 System.Windows.RoutedEventArgs 파라메터를 전달하게 된다. 


 public void btnClickMe_Clicked(object sender, RoutedEventArgs e)

{

    // 버튼이 클릭되었을 때의 동작

    MessageBox.Show("Clicked the button");

}


다음 [그림29-4]는 현재 컨트롤을 클릭했을 때의 동작을 보여주고 있다. (다음과 같이 버튼이 정렬되는 이유는 필자는 처음에 생성된 <Grid>를 <StackPanel>로 변경하고 실행했기 때문이다.)


그럼 버튼의 구조에 대해서 살펴보도록 하자. 버튼은 UI를 표현하기 위한 여러 개의 자식 엘리먼트들을 가지고 있다. 만약 WPF가 이러한 자식 엘리먼트들에 각각의 Click 이벤트를 지정해주어야 한다고 생각한다면 굉장히 당황스러울 것이다. 결국 사용자는 버튼의 어느 영역이라도 클릭만 한다면 클릭이벤트를 발생시킬 수 있는 것이다. 뿐만 아니라 이벤트들이 분리되어 있다고 생각해보면 그 코드는 상당히 더러워질 것이다. 


윈도우 폼에서 버튼을 가지고 커스텀 컨트롤을 만든다고 한다면 버튼에 추가된 모든 항목별로 Click 이벤트를 추가해주어야 한다. 하지만 WPF는 다행스럽게도 자동적으로 이벤트를 라우팅 시켜주게 된다. 즉, WPF의 이벤트 라우팅 모델은 자동으로 이벤트를 상위 객체로 라우팅 시켜주는 것이다. 


특히 이벤트 라우팅은 세 가지 분야로 분리하여 정리할 수 있다. 첫 번째로 이벤트가 발생했을 때 현재개체에서 상위로 올라가면서 이벤트가 전달되는 경우를 우리는 버블링 이벤트라고 한다. 이와 반대로 이벤트가 자식 개체로 전달되는 경우를 터너링 이벤트라고 한다. 마지막으로 이벤트가 단 하나의 개체에서만 발생하게 된다면 우리는 이것을 다이렉트 이벤트라고 한다.


의존성 속성처럼 이벤트 라우팅은 WPF 구조를 위해서 생성된 타입이라고 보면 된다. 그렇기 때문에 C# 문법을 공부할 필요는 없다.



이벤트 버블링의 역할


앞에서 살펴본 예제에서 만약 사용자가 노란 타원을 클릭했을 때 Click 이벤트는 상위 계층 <Canvas>로 이벤트가 전달되고 그 다음에는 <StackPanel>으로 이벤트가 전달되고 마지막으로 버튼으로 그 벤트가 전달되는 것이다. 이와 비슷하게 만약 Label이 클릭하게 되었다면 그 이벤트는 <StackPanel>로 그리고 버튼으로 이벤트가 전달될 것이다.


이벤트 라우팅을 살펴보았듯이 우리는 Click 이벤트를 다루기 위해서 모든 개체에 이벤트를 각각 넣어주는 수고는 걱정하지 않아도 되는 것이다. 하지만 만약 이러한 클릭 이벤트를 원하는 대로 수정하여 사용하고 싶은 경우가 있을 것이다. 이 경우 또한 우리가 그렇게 수정하는 것이 가능하다. 먼저 outerEllipse이란 컨트롤을 클릭했을 때만 이벤트를 발생시키고 싶다고 가정하자. 먼저 이 객체에 MouseDown 이벤트를 설정해 두도록 하자. 참고로 그래픽 개체들은 Click 이벤트를 지원하지 않고 있지만 MouseDown, MouseUp 이벤트를 이용해서 버튼과 같은 Click 이벤트를 구현할 수 있다.


<Button Name="btnClickMe" Height="75" Width = "250" Click ="btnClickMe_Clicked">

    <StackPanel Orientation ="Horizontal">

    <Label Height="50" FontSize ="20">Fancy Button!</Label>

    <Canvas Height ="50" Width ="100" >

        <Ellipse Name = "outerEllipse" Fill ="Green"

            Height ="25" MouseDown ="outerEllipse_MouseDown"

            Width ="50" Cursor="Hand" Canvas.Left="25" Canvas.Top="12"/>

        <Ellipse Name = "innerEllipse" Fill ="Yellow" Height = "15" Width ="36"

            Canvas.Top="17" Canvas.Left="32"/>

    </Canvas>

    </StackPanel>

</Button> 


그리고 나서 각각의 이벤트 메서드에서는 제목 표시줄의 제목을 간단하게 변경하는 로직을 작성해 보도록 하자.


 public void outerEllipse_MouseDown(object sender, RoutedEventArgs e)

{

    // Window의 제목 변경 이벤트

    this.Title = "You clicked the outer ellipse!";

}


이러한 방식으로 우리는 원하는 동작을 커스텀하게 작성할 수 있을 것이다. 


버블링 이벤트 라우팅은 언제나 상위의 개체로 이벤트를 이동시킨다. 그렇기 때문에 이번 예제에서 innerEllipse 객체를 클릭하면 outerEllipse가 아닌 상위 Canvas에 그 이벤트가 전달될 것이다. 즉, 두 개의 Ellipse 개체는 모두 동일한 레벨에 위치되어 있기 때문이다.



연속적이거나 불완전한 이벤트 버블링


여기서 만약 사용자가 outerEllipse객체를 클릭한다면 트리거에 Ellipse 타입을 위한 MouseDown 이벤트가 등록될 것이고 이 버블링은 해당 객체를 만나게 되면 이벤트는 중지된다. 대부분의 경우 이렇게 되길 바랄 수도 있지만 어떤 경우에서는 이 이벤트가 계속 상위로 전달되기를 바랄 수도 있다. 이 때 우리는 RountedEventArgs 타입에 false를 할당해 줘서 이벤트를 계속 유지시키는 것이 가능하다.




public void outerEllipse_MouseDown(object sender, RoutedEventArgs e)

{

    // Window 제목의 변경

    this.Title = "You clicked the outer ellipse!";

    // 버블링의 유지

    e.Handled = false;

}


이 경우 우리는 제목을 변경한 후에 버튼의 Click 이벤트에 전달되어 메시지 박스가 실행되는 것을 볼 수 있다. 요약하자면 이벤트 버블링을 단 하나의 이벤트로 처리되는 것을 가능하고 또한 불연속적인 이벤트를 제어하는 것 또한 가능하다.



터너링 이벤트의 역할


엄밀히 말해서 이벤트 라우팅은 실제로 버블링(Bubbling) 아니면 터너링(Tunneling) 이벤트 중에 하나이다. 터너링 이벤트들은 원래 엘리먼트가 가지고 있는 자식들 개체로 이벤트를 전달하게 된다. 대체로 WPF 클래스 라이브러리의 각각의 버블링 이벤트는 터너링 이벤트와 짝을 이루게 된다. 예를 들어 앞에서 MouseDown이 발생했을 때 PreviewMouseDown 이벤트가 먼저 발생하게 된다. 


터너링 이벤트는 다른 이벤트들을 선언하는 것과 같이 선언할 수 있다. 간단하게 XAML안에 이벤트 이름을 할당하고 거기에 메서드 이름을 지정해주면 되는 것이다. 그럼 이 터너링과 버블링 이벤트들을 확인해 보기 위해서 outerEllipse에 PreviewMouseDown를 추가해 보도록 하자.


 <Ellipse Name = "outerEllipse" Fill ="Green" Height ="25"

MouseDown ="outerEllipse_MouseDown"

PreviewMouseDown ="outerEllipse_PreviewMouseDown"

Width ="50" Cursor="Hand" Canvas.Left="25" Canvas.Top="12"/>



다음으로 현재 C# 클래스를 정의했던 메서드들을 string 문자열에 정보를 업데이트 하게 수정하자. 그리고 마지막에 이 문자열들을 한꺼번에 보여주게 수정해보도록 하자.


 public partial class MainWindow : System.Windows.Window

{

    // 마우스 관련 이벤트 정보를 담을 문자열

    string mouseActivity = string.Empty;

    public MainWindow()

    {

        InitializeComponent();

    }

    public void btnClickMe_Clicked(object sender, RoutedEventArgs e)

    {

        // 마지막으로 문자열 보여주기

        mouseActivity += "Button Click event fired!\n";

        MessageBox.Show(mouseActivity);

        // 문자열 클리어

        mouseActivity = string.Empty;

    }

    public void outerEllipse_MouseDown(object sender, RoutedEventArgs e)

    {

        // 문자열 추가

        mouseActivity += "MouseDown event fired!\n";

        // 버블링 유지

        e.Handled = false;

    }

    public void outerEllipse_PreviewMouseDown(object sender, RoutedEventArgs e)

    {

        // 문자열 추가

        mouseActivity = "PreviewMouseDown event fired!\n";

        // 버블링 유지

        e.Handled = false;

    }

}


이렇게 수정한 후에 프로그램을 실행해본 후에 밖의 원을 피해서 클릭해보면 간단하게 “Button Click event fired!” 라는 이벤트가 보여지는 것을 볼 수 있을 것이다. 하지만 만약 밖의 원을 클릭해보면 다음 [그림29-5]와 같은 메시지가 보여지는 것을 볼 수 있을 것이다.



그렇다면 WPF는 왜 이렇게 한 쌍으로 이벤트를 발생시키는 것인지 궁금할 것이다. 그 이유는 이벤트 미리보기를 통해서 데이터 유효성 검사나 버블링 동작의 실행여부와 같은 로직을 좀 더 유연하게 구현할 수 있게 하기 위해서라고 보면 된다. 대부분의 경우 Preview 접두사로 이용하는 터너링 이벤트들을 많이 이용하지 않을 것이고 보다 간단한 버블링 이벤트를 사용할 것이다.


의존성 속성을 직접 손으로 구현하는 경우처럼 터너링 이벤트는 서브 클래스를 가지고 있는 WPF 컨트롤에서 일반적으로 사용된다. 만약 이벤트가 버블링 되는 커스텀 컨트롤을 만든다면 의존 속성과 비슷한 메커니즘을 이용해서 커스텀 라우팅 로직을 구현해주어야 한다. 만약 이 내용에 대한 더 자세한 정보를 보고 싶다면  .NET Framework 3.5 SDK 문서의 “How to: Create a Custom Routed Event”를 살펴볼 것을 권한다.


Posted by k1rha
2012.05.06 01:17

우리가 자주 사용하는 특정 배열이 변하지 않는다는 가정을 하고, 그 배열을 이곳 저곳 (List Box)에서 반복해서 사용해야 한다고 생각해보자. 

이렇게 다른곳에서 참조하여 사용하고 싶을대 이 배열을 리소스 엘리먼트안에 넣는다면 그러한 방식으로 사용 할 수 있다.


WPF의 리소스들은 문자열 배열과 같은 마크업의 커스텀 데이터를 보여주기 위해서 주로 사용한다.




 <Page

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

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

xmlns:CorLib="clr-namespace:System;assembly=mscorlib">

  <StackPanel>

    <StackPanel.Resources>

      <x:Array Type="CorLib:String" x:Key = "GoodMusic">

        <CorLib:String>Sun Kil Moon</CorLib:String>

        <CorLib:String>Red House Painters</CorLib:String>

        <CorLib:String>Besnard Lakes</CorLib:String>

      </x:Array>

    </StackPanel.Resources>

    <Label Content ="Really good music"/>

    <ListBox Width = "200" ItemsSource ="{StaticResource GoodMusic}"/>

  </StackPanel>

</Page>


그리고 이렇게 staticResource마크업 확장자 식으로 ListBox에 대입되게 되면 초기 바인딩 이후에 값이 변하지 않고 항상 유지된다. 다른것이 향후 변경된다하더라도 이 staticResource를 참조한 컨트롤의 값은 변하지 않는다.


이것을 허용하기 위해서는 DynamicReosurce를 이용해야 한다. 



Posted by k1rha
2012.05.05 19:12


this. 객체에는 여러가지 이벤트 기능을 추가 할 수 있는데 크게 Activated 와 Keyboard 그리고 mouse 이벤트가 있다.

종류는 아래 스크린샷과 같다. 

 




이를 이용하여 += 으로 객체들을 추가 해 줄 수 있다. 이 때 파라미터값은 생략한다. 

그리고 아래 코드와 같이 메소드를 선언해 준다. 



 

 protected void MainWindow_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)

        {

            // Display keypress.

            title.Content = e.Key.ToString();

        }


        protected void MainWindow_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)

        {

            // 마우스의 X,Y 좌표를 가져온다.

            title.Content = e.GetPosition(this).ToString();

        }


}


위와같은 방식으로 마우스의 위치와 키보드의 입력을 가져 올 수 있다. 



Posted by k1rha
2012.05.05 17:20
이미지를 XMAML 로 생성해주지 않고 동적으로(갯수가 몇개인지 정확하지 않을때) 생성해 주고 싶은 경우가 있는데 
아래와 같이 해주면 된다. 

 public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

            String PATH = "c:\\tmp\\1.jpg";


            Image test = new Image();

            BitmapImage bitmap = new BitmapImage(new System.Uri(PATH));

            

            test.Source=bitmap;

            test.Width=100;

            test.Height=100;


            main_grid.Children.Add(test);



        }

    } 


빠트렸던 부분이 이미지 객체를 생성하고나서 이를 grid 쪽에 추가를 안해주고 안뜬다고 툴툴 됬었다. 


Main 에서  children.add 를 통하여 객체를 추가해 줘야함. 

Posted by k1rha
2012.05.03 00:28



 

using System;

using System.Collections.Generic;

using System.Windows.Forms;


namespace marlie.TumbnailDotnet

{

    static class Program

    {

        /// <summary>

        /// The main entry point for the application.

        /// </summary>

        [STAThread]

      

        static void Main()

        {

            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new MainForm());

        }

    }

}



헐.. 당황..    [STAThread] 이런 문법은 도데체 무엇이던가?! 


 C# 코드에서 [STAThread] 가 의미하는 바는 기본적으로, VS .NET에 의해 만들어진 응용 프로그램의 Main()메소드에는 [STAThread] 라는 속성으로 되어 있다. 


하지만 COM 형식을 이용하는 경우엔 [STAThread]  라는 것으로  해당 응용 프로그램이 COM형식을 이용하는 경우에 (단지 이 경우에만 해당하는 것인데) 해당 응용 프로그램이 단일 스레드 아파트(single threaded apartment, STA) 모델로 설정되어야 한다는 것을 런타임에게 알려주는 역할을 한다. 


즉 다중쓰레드로 동작하지 않는다는 것을 알려주는것이다. 


해당 응용 프로그램에서 COM 형식을 이용하지 않는다면, [STAThread] 어트리뷰트는 무시되기 때문에 삭제해도 무방하다.

Posted by k1rha