블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2738)
Unity3D (817)
Programming (475)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-30 00:00

rangeslider

기존의 sliderbar 혹은 trackbar 라고 부르는 컨트롤의 하나의 값 만을 선택할 수 있었는데요.

저는 어떤 영역(Range)를 선택할 수 있는 컨트롤을 만들었습니다.
슬라이더 영역의 최소값, 최대값을 입력하고 그 값들 안에서 특정 구간의 값을 선택할 수 있습니다.


슬라이더 컨트롤은 아래 첨부된 파일에서 Slider.dll 입니다.


// 아래는 컨트롤 모양, 값을 구성하는 기본값

LineThickness = 5;     // 슬라이더의 회색 표시의 라인 두께
TickFrequency = 10;    // 눈금 표시 단위
TickHeight = 5;        // 눈금 표시 길이

MinValue = 0;          // 슬라이더가 가지는 최소값
MaxValue = 100;        // 슬라이더가 가지는 최대값

RangeFrom = 0;         // 선택된 영역에서의 시작 값
RangeTo = 20;          // 선택된 영역에서의 끝 값

MinRangeSize = 10;     // 영역이 가지는 최소한의 크기
MaxRangeSize = 30;     // 영역이 가지는 최대한의 크기

영역이 가지는 최소값, 최대값을 사용하면 슬라이더의 영역(thumb)의 크기 변경이 제한됩니다.
사용하지 않으려면 MinRangeSize 를 0 으로 , MaxRangeSize 를 MaxValue - MinValue로 하시면 되겠지요.


test


위의 그림처럼 컨트롤을 테스트 할 수 있는 프로젝트를 배포합니다.

본 컨트롤은 상업적인 목적 이외에 자유롭게 사용 가능합니다.



반응형
Posted by blueasa
, |
Link : http://www.codeproject.com/KB/architecture/DesignPatternExampleCS.aspx

Simple examples illustrate Design Pattern

Introduction

Design patterns are some common ideas in writing programs. The whole list and their definitions can be found here. The link has very good descriptions and examples, so I won't repeat the definitions here. I think that the design patterns are not easy to understand, and there are too many examples to remember. In order to apply the design patterns to solve a problem, you would need to understand and remember the patterns so that you could see them in the problem. I couldn't remember even half of the names; I couldn't accurately recite a single pattern definition; and I am not sure whether I fully understand the definitions of the design patterns. However, I have been helped by a simple example which makes the patterns easy to understand and remember. I would like to share it and hope that it can help other people, too.

Background

I took the training from NetObjectives several years ago. I don't remember much of the definitions or principles from the training, but their example sticks in my mind. It is a simple problem but it holds several patterns in the problem.

The example is this: We need to design classes for two Shapes: Rectangle and Circle. We need to draw them on different devices: Console and Printer. The shapes can be moved and expanded. In the future, we might need to support other forms of transformation, such as rotate and distort. After transforming the shapes, we need to be able to undo it. We need to support more complex shapes which are comprised of simpler shapes.

Patterns in this Example

We first abstract the Rectangle and Circle as Shape. If the Shapes know how to draw on Printer and Console, then we would need different versions of Shapes. So, it is better to separate the Shape from the Drawing devices.We also abstract the Console and Printer as Drawing devices. This is actually using Bridge pattern because that it decouples the implementation of Shape and Drawing. In the following snippet, the IShape holds a reference to IDrawing object. Shape has two implementations: Circle and Rectangle. Drawing has two implementations: V1 and V2.

Collapse | Copy Code
/*
IShape------------->IDrawing
 /    \              / \
Circle Rectangle    V1 V2
*/
abstract class IShape
{
 protected IDrawing drawing;
 abstract public void Draw();
}
abstract class IDrawing
{
    abstract public void DrawLine();
 abstract public void DrawCircle();
}
class Circle:IShape
{
 override public void Draw(){drawing.DrawCircle();}
}
class Rectangle:IShape
{
 override public void Draw(){drawing.DrawLine(); drawing.DrawLine();}
}
class V1Drawing:IDrawing
{
 override public void DrawLine(){}
 override public void DrawCircle(){}
}
class V2Drawing:IDrawing
{
 override public void DrawLine(){}
 override public void DrawCircle(){}
}

Suppose that there are fixed number of Shapes, but there will be new types of Transformations. In order to support new types of Transformations, we can use the Visitor pattern to make Shapes class future proof. In the following snippet, the Shape class defines operation interface Accept(ITransform), so that new transform types can operated on shapes without modifying Shape classes.

Collapse | Copy Code
/*
   IShape---------->ITransform
 /    \            / \
Circle Rectangle Move Expand
*/
    abstract class IShape
    {
        abstract public void Accept(ITransform transform);
    }
    abstract class ITransform
    {
        abstract public void TransformCircle(Circle c);
        abstract public void TransformRectangle(Rectangle rect);
    }
    class Circle : IShape
    {
        override public void Accept(ITransform transform)
        {
            transform.TransformCircle(this);
        }
    }
    class Rectangle : IShape
    {
        override public void Accept(ITransform transform)
        {
            transform.TransformRectangle(this);
        }
    }
    class Move : ITransform
    {
        override public void TransformCircle(Circle c) { }
        override public void TransformRectangle(Rectangle rect) { }
    }
    class Expand : ITransform
    {
        override public void TransformCircle(Circle c) { }
        override public void TransformRectangle(Rectangle rect) { }
    }

If we want to undo the transform, we can use Memento pattern, where we can store the state of the Shape object without exposing its internal state.

Collapse | Copy Code
//Memento--->IShape

interface IMemento
{
 void ResetState();
}
class IShape
{
 public abstract IMemento GetMemento();
}

If we have a shape which is comprised of collections of other shapes, we can use Composite pattern so that we may handle the complex shape the same way.

Collapse | Copy Code
/*        IShape
         / | \
    Circle | Rectangle
           |
    CompositeShape 1--->* IShape

*/

class CompositeShape : IShape
{
 List<IShape> list = new List<IShape>();
}

If you call MembewiseClone() on an object, you only get a shallow copy of the object. The book “C# 3.0 Design Patterns” has a solution for DeepCopy. It serializes the object into a MemoryStream, and then Deserializes it back to a cloned object.

Collapse | Copy Code
[Serializable]
class IShape
{
public IShape DeepCopy()
{
 using (MemoryStream m = new MemoryStream())
 {
    BinaryFormatter f = new BinaryFormatter();
    f.Serialize(m, this);
    m.Seek(0, SeekOrigin.Begin);
    IShape ret = (IShape)f.Deserialize(m);
    ret.Drawing = drawing;
    return ret;
 }
}
}

Design Pattern Examples in C# and .NET Libraries

There are many examples in C# and .NET libraries. For example:

Adapter Pattern

Streams are tools to read/write a sequence of bytes. If you need to read/write strings or characters, you would need to create a Reader/Writer class. Fortunately, all the Reader/Writer classes can be constructed from a stream object. So, I think that the Reader/Writer classes are adapters which convert a byte array interface to string/char interface.

Collapse | Copy Code
Reader/Writer-->Stream
BinaryReader/Writer{ReadChars,ReadString}
TextReader/Writer{ReadLine,ReadBlock}
|-StreamReader/Writer
|-StringReader/Writer
Stream{Read(byte[]), Write(byte[], Seek, Position)
|
|-NetworkStream(socket){DataAvailable}
|-FileStream(path){ Lock/Unlock/GetACL,IsAsync}
|-MemoryStream (byte[]){GetBuffer(), WriteTo(stream),ToArray()}

I think "boxing" is also an adapter. It converts a value type into a reference type.

Decorator Pattern

When you need encryption or compression, or need to add a buffer on the network stream, you can use Decorator pattern. The bufferedStream, CryptoStream, and DeflateStream are decorators to other streams. They attach additional functionalities to existing streams without changing the interface of the original streams.

Collapse | Copy Code
Stream
|
|- BufferedStream(stream,buffersize), for network
|- CryptoStream: for encryption
|- DeflateStream: for compression

Flyweight Pattern

To save space, String class holds a reference to an Intern object. So, if two strings have the same literal, they share the same storage space. It uses "sharing" to support a large number of fine grained objects efficiently so that it is using Flyweight pattern.

Collapse | Copy Code
String s3 = String.Intern(s2); 

Object Pool Pattern

Creating threads are expensive. You can call Threadpool.QueueUserWorkitem() which uses thread pool to better use the system resources. So, I think that threadpool is a good example of object pool pattern.

Observer Pattern

Observer pattern defines a one to many dependency so that when one object changes state, all its dependencies are notified. The event in C# is exactly for this purpose. An event can be subscribed:

Collapse | Copy Code
UnhandledExceptionEventHandler handler =
	(object sender, UnhandledExceptionEventArgs v) => {
Console.WriteLine(
  "sender={0}, arg={1}, exception={2}, v.IsTerminating={3}",
  sender, v, v.ExceptionObject, v.IsTerminating);
  };
AppDomain.CurrentDomain.UnhandledException += handler;
throw new Exception("hiii");

To unsubscribe, you just need to call event-=.

Collapse | Copy Code
AppDomain.CurrentDomain.UnhandledException -= handler;

You can also define your own events:

Collapse | Copy Code
static public event EventHandler<EventArgs> breakingNews;
if(breakingNews!=null)
breakingNews("NBC", EventArgs.Empty);

If you don't want to check whether the event is null, just add a dummy subscriber:

Collapse | Copy Code
breakingNews += delegate { }; 

Iterator Pattern

Iterator provides a way to access the elements inside an aggregate object. C# has foreach keyword which makes Iterator really easy. It is hard for me to understand what Enumerable and Enumerator are. It is even more confusing why I have to define GetEnumerator for both IEnumerable and IEnumerable<T>. So, I just try to remember this example:

Collapse | Copy Code
class IntEnumerable:IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
    yield return 1;
    yield return 2;
}
IEnumerator IEnumerable.GetEnumerator()
{
    return this.GetEnumerator();
}
}
//Then you use the iterator like this:
foreach(int i in new IntEnumerable())Console.WriteLine(i);

Singleton Pattern

The simplest way to create a singleton is to use a static variable in C#.

Collapse | Copy Code
class Singleton
{
    private static Singleton instance = new Singleton();
    public static Singleton GetInstance()
    {
        return instance;
    }
}

Some people use the double-checked-lock to create a thread safe lazy initialization singleton. However, it is so subtle to implement that some people consider it as Anti-pattern: [Read this].

Netobjectives has this method which I think is the best way to create a thread safe lazy init singleton. Note that the static constructor disables BeforeFieldInit flag (see this link). The inner class Nested avoids early init when other static fields or methods of Singleton are called.

Collapse | Copy Code
class Singleton
{
    private Singleton() { }
    public static Singleton GetInstance()
    {
        return Nested.instance;
    }
    private class Nested
    {
        internal static Singleton instance = new Singleton();
        //static constructor to prevent beforefieldInit
        // see http://www.yoda.arachsys.com/csharp/beforefieldinit.html
        static Nested() {}
    }
} 

Using the Code

The sample code is written in C# 3.0.

Conclusion

I am sure I missed many patterns and might have misunderstood some in the above examples. If so, please let me know so that they can be corrected.

I have benefited from the examples I got from the training in NetObjectives. I felt that the training is an eye opener and I really learnt a lot. After a couple years, the only thing I still remember is their example about Shape, Drawing, and Transform. If you are not familiar with design patterns, I hope that this example gets you interested in reading Wikipedia or a book, or taking the training from NetObjectives. If you have taken their training or are familiar with design patterns, then the examples might help you quickly refresh your memory of design patterns.
One thing I learned is that if my code has a lot of copy/paste, or has a lot of switch/case statements, then I might need to think about using some design patterns.

I think the idea of design pattern is similar to Database normalization. During database normalization, we break one big table into several smaller tables, so that the total number of rows in tables is much smaller, and modification in one small table won't affect other tables. If we can separate/isolate the concepts in our problem, then we are likely applying the ideas of design pattern already, even if we don't remember the pattern names.

History

  • 23rd February, 2009: Initial post
  • 6th March, 2009: Article updated
    • Fixed a broken link
    • Fixed the snippet compilation errors
    • Removed some samples

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

반응형

'Programming > Design Pattern' 카테고리의 다른 글

C# 디자인패턴  (0) 2010.12.15
Dependency를 관리하는 방법  (0) 2010.10.21
GoF의 디자인패턴  (0) 2010.07.23
FSM - 유한 상태 기계 (Finite State Machine)  (0) 2010.07.09
GoF Design Pattern 요약  (0) 2010.05.31
Posted by blueasa
, |

C#에서 함수를 호출 하다 보면  함수명 다음에 Object sender, EventArgs e  가 있다.

과연 이넘은 무엇일까??

sender는 어떤 오브젝트가 이 이벤트를 유발시켰는지를 나타나게 한다.
다시 말해 이벤트를 보내는 객체이다.
여러개의 버튼이 한가지 이벤트 함수를 공유하고 있을 때
이 이벤트 함수가 어느 버튼에 의해서 유발되었는지를 알 수 있는 방법은
sender를 확인해 보는것이다.
즉.... 누가 이벤트를 부르고 있느냐에 대한 정보이다.!!

e 는 EventArgs 형으로 이벤트 발생과 관련된 정보를 가지고 있다.
즉 이벤트 핸들러가 사용하는 파라미터이다.
예를 들어서 마우스 클릭 이벤트시에 마우스가 클릭된 곳의 좌표를 알고 싶다던가
마우의 왼쪽 버튼인지 오른쪽 버튼인지를 알고 싶을 때 e의 내용을 참고 하면 될 것이다.

이벤트 처리기(Event Handler)는 이벤트에 바인딩되는 메서드이다.
이벤트가 발생하면 이벤트와 연결된 이벤트 처리기의 코드가 샐행된다.
모든 이벤트 처리기는 위와 같은 두 개의 매개변수를 전달한다.

출처 : http://h0wan.tistory.com/entry/Object-sender-EventArgs-e-는-무엇인가
반응형
Posted by blueasa
, |

이 기능은 사실 마우스 이벤트에 관해 검색 하던 중 발견 하게 되었다.

사실 검색기능과 사전 기능은 어느정도 구현 하긴 했으나 텍스트 창에서 엔터키를 쳤을때

검색 기능은 구현 하지 못하고 있었다.

방법은 간단 했다. 먼저  TextBox 이벤트에셔 keydown 이벤트를 추가 시켰다.

그리고 나서

if (e.KeyCode == Keys.Enter)
         Go_click(sender, e);

       

위 2줄 코드만 추가 시키면 끝!!

출처 : http://h0wan.tistory.com/entry/TextBox에-엔터-이벤트-넣기
반응형
Posted by blueasa
, |

Download source code (Microsoft Visual C# 2005 Express Edition)

 

image

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace WindowsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        List<PointF> PointList = new List<PointF>();
        int pointIndex = 0;

        private void Form1_Load(object sender, EventArgs e)
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            PointF[] pt = new PointF[] {
                new PointF(100, 100),
                new PointF(150, 150),
                new PointF(200, 100),
                new PointF(100, 100),

            };
            // Get Points From Line(s)
            float curDist = 0;
            float distance = 0;
            for (int i = 0; i < pt.Length - 1; i++)
            {
                PointF ptA = pt[i];
                PointF ptB = pt[i + 1];
                float deltaX = ptB.X - ptA.X;
                float deltaY = ptB.Y - ptA.Y;
                curDist = 0;
                distance = (float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));
                while (curDist < distance)
                {
                    curDist++;
                    float offsetX = (float)((double)curDist / (double)distance * (double)deltaX);
                    float offsetY = (float)((double)curDist / (double)distance * (double)deltaY);
                    PointList.Add(new PointF(ptA.X + offsetX, ptA.Y + offsetY));
                }
            }
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            for (int i = 0; i < pointIndex; i++)
            {
                e.Graphics.DrawLine(Pens.Black, PointList[i].X, PointList[i].Y, PointList[i + 1].X, PointList[i + 1].Y);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (pointIndex < PointList.Count - 1)
            {
                pointIndex++;
                this.Refresh();
            }
        }
    }
}
 
출처 : http://blog.daum.net/starkcb/63
반응형
Posted by blueasa
, |

Form1와 Form2를 만들었거든요.

Form1에 값을 Form2에 넘겨서 Form2에 있는 다이얼로그박스에있는 버튼을 누르면 Form1에서 넘겨준

값을 뿌려주는 간단한 프로그램입니다.

 

Form2안에 get,set 코드를 심어주면 잘 되는데.그렇게 하지않구 Data.cs라는 클래스를 하나 만들어서

거기에 get_set을 넣었습니다.어떻게 호출하면 되는지요?

아래와같이 작성했는데 왜 값이 Form2에 안넘어가는지 모르겠네요.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";          
            Frm2.ShowDialog();
         
        }

/***********************************************/

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            Data Dt =new Data();          
            MessageBox.Show(Dt.Ct.ToString());
          
        }

 

/************************************************/

 

/************Data.cs*******************************/

class Data
    {
        string caption;
        public string Ct
        {
            get
            {
                return caption;
            }
            set

            {

               caption = value;

            }
        }
    }

 

/***************************************************/

 

왜 그런지 답을 알려드릴게요.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";          
            Frm2.ShowDialog();
         
        }

/***********************************************/

 

Form1 클래스의 button1_Click 이벤트 핸들러에서 하는 작업은 다음과 같네요.

 

1) Form2 클래스의 인스턴스를 생성

 

2) Data 클래스의 인스턴스를 생성 후 초기화 작업

 

3) 생성된 Form2 클래스의 인스턴스를 화면에 출력. ShowDialog() 메소드 사용.

 

 

자~~ 여기서..

 

1) 2) 과정을 보면,

 

Form2 클래스의 인스턴스와

 

Data 클래스의 인스턴스는

 

아무런 연관 관계가 없다는 거죠.

 

관련점을 찾자면, 이벤트 핸들러의 지역 변수로 설정되었다는 거죠.

 

Form2 클래스의 인스턴스는  Data 클래스의 인스턴스의 참조를 갖고 있지 않으므로,

 

여기서 생성된 Data 클래스의 인스턴스에 절대로 접근할 수 없답니다.

 

 

즉, 지역변수로 인스턴스를 생성했든간에, 뭔가 클래스에 참조로 넘겨주든지 하는게 있어야 하는데,

 

그런게 없으니, 클래스의 인스턴스가 무슨 수로 지역 변수에 접근할 수 있겠냐구요?

 

지역변수를 소개시켜주지도 않았으니 알 턱이 없죠.

 

 

****************************************

예를 들어, 최소한 다음과 같은 코드는 있어야 겠죠.

 

            Form2 Frm2 = new Form2();       
            Data a = new Data();
            a.Ct = "안녕하세요";  

 

            frm2.CustomData = a;        // 뭐, 이렇게 설정하는게 있다면야, frm2 에서 CustomData        

                                                     // 프로퍼티로, 데이터를 전달받고 이를 출력할 수 있겠죠.

                                                     // 연관고리가 있어야 한다는 거죠.


            Frm2.ShowDialog();
 

****************************************

 

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            Data Dt =new Data();          
            MessageBox.Show(Dt.Ct.ToString());
          
        }

 

/************************************************/

 

 

Form2 클래스의 button1_Click 이벤트 핸들러에서 하는 작업은 다음과 같네요.

 

 

1) Data 클래스의 인스턴스를 생성.

 

2) 이 인스턴스의 내용을 메시지 박스에 출력

 

 

자~~ 여기서..

 

1) 과정에서 생성한 인스턴스는 완전히

 

별도의 메모리 개체로써,

 

Form1 클래스의 이벤트 핸들러에서

 

생성한 Data 개체와는 하나도 관련이 없죠.

 

무슨 말인지 아시겠죠?

 

각각 Form1, Form2 클래스의 이벤트 핸들러에 있는

 

지역 변수일 뿐이란 말입니다.

 

이벤트 핸들러가 끝나면, 그냥 가비지 컬렉터로 이동되는 변수죠.

 

 

 

자~~ 해결책은 여러가지가 있는데, 매우 간단하게 방법을 알려드리죠.

 

Data 클래스를 매개로 Form1 과 Form2 를 연결하고 싶다고 했죠?

 

그러면, Data 클래스를 static 으로 만들어 볼 수도 있어요.

 

클래스를 static 으로 만들었으면, 그 내부에는 멤버도 모두 static 이 되어야 하죠.

 

이렇게 되면, 일종의 전역 변수 형태가 되죠.

 

Form1 클래스에서도 참조가능하고,

 

Form2 클래스에서도 참조가능하죠.

 

static class Data
{
        static string caption;

        static public string Ct
        {
            get
            {
                  return caption;
            }
            set

            {

                 caption = value;

            }
       }
}

 

 

이제, 이벤트 핸들러를 고쳐봅시다.

 

/**********Form1.cs***********************/

private void button1_Click(object sender, EventArgs e)
        {          
           
            Form2 Frm2 = new Form2();       
 

           // Data a = new Data();

           // a.Ct = "안녕하세요";          
          

           Data.Ct = "안녕하세요";
            Frm2.ShowDialog();         
        }

 

/***********************************************/

 

 

/************Form2.cs***************************/

  private void button1_Click(object sender, EventArgs e)
        {
            //Data Dt =new Data();          
            MessageBox.Show(Data.Ct.ToString());
          
        }

 

/************************************************/


출처 : http://blog.daum.net/starkcb/101

반응형
Posted by blueasa
, |

using Microsoft.Win32;  // RegistryKey 사용을 위해 추가

namespace RegTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 레지스트리 가져오기
        private string getReg(string regVal)
        {
            RegistryKey reg = Registry.LocalMachine;
            reg = reg.OpenSubKey("Software\\myProgram", true);
            if (reg == null)
                return "";
            else
                return Convert.ToString(reg.GetValue(regVal)); // 값 검색
        }

        // 레지스트리 쓰기
        private void setReg(string regKey, string regVal)
        {
            RegistryKey reg = Registry.LocalMachine;
            reg = reg.CreateSubKey("Software\\myProgram",
                   RegistryKeyPermissionCheck.ReadWriteSubTree);
            reg.SetValue(regKey, regVal, RegistryValueKind.String);
            reg.Close();
        }

        // 등록 버튼
        private void button1_Click(object sender, EventArgs e)
        {
            string regKey = textBox1.Text;
            string regVal = textBox2.Text;

            setReg(regKey, regVal);
           
        }

        // 읽기 버튼
        private void button2_Click(object sender, EventArgs e)
        {
            string regKey = textBox1.Text;
            textBox2.Text = getReg(regKey);
        }
    }
}

출처 : http://blog.daum.net/starkcb/165

반응형
Posted by blueasa
, |

종료 혹은 최소화 버튼을 눌렷을 때 트레이 아이콘만들기~!

 

1.도구상자에서 NotifyIcon을 선택하여 Form에 추가 합니다. 추가 후 소성창의 Icon 속성에 준비해준 Ico 파일을 연결해 줍니다. 여기까지만 하고 실행시켜도 트레이에 우리 프로그램의 아이콘이 보이는 걸 볼 수 있습니다.


2. 트레이에서 마우스 오른쪽 버튼을 눌렀을 경우 나올 메뉴를 위해 ContextMenuStrip도 추가해 줍니다.

 



3. 아이콘 추가
Form에 NotifyIcon을 드레그 하여 추가한다.(시스템에 보여질 아이콘)

4. contextMenuStrip를 드레그 하여 추가한다.(트레이 아이콘의 오른쪽을 클릭하였을 때 보여질 메뉴스트립)
최대화(show)와 종료 버튼을 추가하였다.



5. 트레이 아이콘과 메뉴스트립 연결
폼이 초기에 로드될 때 연결이 되도록 설정하였다.
private void frmMain_Load(object sender, EventArgs e)
        {
            //트레이 아이콘과 컨텍스트메뉴 연결
            Tray.ContextMenuStrip = contextMenuStrip1;
        }
5. 종료 버튼을 눌렸을 때 최소화하기


이렇게 폼의 속성창에서 종료 이벤트를 추가하면 함수가 생성된다
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
 {
            e.Cancel = true;//이벤트 취소
            //둘중 한개 쓰면 됨 이둘을 사용하여 최소화 하면 alt+tab 실행 시 출력이 되지 않음 Start->
             this.Visible = false;
            //this.Hide();
            //둘중 한개 쓰면 됨 이둘을 사용하여 최소화 하면 alt+tab 실행 시 출력이 되지 않음 End<-

            //alt+tab를 눌렸을 때 도 나타나게 하는 법 Start ->
            //  this.WindowState = FormWindowState.Minimized;// 최소화
            //  this.ShowInTaskbar = false; //화면 하단에 나타나는것 해제
            //alt+tab를 눌렸을 때 도 나타나게 하는 법 End <-

   }

6. 트레이 아이콘 클릭시 최대화 하기
private void Tray_DoubleClick(object sender, EventArgs e)
        {
            //둘중 한개 쓰면 됨 이둘을 사용하여 최소화 하면 alt+tab 실행 시 출력이 되지 않음 Start->
             this.Visible = true;
            //this.Show();
            //둘중 한개 쓰면 됨 이둘을 사용하여 최소화 하면 alt+tab 실행 시 출력이 되지 않음 End<-

            //alt+tab를 눌렸을 때 도 나타나게 하는 법 Start ->
            //this.WindowState = FormWindowState.Maximized;// 최소화
            //this.ShowInTaskbar = true; //화면 하단에 나타나는것 해제
            //alt+tab를 눌렸을 때 도 나타나게 하는 법 End <-

      }

그외 트레이 아이콘에 show버튼을 눌렸을 때 함수 처리는 5번과 동일하게 내부 함수 처리하면 되고 exit눌렸을 때는 this.Close();처리를 하여 종료처리를 해주면 된다.!!

TraySample.zip


출처 : http://blog.daum.net/starkcb/60



포비님 예제 처럼 Application.Exit();로 처리하시던지
아래와 같이 처리하실수도 있습니다.

        private bool bNotClose = true;
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (bNotClose)
            {
                e.Cancel = true;    // 이벤트 취소
                Visible = false;    // 폼을 표시하지 않는다.
            }
            else
            {
                // 실제 종료시 코드를 처리(DB 세션 종료등..)
            }
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            notifyIcon1.Visible = false; //트레이아이콘 없앰
            bNotClose = false; // 실제 종료가 되도록 변경
            Close();

            //프로세스 종료
        //    Application.Exit();
        }
반응형
Posted by blueasa
, |

시스템 트레이(task tray)에 아이콘을 표시하려면?

 Outlook이나 MSN Messenger등과 같이 Windows 어플리케이션에서는 시스템 트레이(task tray, status 영역이라고도 불린다)에 아이콘을 표시하고, 어플리케이션 상태를 나타내거나 어플리케이션의 폼을 표시하기 위한 쇼트컷으로 이용할 수 있다.

 .NET Framework의 클래스 라이브러리에는 시스템 트레이에 아이콘을 표시하기 위한 NotifyIcon 컴퍼넌트를 사용하여, 위와 같은 어플리케이션을 간단하게 작성할 수 있다.

 본고에서는, 이하와 같은사양의 어플리케이션을 작성하면서, NotifyIcon 컴퍼넌트의 기본적인 이용 방법에 대해 정리한다.

  • 기동시에 폼과 시스템 트레이에 아이콘을 표시한다

  • 아이콘을 오른쪽 클릭해 표시되는 컨텍스트·메뉴의[종료]로 어플리케이션을 종료할 수 있다.

  • 폼의 오른쪽 상단에 있는[닫기]버튼을 클릭하면, 폼이 비표시화 된다(어플리케이션은 종료하지 않는다).

  • 아이콘의 더블 클릭으로 폼을 표시하고, 활성화 시킨다.

시스템 트레이에 아이콘을 표시

 우선 어플리케이션의 기동시에 시스템 트레이에 아이콘이 표시되도록 하자.

 Visual Studio .NET으로 Windows 어플리케이션의 프로젝트를 신규 작성하고,[툴 박스]윈도우에서 NotifyIcon 컴퍼넌트를 폼상에 드래그&드롭 한다.

 다음에[프로퍼티]윈도우에서 Icon 프로퍼티로 적당한 아이콘 파일(.ico 파일)을 선택한다. 여기서 지정한 아이콘이 시스템 트레이에 표시 된다. 이 설정을 하지 않으면, 어플리케이션을 실행해도 시스템 트레이에 아이콘이 표시되지 않는다.

 또, NotifyIcon 컴퍼넌트의 Text 프로퍼티에 문자열을 설정해 두면, 그것이 아이콘의 툴·힌트·텍스트로 사용된다. 이것은 마우스 커서를 아이콘으로 이동시켰을 때에 표시된다.

시스템 트레이 아이콘에서의 컨텍스트·메뉴 표시

 다음으로, 아이콘을 오른쪽 클릭할때[종료]메뉴를 표시하고 그것을 실행시키면 어플리케이션을 종료시키게 한다.

 이것은, ContextMenu 컴퍼넌트를 폼상으로- 드래그&드롭 해서[종료]항목을 추가하고,[프로퍼티]윈도우에서 NotifyIcon 컴퍼넌트의 ContextMenu 프로퍼티에, 지금 작성한 ContextMenu 컴퍼넌트를 설정한다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.

[종료]메뉴의 항목을 추가한 ContextMenu 컴퍼넌트

여기서는 폼 메뉴로 디자인하지만, 메뉴(이 화면에서는 contextMenu1)를 NotifyIcon 컴퍼넌트의 ContextMenu 프로퍼티로 설정하여, 아이콘을 오른쪽 클릭했을 때에 표시되게 한다. □

 

아이콘의[종료]메뉴에 의한 어플리케이션의 종료

 다음에는 지금 추가한[종료]메뉴 항목을 더블 클릭 하고, 메뉴 항목의 선택시 실행되는 이벤트 핸들러를 아래와 같이 기술한다.

private void menuItem1_Click(object sender, System.EventArgs e)
{
  notifyIcon1.Visible = false; // 아이콘을 트레이에서 삭제
  Application.Exit(); // 어플리케이션 종료
}
Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click
  NotifyIcon1.Visible = False '아이콘을 트레이에서 삭제
  Application.Exit() ' 어플리케이션 종료
End Sub

 

컨텍스트 메뉴의[종료]이벤트 핸들러의 기술(상:C#, 하:VB.NET)

 통상 Windows 폼을 종료시킬 때는 Close 메소드를 호출하지만, 이번에는 다음 항목에서 서술하는 것처럼 Close 메소드 호출에 의해 발생하는 Closing 이벤트를 취소시킨다. 여기서는 Application.Exit 메소드에 의해 어플리케이션을 강제적으로 종료시킨다.

 또, 어플리케이션 종료시에 시스템 트레이에 아이콘이 남아 있는 일이 있으므로, 아이콘(NotifyIcon 오브젝트)의 Visible 프로퍼티를 false로 설정하여 시스템 트레이에서 지운다.

 시스템 트레이 아이콘을 이용해 어플리케이션을 작성한 뒤에 종료해도 아이콘이 남아있어서, 그 아이콘 위에 마우스 커서를 올리면 사라지는 현상이 발생할 때에 이 방법을 시험해 보자.

 

[닫기]버튼 클릭에 의한 폼의 비표시

 시스템 트레이에 아이콘이 표시되는, 이른바 상주형의 어플리케이션에서는 폼의 오른쪽 상단에 있는[닫기]버튼을 클릭해도 어플리케이션이 종료되지 않고 서 폼을 비표시 시키는 경우가 많다.

 이 동작을 구현하려면, 폼을 닫으려 할 때에 발생하는 Closing 이벤트의 이벤트·핸들러를 폼에 추가해, 다음과 같이 기술한다.

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
  e.Cancel = true; // 종료 처리의 취소
  this.Visible = false; // 폼의 비표시
}
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
  e.Cancel = True ' 종료 처리의 취소
  Me.Visible = False ' 폼의 비표시
End Sub
 
 
폼의 Closing 이벤트 핸들러의 기술(상:C#, 하:VB.NET)

 이 이벤트 핸들러에서는 파라미터로 건네받는 CancelEventArgs 오브젝트의 Cancel 프로퍼티에 true를 설정해서 폼의 종료 처리를 취소할 수 있다.

 또 여기에서는, 폼의 Visible 프로퍼티에 false를 설정해서 폼을 비표시 시킨다.

아이콘의 더블 클릭에 의한 폼의 표시

 마지막으로, 폼의[닫기]버튼에 의해 비표시가 된 폼을, 시스템 트레이의 아이콘을 더블 클릭 하는 것으로 다시 표시되도록 하자.

 여기에는 NotifyIcon 컴퍼넌트에 DoubleClick 이벤트 핸들러를 추가해서 다음과 같이 기술한다.

private void notifyIcon1_DoubleClick(object sender, System.EventArgs e)
{
  this.Visible = true; // 폼의 표시
  if (this.WindowState == FormWindowState.Minimized)
    this.WindowState = FormWindowState.Normal; // 최소화를 멈춘다
  this.Activate(); // 폼을 활성화 시킨다
}
Private Sub NotifyIcon1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.DoubleClick
  Me.Visible = True '폼의 표시
  If Me.WindowState = FormWindowState.Minimized Then
    Me.WindowState = FormWindowState.Normal ' 최소화를 멈춘다
  End If
  Me.Activate() ' 폼을 활성화 시킨다
End Sub

 

아이콘(NotifyIcon 컴퍼넌트)의 DoubleClick 이벤트 핸들러의 기술(상:C#, 하:VB.NET)

 폼이 최소화되고 있는 경우에는 폼의 WindowState 프로퍼티에 FormWindowState.Normal로 설정하여 폼의 기본 상태로 되돌린다.

 또, 폼의 Activate 메소드를 호출해 폼을 활성화 시키고 있다. 이로써, 폼이 다른 윈도우 뒤에 숨을 경우에도 맨 앞에 표시 된다.

반응형

'Programming > C#' 카테고리의 다른 글

레지스트리 값 읽고, 쓰기 방법  (0) 2010.07.22
트레이 아이콘 만들기  (0) 2010.07.22
[Link] C# 관련 사이트  (0) 2010.07.22
C# 진법전환  (0) 2010.07.22
is 와 as  (0) 2010.07.21
Posted by blueasa
, |
반응형

'Programming > C#' 카테고리의 다른 글

트레이 아이콘 만들기  (0) 2010.07.22
.net에서 시스템 트레이아이콘 예제 전체공개  (0) 2010.07.22
C# 진법전환  (0) 2010.07.22
is 와 as  (0) 2010.07.21
region을 사용해서 코드를 깔끔하게  (0) 2010.07.21
Posted by blueasa
, |