블로그 이미지
따시쿵

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2015. 6. 1. 17:28 C#

프로그램 설명


이벤트와 델리게이트에 간단한 예제입니다.


1. 이벤트란?


1. A mechanism for communication between objects.

2. Used in building Loosely Coupled Applications.

   Encodo C# Handbook 7.30 – Loose vs. Tight Coupling

3. Helps Extending Applications.


오브젝트간에 통신(신호)을 담당하는 부분이며 Loosely Coupled 이 가장 큰 특징입니다.

 

 

델리게이트란?

 

1. Agreement / Contract between Publisher and Subscriber

2. Determines the signature of the event handler method in Subscriber

 

 

델리게이트와 이벤트를 만드는 순서


1. Define a delegate

2. Define an event based on that delegate 

3. Raise the event


2. 예제 시나리오를 위해서 3개의 클래스를 미리 만들어 두고, 여기에 델리게이트와 이벤트를 추가하는 것으로 하겠습니다.

 

전체적인 그림은 다음과 같으며, 기본 프로그램에 추가해 보도록 하겠습니다. 

 

기본 소스 파일 :

 

MainForm.cs MainForm.Designer.cs MainForm.resx Video.cs VideoEncoder.cs

 

mainform class

    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            Thread t_handler = new Thread(WorkingThread);
            t_handler.IsBackground = true;
            t_handler.Start();
        }

        private void WorkingThread()
        {
            var video = new Video() { Title = "video 1" };
            var videoEncoder = new VideoEncoder();

            videoEncoder.Encode(video, textBox1);
        }
    }

 

Video class

    public class Video
    {
        public string Title { get; set; }
    }

 

VideoEncoder class

    public class VideoEncoder
    {
        private delegate void SetDisplayText(string displayText, TextBox textbox1);
        public void Encode(Video video, TextBox textbox1)
        {
            TextDisplay("Encoding video...\n", textbox1);
            Thread.Sleep(3000);
            TextDisplay("End.", textbox1);
        }

        private void TextDisplay(string displayText, TextBox textbox1)
        {
            if(textbox1.InvokeRequired)
            {   
                textbox1.Invoke(new SetDisplayText(TextDisplay), displayText, textbox1);
                Application.DoEvents();
                return;
            }
            else
            {
                textbox1.AppendText(displayText + "\n");
            }
        }
    }

 

3. 델리게이트와 이벤트를 VideoEncoder class 에 정의합니다. (Publisher 정의)

    public class VideoEncoder
    {
        private delegate void SetDisplayText(string displayText, TextBox textbox1);

        // 1. Define a delegate
        // 2. Define an event based on that delegate
        // 3. Raise the event
        public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox textbpx1);
        public event VideoEncodedEventHandler VideoEncoded;

        public void Encode(Video video, TextBox textbox1)
        {
            TextDisplay("Encoding video...\n", textbox1);
            Thread.Sleep(3000);

            OnVideoEncoded(textbox1);

            TextDisplay("End.", textbox1);
        }

        private void TextDisplay(string displayText, TextBox textbox1)
        {
            if(textbox1.InvokeRequired)
            {   
                textbox1.Invoke(new SetDisplayText(TextDisplay), displayText, textbox1);
                Application.DoEvents();
                return;
            }
            else
            {
                textbox1.AppendText(displayText + "\n");
            }
        }
    }

 

이벤트를 호출합니다.

        protected virtual void OnVideoEncoded(TextBox textbox1)
        {
            if (VideoEncoded != null)
                VideoEncoded(this, EventArgs.Empty, textbox1);
        }

 

 

4. 이벤트 핸들러 구현합니다.(Subscriber 정의)

    public class MailService
    {
        public void OnVideoEncoded(object sender, EventArgs e, TextBox textbox1)
        {
            textbox1.Invoke((MethodInvoker)delegate
            {
                textbox1.AppendText("MailService: Sending an email....\n");
            });
        }
    }

    public class MessageService
    {
        public void OnVideoEncoded(object sender, EventArgs e, TextBox textbox1)
        {
            textbox1.Invoke((MethodInvoker)delegate
            {
                textbox1.AppendText("MessageService: Sending an message text....\n");
            });
        }
    }

 

5. 이벤트와 이벤트 핸들러를 추가합니다. (매개체 역할)  

            var video = new Video() { Title = "video 1" };
            var videoEncoder = new VideoEncoder();      // publisher
            var mailService = new MailService();        // subscriber
            var messageService = new MessageService();  // subscriber

            videoEncoder.VideoEncoded += mailService.OnVideoEncoded;
            videoEncoder.VideoEncoded += messageService.OnVideoEncoded;

            videoEncoder.Encode(video, textBox1);


현재까지 작업한 소스 파일 : MyEvnetnDelegate1.zip


6. 파라미터를 encapsulation 시켜서 구현하는 방법입니다.


파라미터를 숨길 VideoEventArgs class 를 추가 합니다.

    public class VideoEventArgs : EventArgs
    {
        public Video Video { get; set; }
    }

기존의 델리게이트 정의 부분의 두 번째 파라미터를 아래와 같이 VideoEventArgs class 로 변경합니다.


변경 전

public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox text1);

변경 후

public delegate void VideoEncodedEventHandler(object sender, VideoEventArgs args, TextBox text1);


이벤트를 호출하는 부분도 변경해 줍니다.


기존에 EventArgs 를 파라미터로 받는 부분을 VideoEventArgs 로 변경을 해 줍니다.


소스 파일 : 

MyEvnetnDelegate1(2).zip


7.EventHandler<TEventargs> 를 이용한 델리게이트


이벤트에서 이벤트 데이터를 생성할 때 EventHandler<TEventArgs>을 사용하면 사용자 지정 대리자를 직접 코딩할 필요가 없습니다. 단순히 이벤트 데이터 개체의 형식을 제네릭 매개 변수로 제공합니다.


VideoEventArgs class 를 다음과 같이 변경합니다.

    public class VideoEventArgs : EventArgs
    {
        public Video Video { get; set; }
        public TextBox Textbox1 { get; set; }
    }


다음 줄을 삭제합니다.

public delegate void VideoEncodedEventHandler(object sender, EventArgs args, TextBox text1);
public event VideoEncodedEventHandler VideoEncoded;


EventHanlder<TEventArgs> 델리게이트를 추가합니다.

public event EventHandler VideoEncoded;


소스 파일 : 

MyEvnetnDelegate1(3).zip



실행 화면





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

람다식(Lambda Expression) - 1  (0) 2015.06.08
EventHandler 와 EventHandler<TEventArgs> Delegate  (0) 2015.06.04
초단위 시간 경과 보이기  (0) 2015.05.12
로그인 창  (0) 2015.05.08
멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
posted by 따시쿵
2015. 5. 30. 14:22 C# with TCP/IP
프로그램 설명

서버-클라이언트로 구성 된 파일 전송 예제입니다.
한 번에 전송되는 양은 8k 이며, 양방향 통신을 합니다.

1. 기본 클래스와 UI 파일입니다.

기본 클래스 : SocketAcceptedEventArgs, Listener, PacketWriter, PacketReader

Listener.cs PacketIO.cs


UI 파일 : main.cs (서버와 클라이언트가 공통된 UI 를 사용함)


2. QueueType, TransferQueue class 를 정의합니다.

enum QueueType define : 다운로드인지, 업로드인지 구분하는 enum
    public enum QueueType : byte
    {
        Download,
        Upload
    }

class TransferQueue define : 전송되는 queue 에 저장하는 class
    public class TransferQueue
    {
        public static TransferQueue CreateUploadQueue(TransferClient client, string fileName)
        {
            try
            {
                var queue = new TransferQueue();
                queue.Filename = Path.GetFileName(fileName);
                queue.Client = client;
                queue.Type = QueueType.Upload;
                queue.FS = new FileStream(fileName, FileMode.Open);
                queue.Thread = new Thread(new ParameterizedThreadStart(transferProc));
                queue.Thread.IsBackground = true;
                queue.ID = Program.Rand.Next();
                queue.Length = queue.FS.Length;

                return queue;
            }
            catch
            {
                return null;
            }
        }

        public static TransferQueue CreateDownloadQueue(TransferClient client, int id, string saveName, long length)
        {
            try
            {
                var queue = new TransferQueue();
                queue.Filename = Path.GetFileName(saveName);
                queue.Client = client;
                queue.Type = QueueType.Download;
                queue.FS = new FileStream(saveName, FileMode.Create);
                queue.FS.SetLength(length);
                queue.Length = length;
                queue.ID = id;

                return queue;
            }
            catch
            {
                return null;
            }
        }

        private const int FILE_BUFFER_SIZE = 8175;
        private static byte[] file_buffer = new byte[FILE_BUFFER_SIZE];

        private ManualResetEvent pauseEvent;

        public int ID;
        public int Progress, LastProgress;

        public long Transferred;
        public long Index;
        public long Length;

        public bool Running;
        public bool Paused;

        public string Filename;

        public QueueType Type;

        public TransferClient Client;
        public Thread Thread;
        public FileStream FS;

        private TransferQueue()
        {
            pauseEvent = new ManualResetEvent(true);
            Running = true;
        }

        public void Start()
        {
            Running = true;
            Thread.Start(this);
        }

        public void Stop()
        {
            Running = false;
        }

        public void Pause()
        {
            if(!Paused)
            {
                pauseEvent.Reset();
            }
            else
            {
                pauseEvent.Set();
            }

            Paused = !Paused;
        }

        public void Close()
        {
            try
            {
                Client.Transfers.Remove(ID);
            }
            catch
            { 
            
            }

            Running = false;
            FS.Close();
            pauseEvent.Dispose();

            Client = null;
        }

        public void Write(byte[] bytes, long index)
        {
            lock(this)
            {
                FS.Position = index;
                FS.Write(bytes, 0, bytes.Length);
                Transferred += bytes.Length;
            }
        }

        private static void transferProc(object o)
        {
            TransferQueue queue = (TransferQueue)o;

            while(queue.Running && queue.Index < queue.Length)
            {
                queue.pauseEvent.WaitOne();

                if (!queue.Running)
                    break;

                lock(file_buffer)
                {
                    queue.FS.Position = queue.Index;

                    int read = queue.FS.Read(file_buffer, 0, file_buffer.Length);

                    PacketWriter pw = new PacketWriter();
                    pw.Write((byte)Headers.Chunk);
                    pw.Write(queue.ID);
                    pw.Write(queue.Index);
                    pw.Write(read);
                    pw.Write(file_buffer, 0, read);

                    queue.Transferred += read;
                    queue.Index += read;

                    queue.Client.Send(pw.GetBytes());

                    queue.Progress = (int)((queue.Transferred * 100) / queue.Length);

                    if(queue.LastProgress < queue.Progress)
                    {
                        queue.LastProgress = queue.Progress;

                        queue.Client.callProgressChanged(queue);
                    }

                    Thread.Sleep(1);
                }
            }
            queue.Close();
        }
    }

3. queue 작동 방법을 정의합니다.
    public enum Headers : byte
    {
        Queue,
        Start,
        Stop,
        pause,
        Chunk
    }

4. TransferClient class 정의 합니다.


transferClient calss define : 클라이언트 전송 class

    public class TransferClient
    {
        private Socket _baseSocket;

        private byte[] _buffer = new byte[8192];

        private ConnectCallback _connectCallback;

        private Dictionary<int, TransferQueue> _transfers = new Dictionary<int, TransferQueue>();

        public Dictionary<int, TransferQueue> Transfers
        {
            get { return _transfers; }
        }

        public bool Closed
        {
            get;
            private set;
        }

        public string OutputFolder
        {
            get;
            set;
        }

        public IPEndPoint EndPoint
        {
            get;
            private set;
        }

        public event TransferEventHandler Queued;
        public event TransferEventHandler ProgressChanged;
        public event TransferEventHandler Stopped;
        public event TransferEventHandler Complete;
        public event EventHandler Disconnected;

        public TransferClient()
        {
            _baseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public TransferClient(Socket sock)
        {
            _baseSocket = sock;
            EndPoint = (IPEndPoint)_baseSocket.RemoteEndPoint;
        }

        public void Connect(string hostName, int port, ConnectCallback callback)
        {
            _connectCallback = callback;
            _baseSocket.BeginConnect(hostName, port, connectionCallback, null);
        }

        private void connectionCallback(IAsyncResult ar)
        {
            string error = null;
            try
            {
                _baseSocket.EndConnect(ar);
                EndPoint = (IPEndPoint)_baseSocket.RemoteEndPoint;
            }
            catch(Exception ex)
            {
                error = ex.Message.ToString();
            }

            _connectCallback(this, error);
        }

        public void Run()
        {
            try
            {
                _baseSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.Peek, receiveCallback, null);
            }
            catch
            {
                Close();
            }
        }

        public void QueueTransfer(string fileName)
        {
            try
            {
                TransferQueue queue = TransferQueue.CreateUploadQueue(this, fileName);
                _transfers.Add(queue.ID, queue);
                PacketWriter pw = new PacketWriter();
                pw.Write((byte)Headers.Queue);
                pw.Write(queue.ID);
                pw.Write(queue.Filename);
                pw.Write(queue.Length);
                Send(pw.GetBytes());

                if(Queued != null)
                {
                    Queued(this, queue);
                }
            }
            catch
            {

            }
        }
        
        public void StartTransfer(TransferQueue queue)
        {
            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.Start);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
        }

        public void StopTransfer(TransferQueue queue)
        {
            if(queue.Type == QueueType.Upload)
            {
                queue.Stop();
            }

            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.Stop);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
            queue.Close();
        }

        public void PauseTransfer(TransferQueue queue)
        {
            if(queue.Type == QueueType.Upload)
            {
                queue.Pause();
                return;
            }

            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.pause);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
        }

        public int GetOverallProgress()
        {
            int overall = 0;

            foreach(KeyValuePair<int, TransferQueue> pair in _transfers)
            {
                overall += pair.Value.Progress;
            }
            System.Diagnostics.Trace.WriteLine(string.Format("1. overall = {0}", overall));
            if (overall > 0)
            {
                overall = (overall * 100) / (_transfers.Count * 100);
            }

            System.Diagnostics.Trace.WriteLine(string.Format("2. overall = {0}", overall));
            if (overall > 100)
                overall = 100;

            return overall;
        }

        public void Send(byte[] data)
        {
            if (Closed)
                return;

            lock(this)
            {
                try
                {
                    _baseSocket.Send(BitConverter.GetBytes(data.Length), 0, 4, SocketFlags.None);
                    _baseSocket.Send(data, 0, data.Length, SocketFlags.None);
                }
                catch
                {
                    Close();
                }
            }
        }

        public void Close()
        {
            Closed = true;
            _baseSocket.Close();
            if (_transfers != null)
            {
                _transfers.Clear();
                _transfers = null;
            }
            _buffer = null;
            OutputFolder = null;

            if (Disconnected != null)
                Disconnected(this, EventArgs.Empty);
        }

        private void process()
        {
            PacketReader pr = new PacketReader(_buffer);

            Headers header = (Headers)pr.ReadByte();

            switch(header)
            {
                case Headers.Queue:
                    {
                        int id = pr.ReadInt32();
                        string fileName = pr.ReadString();
                        long length = pr.ReadInt64();

                        TransferQueue queue = TransferQueue.CreateDownloadQueue(this, id, Path.Combine(OutputFolder, Path.GetFileName(fileName)), length);

                        _transfers.Add(id, queue);

                        if (Queued != null)
                        {
                            Queued(this, queue);
                        }

                    }
                    break;
                case Headers.Start:
                    {
                        int id = pr.ReadInt32();

                        if(_transfers.ContainsKey(id))
                        {
                            _transfers[id].Start();
                        }
                    }
                    break;
                case Headers.Stop:
                    {
                        int id = pr.ReadInt32();

                        if (_transfers.ContainsKey(id))
                        {
                            TransferQueue queue = _transfers[id];

                            queue.Stop();
                            queue.Close();

                            if(Stopped != null)
                            {
                                Stopped(this, queue);
                            }

                            _transfers.Remove(id);
                        }
                    }
                    break;
                case Headers.pause:
                    {
                        int id = pr.ReadInt32();

                        if(_transfers.ContainsKey(id))
                        {
                            _transfers[id].Pause();
                        }
                    }
                    break;
                case Headers.Chunk:
                    {
                        int id = pr.ReadInt32();
                        long index = pr.ReadInt64();
                        int size = pr.ReadInt32();
                        byte[] buffer = pr.ReadBytes(size);

                        TransferQueue queue = _transfers[id];

                        queue.Write(buffer, index);

                        queue.Progress = (int)((queue.Transferred * 100) / queue.Length);

                        if(queue.LastProgress < queue.Progress)
                        {
                            queue.LastProgress = queue.Progress;

                            if(ProgressChanged != null)
                            {
                                ProgressChanged(this, queue);
                            }

                            if(queue.Progress == 100)
                            {
                                queue.Close();

                                if(Complete != null)
                                {
                                    Complete(this, queue);
                                }
                            }
                        }
                    }
                    break;
            }
            pr.Dispose();
        }

        private void receiveCallback(IAsyncResult ar)
        {
            try
            {
                int found = _baseSocket.EndReceive(ar);

                if(found >= 4)
                {
                    _baseSocket.Receive(_buffer, 0, 4, SocketFlags.None);

                    int size = BitConverter.ToInt32(_buffer, 0);

                    int read = _baseSocket.Receive(_buffer, 0, size, SocketFlags.None);

                    while(read < size)
                    {
                        read += _baseSocket.Receive(_buffer, read, size - read, SocketFlags.None);
                    }

                    process();
                }

                Run();
            }
            catch
            {
                Close();
            }
        }

        internal void callProgressChanged(TransferQueue queue)
        {
            if (ProgressChanged != null)
                ProgressChanged(this, queue);
        }
    }

5. UI method 를 정의 합니다.


실행 화면




소스 파일 : 
posted by 따시쿵
2015. 5. 25. 15:13 C# with TCP/IP

프로그램 설명


패킷을 이용한 데이타 전송 예제입니다. 로그인과 회원가입을 예로 들어 설명 합니다.

전송할 데이타를 바로 네트워크 스트림에 쓰지 않고 전송 패킷에 저장을 한 후, 일괄 전송하는 방법입니다.


1. 3개의 프로젝트를 먼저 만듭니다.


  MyLogin_Packet : 클래스 라이브러리 타입, dll class 파일, 패킷 정의용

  MyLoginClient1_WindowsForm : 윈도우즈 폼 타입. 클라이언트 폼. exe 파일

  MyLoginServer1_WindowsForm : 윈도우즈 폼 타입. 서버 폼. exe 파일



2. MyLogin_Packet : 클래스 라이브러리 타입, dll class 파일, 패킷 정의용

   

   기본 패킷 정의

namespace MyLogin_Packet
{
    public enum PacketType :int
    {
        Login = 0,
        Login_RESULT,
        Member_REGISTER,
        Member_REGISTER_RESULT
    }

    [Serializable]
    public class Packet
    {
        public int packet_Type;
        public int packet_Length;
        
        public Packet()
        {
            this.packet_Type = 0;
            this.packet_Length = 0;
        }

        public static byte[] Serialize(Object data)
        {
            try
            {
                MemoryStream ms = new MemoryStream(1024 * 4); // packet size will be maximum 4k
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, data);
                return ms.ToArray();
            }
            catch
            {
                return null;
            }
        }

        public static Object Deserialize(byte[] data)
        {
            try
            {
                MemoryStream ms = new MemoryStream(1024 * 4);
                ms.Write(data, 0, data.Length);

                ms.Position = 0;
                BinaryFormatter bf = new BinaryFormatter();
                Object obj = bf.Deserialize(ms);
                ms.Close();
                return obj;
            }
            catch
            {
                return null;
            }
        }
    }
}

   

   파생된 패킷 정의(로그인, 회원가입)

namespace MyLogin_Packet
{
    [Serializable]
    public class Login : Packet
    {
        public string id_str { get; set; }
        public string pw_str { get; set; }

    }
}

namespace MyLogin_Packet
{
    [Serializable]
    public class MemberRegister : Packet
    {
        public string id_str { get; set; }
        public string pw_str { get; set; }
        public string nickname_str { get; set; }
    }
}

   


3. MyLoginClient1_WindowsForm : 윈도우즈 폼 타입. 클라이언트 폼. exe 파일

   

  로그인 버튼 클릭시 전송할 데이타 Login Packet class 로 Serialize 시킴. 받은 데이타는 LoginResult Packet class 로 Deserialize 시킴.

   

        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] buffer = new byte[1024 * 4];

                // 1. connect to server
                TcpClient client = new TcpClient("192.168.0.11", 7778);
                NetworkStream stream = client.GetStream();

                // 2. send the packet
                Login login = new Login();
                login.packet_Type = (int)PacketType.Login;
                login.id_str = textBox1.Text.Trim();
                login.pw_str = textBox2.Text.Trim();

                Packet.Serialize(login).CopyTo(buffer, 0);

                stream.Write(buffer, 0, buffer.Length);

                // 3. receive the packet
                Array.Clear(buffer, 0, buffer.Length);

                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                LoginResult loginResult = (LoginResult)Packet.Deserialize(buffer);

                if (loginResult.result)
                {
                    MessageBox.Show(loginResult.reason, "클라이언트 확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    MessageBox.Show(loginResult.reason, "클라이언트 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                // 4. close the socket
                stream.Close();
                client.Close();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


4. MyLoginServer1_WindowsForm : 윈도우즈 폼 타입. 서버 폼. exe 파일

  

   stream 으로 데이타를 받은 후, PacketType class 로 deserialize 시킴으로, 받은 패킷이 어떤 기능을 하는 패킷인지 구분하는 로직

  

            Packet packet = (Packet)Packet.Deserialize(buffer);

            if (packet == null)
                return;

            switch ((int)packet.packet_Type)
            {
                case (int)PacketType.Login:
                    {
                              // 로그인 로직 추가
                    }
                    break;
                case (int)PacketType.Member_REGISTER:
                    {
                              // 회원가입 로직 추가
                    }
                    break;
            }

   

   Login packet class 로 deserialize 시킴

  

                        // 받은 패킷을 Login class 로 deserialize 시킴
                        Login login = (Login)Packet.Deserialize(buffer);

                        setLog(string.Format("ID : {0}, PWD : {1}", login.id_str, login.pw_str)); // 화면에 display 시킴

   

   Loginresult packet class 로 serialize 시켜서 클라이언트에게 전송함

  

                        // 전송할 패킷을 LoginResult class 로 serialize 시킴
                        LoginResult loginResult = new LoginResult();
                        loginResult.packet_Type = (int)PacketType.Login_RESULT;
                        if (random.Next(1, 100) % 2 == 0)    // 짝수라면.... 로그인 성공 
                        {
                            loginResult.result = true;
                            loginResult.reason = "정상적으로 로그인이 되었습니다.";
                        }
                        else                                // 홀수라면.... 로그인 실패
                        {
                            loginResult.result = false;
                            loginResult.reason = "아이디와 비밀번호를 확인 하시기 바랍니다.";
                        }

                        Array.Clear(buffer, 0, buffer.Length);
                        Packet.Serialize(loginResult).CopyTo(buffer, 0);
                        stream.Write(buffer, 0, buffer.Length);


실행 화면


소스 파일 :


MyLogin_Packet.zip

MyLoginClient1_WindowsForm.zip  MyLoginServer1_WindowsForm.zip

posted by 따시쿵
2015. 5. 20. 11:50 C# with TCP/IP

프로그램 설명


서버에서 연결되어 있는 클라이언트의 유효성을 체크하는 예제입니다.


1. 윈도우폼의 [도구상자]에서 [Timer] 클래스를 끌어다 폼에 추가 


2. 윈도우폼에 체크 박스를 두어서 체크시 클라이언트 connection 체크를 주기적으로 실행.


   메시지 전송시 헤드만 전송하고 바디 전송은 하지 않습니다. 왜냐하면 유효한지만 

   체크하는 것이므로 연결이 정상적인지, 비정상적인지만 체크하면 됩니다.


   client.SendMessage(BitConverter.GetBytes((int)0));


        #region checkBox1_CheckedChanged
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                //
                timer1.Tick += new EventHandler(TimerEventProcessor);

                // Sets the timer interval to 10 seconds.
                timer1.Interval = 10000;
                timer1.Start();
            }
            else
                timer1.Stop();
        }
        #endregion

        #region TimerEventProcessor
        // This is the method to run when the timer is raised.
        private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
        {
            Trace.WriteLine("Event raise the TimerEventProcessor");

            Invoke((MethodInvoker)delegate
            {
                for (int i = 0; i < listView1.Items.Count; i++)
                {
                    Client client = listView1.Items[i].Tag as Client;

                    if (client.sck.Connected)
                        client.SendMessage(BitConverter.GetBytes((int)0));  
                    else
                    {
                        this.client_Disconnected(client);
                        DisconnectedClientList(client.sck);
                    }
                }
            });
        }
        #endregion




실행 후


소스 파일 : 

 MyKeepAliveClient1_WindowsForm.zip MyKeepAliveServer1_WindowsForm.zip


posted by 따시쿵
2015. 5. 15. 11:58 C# with Service Program

프로그램 설명


윈도우즈 서비스 프로그램을 디버깅하는 예제입니다.

디버깅하는 방법은 콘솔 프로그램 같이 F10 버튼을 이용하여 다음 단계로 넘어가는 것입니다.


1. visual syudio 2013 을 관리자 권한으로 실행


2. 프로그램 출력 형식을 [콘솔 응용 프로그램]으로 변경



3. 현재 프로그램이 대화형으로 실행되고 있는지 확인하는 로직 추가


기존의 Main  method를 다음과 같이 변경함. Environment.UserInteractive 를 이용해서 확인합니다. 그리고 테스트 TestStartupAndStop method를 추가합니다.


        static void Main(string[] args)
        {
            if (Environment.UserInteractive)
            {
                MyNewService2 service2 = new MyNewService2();
                service2.TestStartupAndStop(args);
            }
            else
            {
                // Put the body of your old Main method here.
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new MyNewService2() 
                };
                ServiceBase.Run(ServicesToRun);
            }
        }

TestStartupAndStop method를 기술합니다.

        #region TestStartupAndStop
        internal void TestStartupAndStop(string[] args)
        {
           Console.WriteLine("TestStartupAndStop");
           this.OnStart(args);
           LogFile.WriteLog("TestStartupAndStop");
            
            Console.ReadLine();
            this.OnStop();
        }
        #endregion


4. 단일 thread 인 경우, 사용자 thread 가 있는 경우


메인 Thread 에서 작업하는 경우, 즉 단일 쓰레드에서 사용자 작업을 하는 경우에는 OnStart() 안에 로직을 추가하면 됩니다.


그러나, 메인 Thread 외에 사용자 Thread를 이용하는 경우에는, 메인 Thread가 사용자 쓰레드가 정지 할때까지 기달려야 합니다. 그래서 기존의 OnStart() 안에 thread_handler.Join(); 코드를 추가했습니다.

        #region OnStart
        protected override void OnStart(string[] args)
        {
            LogFile.WriteLog("OnStart");
                        
            // Create the sub working thread...
            Thread thread_handler = new Thread(socketMain.StartSocket);
            thread_handler.IsBackground = true;
            thread_handler.Start();

            if (Environment.UserInteractive)
            {
                   thread_handler.Join();
            }
        }
        #endregion



실행 화면



소스 파일 : 

MyNewService2_debug.zip






'C# with Service Program' 카테고리의 다른 글

[C#] 서비스 프로그램 - 2  (0) 2015.05.14
[C#] 서비스 프로그램 - 1  (0) 2015.05.11
posted by 따시쿵
2015. 5. 14. 14:23 C# with Service Program

프로그램 설명


윈도우즈 서비스를 이용해서 Tcp 통신을 하는 예제입니다.

서버는 서비스로 만들었으며, 클라이언트는 윈도우즈 폼으로 작성 했습니다.

서버에서 클라이언트와 통신을 할 때 각 단계별로 로그 파일을 쌓아서 진행 상황을 체크 합니다.


1. app.config 파일에 실제 로그를 쌓을 경로 이름을 기술합니다.


    
      
    
  
     
        
    


Debug 폴더 안에서 파일을 실행 시키면 System.IO.Directory.GetCurrentDirectory() method 를 이용해서 현재의 위치를 찾을 수 있지만, 서비스 프로그램에서 실행 파일의 현재 위치를 찾게되면 64비트 컴퓨터에서는 C:\Windows\SysWOW64 폴더를 찾습니다. 따라서 SysWOW64 폴더 하위에 Log 폴더를 생성합니다. 


app.config 파일 안에서 로그 파일의 위치를 풀경로를 이용해서 명시해 줍니다.


2. 로그 파일 이용 방법 

로그 라이브러리 : LogFile.cs

LogFile.WriteLog("OnStart");

LogFile.WriteLog(ex.Message, LogFile.LogCode.Error);


3. 윈도우즈 서비스가 설치된 컴퓨터의 방화벽에서 해당하는 포트를 열러 주어야 합니다.



실행 화면







프로그램 작성 순서


1. 서비스 프로그램의 OnStart() 에서 소켓 관련 thread 를 생성합니다.


        protected override void OnStart(string[] args)
        {
            LogFile.WriteLog("OnStart");
                        
            // Create the sub working thread...
            Thread thread_handler = new Thread(socketMain.StartSocket);
            thread_handler.IsBackground = true;
            thread_handler.Start();
        }


2. 일반적인 소켓 서버 클래스를 작성합니다.


        static TcpListener server = null;
        #region StartSocket
        public void StartSocket()
        {
            LogFile.WriteLog("StartSocket");

            try
            {
                // set the TcpListener on port 14000
                Int32 port = 14000;
                
                // create the server socket & start
                server = new TcpListener(IPAddress.Any, port);
                server.Start();

                // buffer for reading data
                byte[] bytes = new byte[2014];
                string data = string.Empty;

                // waiting for a client connection
                while (true)
                {
                    LogFile.WriteLog("Waiting for a connection....");

                    TcpClient client = server.AcceptTcpClient();
                    LogFile.WriteLog("Connected!");

                    NetworkStream stream = client.GetStream();

                    // read the message from client and send the message to client
                    int bytesRead = 0;
                    while ((bytesRead = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        data = Encoding.UTF8.GetString(bytes, 0, bytesRead);
                        LogFile.WriteLog(string.Format("Received : {0}", data));

                        data = data.ToUpper();

                        byte[] msg = Encoding.UTF8.GetBytes(data);

                        stream.Write(msg, 0, msg.Length);
                        LogFile.WriteLog(string.Format("Sent : {0}", data));
                    }

                    client.Close();
                }

            }
            catch (SocketException se)
            {
                LogFile.WriteLog(se.Message, LogFile.LogCode.Error);
            }
            catch (Exception ex)
            {
                LogFile.WriteLog(ex.Message, LogFile.LogCode.Error);
            }
            finally
            {
                server.Stop();
            }

        }
        #endregion


3. OnStop method 에서 socket server를 닫습니다.


        protected override void OnStop()
        {
            LogFile.WriteLog("OnStop");

            socketMain.StopSocket();
        }




소스 파일 :

MyNewService2.zip   MyNewService2_Client.zip

'C# with Service Program' 카테고리의 다른 글

[C#] 서비스 프로그램 - 디버깅  (0) 2015.05.15
[C#] 서비스 프로그램 - 1  (0) 2015.05.11
posted by 따시쿵
2015. 5. 12. 16:30 C#
프로그램 설명

타이머 클래스를 이용해서 초단위로 경과 시간을 보이는 예제입니다.



실행 후


폼 로드시에 현재 날자와 시간을 보여주고 1초 단위로 화면에 업데이트 합니다.

        private void Form1_Load(object sender, EventArgs e)
        {
            label1.Text = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            // Set up a timer to trigger every minute.
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Interval = 1000;                          // 1 seconds
            timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
            timer.Start();
        }

        public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
        {
            // TODO: Insert monitoring activities here.
            Invoke((MethodInvoker)delegate
            {
                label1.Text = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            });
        }


소스 파일 : 

MyTimer1.zip


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

EventHandler 와 EventHandler<TEventArgs> Delegate  (0) 2015.06.04
Event 와 Delegate  (0) 2015.06.01
로그인 창  (0) 2015.05.08
멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
데이타베이스 라이브러리  (0) 2015.04.22
posted by 따시쿵
2015. 5. 11. 17:21 C# with Service Program
프로그램 설명

서비스 프로그램을 작성하고 인스톨하며, 삭제하고 서비스의 시작과 종료를 event log 에 명시하는 프로그램입니다.


1. 서비스 만들기


서비스를 만들고 구성하려면


1. Visual Studio의 메뉴 모음에서 파일, 새로 만들기, 프로젝트를 선택합니다.   

새 프로젝트 대화 상자가 열립니다.   


2. Visual C# 프로젝트 템플릿 목록에서 Windows 서비스를 선택하고 프로젝트의 이름을 MyNewService로 지정합니다. 확인을 선택합니다. 


프로젝트 템플릿은 System.ServiceProcess.ServiceBase에서 상속된 Service1이라는 구성 요소 클래스를 자동으로 추가합니다.   


3. 편집 메뉴에서 찾기 및 바꾸기, 파일에서 찾기를 선택합니다(키보드: Ctrl+Shift+F).  모든 Service1을 MyNewService로 변경합니다. Service1.cs, Program.cs 및 Service1.Designer.cs  파일에서 인스턴스를 찾습니다. 


4. Service1.cs [디자인] 의 속성 창에서 Service1의 ServiceName 및 (이름) 속성이 아직 설정되어 있지 않으면 MyNewService로 설정합니다.  


5. 솔루션 탐색기에서 Service1.cs의 이름을 MyNewService.cs로 바꿉니다. 



2. 서비스에 기능 추가


사용자 지정 이벤트 로그 기능을 서비스에 추가하려면


1. 솔루션 탐색기에서 MyNewService.cs 뷰 디자이너를 선택합니다.  


2. 도구 상자의 구성 요소 섹션에서 EventLog 구성 요소를 디자이너로 끌어 옵니다.  


3. 솔루션 탐색기에서 MyNewService.cs 메뉴를 열고 코드 보기를 선택합니다.  


4. MyNewService 클래스에서 components 변수를 선언하는 줄 바로 다음에 eventLog 개체에 대한 선언을 추가합니다. 

this.AutoLog = false;

5. 사용자 지정 이벤트 로그를 정의하는 생성자를 추가하거나 편집합니다. 

	public MyNewService()
	{
		InitializeComponent();
		if (!System.Diagnostics.EventLog.SourceExists("MySource")) 
		{         
				System.Diagnostics.EventLog.CreateEventSource(
					"MySource","MyNewLog");
		}
		eventLog1.Source = "MySource";
		eventLog1.Log = "MyNewLog";
	}


서비스가 시작될 때 수행되는 동작을 정의하려면


• 코드 편집기에서 프로젝트를 만들 때 자동으로 재정의된 OnStart 메서드를 찾아서 코드를 다음과 같이 바꿉니다.  이렇게 하면 서비스 실행이 시작될 때 이벤트 로그에 항목이 추가됩니다. 

        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("In OnStart");
        }

서비스 응용 프로그램은 오랫동안 실행되도록 설계되므로 대개 시스템의 특정 항목을 폴링하거나 모니터링합니다.  모니터링은 OnStart 메서드에서 설정됩니다. 그러나 OnStart가 실제로 모니터링을 수행하지는 않습니다. 서비스의 작업이 시작되고 나면 OnStart 메서드가 운영 체제에 반환되어야 하며 무제한 순환하거나 방해가 되어서는 안 됩니다. 간단한 폴링 메커니즘을 설정하려면 System.Timers.Timer 구성 요소를 사용할 수 있습니다. 타이머는 코드에서 주기적으로 이벤트를 발생시키며 그러는 동안에도 서비스에서는 모니터링을 수행할 수 있습니다. 이렇게 하려면 다음 코드를 사용할 수 있습니다.

        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("In OnStart");

            // Set up a timer to trigger every minute.
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Interval = 60000; // 60 seconds
            timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
            timer.Start();
        }


타이머 이벤트를 처리하는 코드를 추가합니다.

        public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
        {
            // TODO: Insert monitoring activities here.
            eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, 210001);
        }

주 스레드에서 모든 작업을 실행하는 대신 백그라운드 작업자 스레드를 사용하여 작업을 수행할수도 있습니다.


3. 서비스에 설치 관리자 추가


서비스를 위한 설치 관리자를 만들려면


1. 솔루션 탐색기에서 MyNewService.cs 의 메뉴를 열고 뷰 디자이너를 선택합니다.   


2. 디자이너의 배경을 클릭하여 서비스 내용이 아닌 서비스 자체를 선택합니다.  


3. 디자이너 창의 상황에 맞는 메뉴를 열고(포인팅 장치를 사용하는 경우 창 안쪽을 마우스 오른쪽 단추로 클릭) 설치 관리자 추가를 선택합니다.   



기본적으로 설치 관리자가 두 개 들어 있는 구성 요소 클래스가 프로젝트에 추가됩니다.  구성 요소의 이름이 ProjectInstaller로 지정되며 구성 요소에는 서비스를 위한 설치 관리자와 서비스 관련 프로세스를 위한 설치 관리자가 들어 있습니다. 


4. ProjectInstaller의 디자인 뷰에서 Visual C# 프로젝트의 경우 serviceInstaller1을 선택합니다.  


5. 속성 창에서 ServiceName 속성이 행복서비스로 설정되어 있는지 확인합니다.  


6. 설명 속성을 "샘플 서비스"와 같은 텍스트로 설정합니다.  이 텍스트는 서비스 창에 표시되며 사용자가 서비스를 식별하고 서비스의 용도를 이해하는 데 도움이 됩니다. 


7. DisplayName  속성을 서비스 창의 이름 열에 표시할 텍스트로 설정합니다.  예를 들어 "행복서비스 표시 이름"을 입력할 수 있습니다. 이 이름은 net start 명령을 사용하여 서비스를 시작하는 등의 경우 시스템에서 사용하는 이름인 ServiceName 속성과는 다릅니다. 


8. StartType  속성을 Automatic으로 설정합니다. 


9. 디자이너에서 Visual C# 프로젝트의 경우 serviceProcessInstaller1을 선택합니다.  Account  속성을 LocalSystem으로 설정합니다. 이렇게 하면 서비스가 로컬 서비스 계정으로 설치되고 실행됩니다. 



4. 시작 매개 변수 설정


다른 실행 파일과 마찬가지로 Windows 서비스에도 명령줄 인수나 시작 매개 변수를 사용할 수 있습니다.  프로세스 시작 매개 변수에 코드를 추가하면 사용자가 Windows 제어판의 서비스 창을 사용하여 고유한 사용자 지정 시작 매개 변수로 서비스를 시작할 수 있습니다. 그러나 이러한 시작 매개 변수는 다음 번에 서비스를 시작할 때 유지되지 않습니다. 시작 매개 변수를 영구적으로 설정하려는 경우 아래 절차에 나와 있는 것처럼 레지스트리에서 설정하면 됩니다. 


일반적으로 서비스에 많은 시작 매개 변수가 필요한 경우에는 레지스트리나 구성 파일을 대신 사용하는 것이 좋습니다. 

모든 Windows 서비스에는 레지스트리의 HKLM\System\CurrentControlSet\services 아래에 항목이 있습니다. 이 서비스의 키 아래에서 매개 변수 하위 키를 사용하여 서비스가 액세스할 수 있는 정보를 저장할 수 있습니다. Windows 서비스의 응용 프로그램 구성 파일은 다른 프로그램 형식에서와 같은 방식으로 사용할 수 있습니다. 예제 코드를 보려면 AppSettings를 참조하세요. 

1. Program.cs 의 Main 메서드에서 명령줄에 대해 인수를 추가합니다. 

        static void Main(string[] args) 
        { 
            ServiceBase[] ServicesToRun; 
            ServicesToRun = new ServiceBase[] 
            { 
                new MyNewService1(args) 
            }; 
            ServiceBase.Run(ServicesToRun); 
        }

2. MyNewService 생성자를 다음과 같이 변경합니다. 

        public MyNewService1(string[] args)
        {            
            InitializeComponent();
            string eventSourceName = "MySource";
            string logName = "MyNewLog";
            if (args.Count() > 0)
            {
                eventSourceName = args[0];
            }
            if (args.Count() > 1)
            {
                logName = args[1];
            }
            eventLog1 = new System.Diagnostics.EventLog();
            if (!System.Diagnostics.EventLog.SourceExists(eventSourceName))
            {
                System.Diagnostics.EventLog.CreateEventSource(eventSourceName, logName);
            }
            eventLog1.Source = eventSourceName;
            eventLog1.Log = logName;
        }

이 코드는 제공된 시작 매개 변수에 따라 이벤트 소스 및 로그 이름을 설정하거나, 인수를 제공하지 않는 경우에는 기본값을 사용합니다. 


3. 명령줄 인수를 지정하려면 ProjectInstaller.cs 의 ProjectInstaller 클래스에 다음 코드를 추가합니다. 

        protected override void OnBeforeInstall(IDictionary savedState)
        {
            string parameter = "MySource1\" \"MyLogFile1";
            Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";
            base.OnBeforeInstall(savedState);
        }

이 코드는 기본 매개 변수 값을 추가하여 일반적으로 Windows 서비스 실행 파일의 전체 경로를 포함하는 ImagePath 레지스트리 키를 수정합니다. 경로와 개별 매개 변수는 따옴표로 묶어야 서비스가 올바르게 시작됩니다. 이 Windows 서비스의 시작 매개 변수를 변경하려는 경우 사용자는 ImagePath 레지스트리 키에 지정된 매개 변수를 변경할 수 있습니다. 그러나 해당 키를 프로그래밍 방식으로 변경하고 사용자 친화적인 방식(예: 관리 또는 구성 유틸리티)으로 기능을 노출하는 것이 보다 효율적입니다.



5. 서비스 빌드


서비스 프로젝트를 빌드하려면


1. 솔루션 탐색기에서 프로젝트의 상황에 맞는 메뉴를 열고 속성을 선택합니다.  프로젝트의 속성 페이지가 나타납니다. 


2. 응용 프로그램 탭의 시작 개체 목록에서 MyNewService.Program을 선택합니다.   


3. 솔루션 탐색기에서 프로젝트의 상황에 맞는 메뉴를 열고 빌드를 선택하여 프로젝트를 빌드합니다(키보드: Ctrl+Shift+B). 


6. 서비스 설치


Windows 서비스를 설치하려면


1. Windows 7 및 Windows Server에서는 시작 메뉴의 Visual Studio Tools에서 개발자 명령 프롬프트를 엽니다.  Windows 8 또는 Windows 8.1에서는 시작 화면의 Visual Studio Tools 타일을 선택한 다음 관리 자격 증명을 사용하여 개발자 명령 프롬프트를 실행합니다. 마우스를 사용하는 경우 개발자 명령 프롬프트를 마우스 오른쪽 단추로 클릭한 후 관리자 권한으로 실행을 선택합니다. 


2. 명령 프롬프트 창에서 프로젝트의 출력이 포함된 폴더로 이동합니다.  예를 들어, 내 문서 폴더에서 D:\win_project\winformapp2\MyNewService1\bin\Debug로 이동합니다. 


3. 다음 명령을 입력합니다. 


installutil.exe MyNewService1.exe





7. 서비스 시작 및 실행


서비스를 시작하고 중지하려면


1. Windows에서 시작 화면 또는 시작 메뉴를 열고 services.msc를 입력합니다.  

이제 서비스 창의 목록에 행복서비스 이름 표시 가 표시됩니다. 


2. 서비스 창에서 서비스의 바로 가기 메뉴를 열고 시작을 선택합니다.   


3. 서비스의 바로 가기 메뉴를 열고 중지를 선택합니다.   


4. (선택 사항) 명령줄에서 net start 행복서비스 및 net stop 행복서비스 명령을 사용하여 서비스를 시작하고 중지할 수 있습니다. 


서비스의 이벤트 로그 출력을 확인하려면


1. 명령 프롬프트 창에서 eventvwr.msc 를 입력합니다.


2. MyNewLog(선택적 절차를 사용하여 명령줄 인수를 추가한 경우에는 MyLogFile1)의 목록을 찾아서 확장합니다.  서비스에서 수행한 두 작업(시작 및 중지)의 항목을 확인할 수 있습니다. 


8. Windows 서비스 제거


서비스를 제거하려면


1. 관리 자격 증명을 사용하여 개발자 명령 프롬프트를 엽니다.  


2. 명령 프롬프트 창에서 프로젝트의 출력이 포함된 폴더로 이동합니다.  예를 들어, 내 문서 폴더에서 D:\win_project\winformapp2\MyNewService1\bin\Debug로 이동합니다. 


3. 다음 명령을 입력합니다. 


installutil.exe /u MyNewService.exe



소스 파일 : 

MyNewService1.zip





'C# with Service Program' 카테고리의 다른 글

[C#] 서비스 프로그램 - 디버깅  (0) 2015.05.15
[C#] 서비스 프로그램 - 2  (0) 2015.05.14
posted by 따시쿵
2015. 5. 8. 15:48 C#

프로그램 설명


로그인 창에서 메인창으로 이동하는 예제입니다.

이를 위해서 access db를 사용했으며 구조는 이메일, 비밀번호 필드와, idx 자동증가값 필드로 구성되어 있습니다.


테스트를 위해서 데이타는 아래와 같습니다.



실행 후



프로그램 작성


1. access db 에 접근하기 위해서 oledb 를 import 함.

using System.Data.OleDb;

2. [로그인] 버튼에 아래 프로그램을 작성함


        private void btnLogin_Click(object sender, EventArgs e)
        {
            OleDbConnection connect = null;
            OleDbCommand command = null;
            OleDbDataReader reader = null;

            try
            {
                connect = new OleDbConnection();
                connect.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=../../SampleDB.accdb;Persist Security Info=False";
                connect.Open();

                command = new OleDbCommand();
                command.Connection = connect;
                command.CommandText = "select user_email, user_password from tbl_member where user_email ='" + txtUser_email.Text.Trim()
                                     + "' and user_password = '" + txtUser_password.Text.Trim() + "'";

                reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        Trace.WriteLine(string.Format("User email : {0}, password : {1}",
                            reader["user_email"].ToString(), reader["user_password"].ToString()));
                    }

                    // 로그인창을 숨기기
                    this.Hide();

                    // 메인폼으로 이동하는 스크립트
                    MainForm f = new MainForm();
                    f.Show();
                    f.WindowState = FormWindowState.Maximized;
                }
                else
                    MessageBox.Show("이메일과 비밀번호를 확인 하시기 바랍니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch { }
            finally
            {
                connect.Close();
            }
        }



소스 파일 : 

Login1.zip

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

Event 와 Delegate  (0) 2015.06.01
초단위 시간 경과 보이기  (0) 2015.05.12
멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
데이타베이스 라이브러리  (0) 2015.04.22
BackgroundWorker class  (0) 2015.03.02
posted by 따시쿵
2015. 5. 7. 15:43 C#

MDI(Multiple Document Interface) 를 만드는 예제입니다.


MDI 만드는 방법


1. 일반 폼에 isMdiContainer 속성값을 true 로 설정함으로써 폼 컨테이너로 설정


실행화면


프로그램 작성

        #region Form2
        Form2 f2 = null;
        private void form2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (f2 == null)
            {
                f2 = new Form2();
                f2.MdiParent = this;
                f2.FormClosed += new FormClosedEventHandler(f2_FormClosed);
                f2.Show();
            }
            else
                f2.Activate();
        }

        void f2_FormClosed(object sender, FormClosedEventArgs e)
        {
            f2 = null;
        }
        #endregion

        #region Form3
        private void form3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form3 f3 = new Form3();
            f3.MdiParent = this;
            f3.Show();
        }
        #endregion


2. 폼을 만드는 시점에 MDI 부모 폼 으로 폼 자체를 만듦


실행화면


프로그램 작성

        private void form1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form1 f1 = new Form1();
            f1.MdiParent = this;
            f1.Show();
        }

        private void form2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            f2.MdiParent = this;
            f2.Show();
            f2.WindowState = FormWindowState.Maximized;
        }


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

초단위 시간 경과 보이기  (0) 2015.05.12
로그인 창  (0) 2015.05.08
데이타베이스 라이브러리  (0) 2015.04.22
BackgroundWorker class  (0) 2015.03.02
텍스트 로그 파일 라이브러리 - 3  (0) 2015.02.21
posted by 따시쿵