2008/C#2008. 10. 28. 15:05
영처리 교육 내용
메소드(Method)
Posted by penguindori
2008/C#2008. 10. 14. 16:51

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;
using System.Threading;

namespace Login
{
    public partial class LoginForm : Form
    {
        private int index = 12;
        private int index2 = 12;

        bool isSleep = false;

        Thread t1;

        System.Windows.Forms.Timer timer1;
        System.Windows.Forms.Timer timer2;


        public LoginForm()
        {
            InitializeComponent();       
           
        }

        private void LoginForm_Load(object sender, EventArgs e)
        {
            axWebBrowser1.Navigate(Application.StartupPath + @"\0_main.swf");

            timer1 = new System.Windows.Forms.Timer();
            timer2 = new System.Windows.Forms.Timer();

            timer1.Tick += new EventHandler(timer1_Tick);
            timer2.Tick += new EventHandler(timer2_Tick);

            timer1.Interval = 10;
            timer2.Interval = 10;

            timer1.Enabled =true;
            timer2.Enabled =true;   
        }

        void timer2_Tick(object sender, EventArgs e)
        {
            index2++;

            if (index2 == 60) index2 = 12;

            button2.Location = new Point(index2, 183);


        }

        void timer1_Tick(object sender, EventArgs e)
        {
            // isSleep(bool)변수가 false일때만 실행

            if (!isSleep)
            {

                index++;

 

                // index가 30이면 isSleep을 true로 바꾸고

                // 쓰레드를 실행합니다.

                if (index == 30)
                {

                    isSleep = true;

                    t1 = new Thread(new ThreadStart(TimerStart));

                    t1.Start();

                }

 

                // index가 60이면 12로(앞으로) 되돌리고 애니메이션~!

                if (index == 60) index = 12;

                button2.Location = new Point(index, 12);

            }


        }

        private void TimerStart()
        {

            // 간단하게 0.5초를 쉬고 isSleep변수값을 바꿉니다.

            Thread.Sleep(500);

            isSleep = false;

      }
      
    }
}

Posted by penguindori
2008/C#2008. 10. 13. 15:10

[C#] Round Rectangle 처리하기

사용자 삽입 이미지

RoundPanel 클래스를 제작했습니다.
Panel을 상속해서 처리 했습니다.

Round 하는 코드는 아래의 코드를 참조 하시면 됩니다.       

        static public GraphicsPath GetRoundedRectPath(Rectangle rect, int radius)
        {
            int diameter = 2 * radius;
            Rectangle arcRect =
                new Rectangle(rect.Location, new Size(diameter, diameter));

            GraphicsPath path = new GraphicsPath();

            path.AddArc(arcRect, 180, 90);

            arcRect.X = rect.Right - diameter;
            path.AddArc(arcRect, 270, 90);

            arcRect.Y = rect.Bottom - diameter;
            path.AddArc(arcRect, 0, 90);

            arcRect.X = rect.Left;
            path.AddArc(arcRect, 90, 90);

            path.CloseFigure();

            return path;
        }

Panel 함수에서 드로잉 하는 코드 입니다.
       

        private void roundPanel_title_Paint(object sender, PaintEventArgs e)
        {
            RoundPanel panel = (RoundPanel)sender;

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;

            int width = panel.ClientRectangle.Width;
            int height = panel.ClientRectangle.Height;

            Rectangle rect = new Rectangle(0, 0, width-1, height-1);
            using (GraphicsPath path = RoundPanel.GetRoundedRectPath(rect, 8))
            {
                using (Brush brush = new LinearGradientBrush(
                                            new Rectangle(0, 0, panel.ClientRectangle.Width, panel.ClientRectangle.Height),
                                            Color.FromArgb(panel.Opcity, 102, 102, 102),
                                            Color.FromArgb(panel.Opcity, 0, 0, 0),
                                            90.0f))
                {
                    //graphics.FillRectangle(brush, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
                    g.FillPath(brush, path);
                }

                //g.FillPath(Brushes.Yellow, path);
                Pen pen = new Pen(Color.FromArgb(panel.Opcity, 255, 255, 255));
                g.DrawPath(pen, path);
            }
        }

이걸 처리 하다 보면 화면을 전환 하거나 리프레쉬할때 플리커 현상이 생기기도 합니다.
이걸 해결하기 위해서 RoundPanel에 더블버퍼링 처리 코드를 추가 했습니다.

        public RoundPanel()
        {
            ...
            this.SetStyle(  ControlStyles.UserPaint |
                            ControlStyles.AllPaintingInWmPaint |
                            ControlStyles.DoubleBuffer, true);
        }

출처 : http://iamgsi.com/374
Posted by penguindori
2008/C#2008. 10. 9. 16:18



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

namespace Login
{
    public partial class Form2 : Form
    {
        OracleConnection oConn;
        OracleCommand oComm;
        OracleParameter[] oPar;

        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            oConn = new OracleConnection("Data Source=mi;User ID=midas;Password=midas123");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            StringBuilder sbSql = new StringBuilder();
            oConn.Open();

            try
            {
                sbSql.Append(" select userid,userpwd,username  ");
                sbSql.Append("  from midas_user ");
                sbSql.Append("  WHERE userid  = :userid ");
                sbSql.Append("  AND userpwd  = :userpwd ");

                oPar = new OracleParameter[2];
                oPar[0] = new OracleParameter(":userid", textBox1.Text);
                oPar[1] = new OracleParameter(":userpwd", textBox2.Text);

                oComm = new OracleCommand(sbSql.ToString(), oConn);

                oComm.Parameters.Add(oPar[0]);
                oComm.Parameters.Add(oPar[1]);

                OracleDataReader dr = oComm.ExecuteReader(CommandBehavior.CloseConnection);
                oComm.Parameters.Clear();

                dr.Read();

                MessageBox.Show(dr["USERNAME"].ToString());
                MessageBox.Show(dr["userid"].ToString());
              

            }
            catch (Exception ex) { string ok = ex.Message.ToString(); }


        }
    }
}

Posted by penguindori
2008/C#2008. 10. 1. 09:44
Posted by penguindori
2008/C#2008. 8. 1. 10:50
Posted by penguindori
2008/C#2008. 8. 1. 09:04

파일 읽어 들이기 (라인수 계산)

using (FileStream fs = new FileStream(@"C:\Windows\Help\tvt_help.js", FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] buffer = new byte[64000];
    int read = 0, count = 0;

    while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
    {
        for (int i = 0; i < read; i++)
            count += (buffer[i].Equals((byte)'\n') ? 1 : 0);
    }
}

---------------------------

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace Position_Chase
{

    class clsLog
    {
       
        private const string FILE_NAME = @"C:\Documents and Settings\Administrator\바탕 화면\보고자료\LogFile\Log_File.txt";
        FileStream mstm_Log;

        private void FileOpen()
        {
            //FileStream stm = new FileStream(@"C:\tmp\log.txt", FileMode.Create);
            //mstm_Log = new FileStream(FILE_NAME, FileMode.Create);
            mstm_Log = new FileStream(FILE_NAME, FileMode.Append);
        }

        public void WriteTextMsg(string pMsg)
        {
            byte[] myB;
            string lp_LogMsg;

            FileOpen();

            lp_LogMsg = pMsg + '\t' + '\n';
            myB = Encoding.GetEncoding("euc-kr").GetBytes(lp_LogMsg);

            mstm_Log.Write(myB, 0, myB.Length);
            FileClose();
        }

        private void FileClose()
        {
            mstm_Log.Close();
        }
    }
}

Posted by penguindori
2008/C#2008. 7. 25. 08:58

2. 리플렉션의 초석: System.Type 클래스

System.Type 클래스는 프레임워크 상에 존재하는 모든 종류의 개체들의 형식에 관한 정보를 대변하는 도우미 클래스입니다. 형식을 나타내는 요소로는, 그 자신이 가지고 있는 멤버 메서드들, 멤버 프로퍼티들, 멤버 필드들, 멤버 이벤트들 모두가 포함됩니다. 그리고 클래스 자신의 시그니처 (이름과 위치하는 네임스페이스)와 부모 클래스, 구현하는 인터페이스들, 특유의 속성들도 형식에 포함되는 것입니다.

위에서 언급한 모든 정보들은 메타 데이터라는 것으로 표현됩니다. 메타 데이터를 기초로 하여 각종 형변환과 리플렉션과 관련된 작업들을 처리하는 것으로 보면 맞습니다. 사실 역 어셈블리가 가능하여 코드 자체의 보안이 (런타임 상의 보안이 아니라) 매우 취약하다고 하는 것도 여기에서 발단이 된 것입니다. 네이티브 런타임에서는 RTTI (Run-Time Type Information) 라는 것으로 비슷한 기능을 제공하기도 하지만 닷넷의 리플렉션에는 훨씬 못미치는 수준의 기능입니다.

지금 설명하려는 System.Type 클래스는 위에 나열된 모든 정보를 자유자재로 탐색할 수 있도록 도와주는 클래스입니다. 하지만 System.Type 클래스 자체의 생성자를 직접 호출할 수는 없게 되어있습니다. 바로 추상 클래스이기 떄문인데, 형식을 조회하려면 생성자가 아닌 방법을 사용해야 합니다.

2.1. 리플렉션을 시작하기 전에 알아두어야 할 것

조사하고자 하는 클래스를 컴파일러가 컴파일을 시도할 당시에 알고 있는가, 모르고 있는가에 따라서 Type 클래스를 생성하는 방법이 크게 달라집니다. 즉, 컴파일러에 -r 옵션을 사용하여 어떤 어셈블리를 지정하였거나 코드 파일 중에 클래스가 정의되어있었다면 흔히 사용하던 언어 구문을 사용할 수 있습니다. 하지만 컴파일러에 일체의 지시를 내린적이 없었던 상태에서 어떤 어셈블리 파일을 직접 열어서 활용할 경우에는 언어 구문이 아닌 System.Reflection의 API들을 활용하지 않으면 안됩니다.

하지만 예외 사항은 있습니다. Visual Basic은 언어의 이미지와 특성 상 "편리성"에 초점을 두고 있다보니 이런 점에 있어서도 자동화를 시도합니다. 따라서, 컴파일러에 지정한 적이 없던 정보도 동적으로 분석하여 언어 구문으로 리플렉션을 사용할 수 있도록 해줍니다.

그리고 강의 중에 나오는 용어로 어셈블리라는 것이 있는데, 혼동하지 마십시오. 이것은 MASM 등에서 사용하는 어셈블리 언어를 의미하는 것이 아닙니다. 어셈블리는 프레임워크에서 다수의 네임스페이스와 다수의 개체를 묶어두는 단위로 이해하시면 되겠습니다.

2.2. typeof() 연산자

typeof() 연산자는 Type 클래스를 컴파일러가 이미 알고 있는 클래스로부터 추출할 수 있도록 도와주는 연산자입니다. 사용 방법은 무척 간단합니다. typeof() 연산자의 괄호 안에는 흔히 생각할 수 있는 형식의 이름을 지정하면 됩니다. (예: System.String, System.Object, MyNameSpace.MyClass, ...)

    Type myType = typeof(System.String);

    Console.WriteLine(myType.ToString());

2.3. GetType() 메서드

GetType() 메서드는 typeof() 연산자로는 찾을 수 없는 개체의 형식 정보를 조회할 수 있도록 도와주는 메서드입니다. System.Object (프레임워크 상의 최상위 부모 클래스)에 정의된 상태로 하위 클래스가 구현하는 형태로 되어있으므로 NULL 참조가 아닌 모든 개체가 가지고 있는 메서드입니다. 혹, 직접 구현한 적이 없었다 할지라도 프레임워크가 자동으로 현재 클래스에 대한 메타데이터를 대변하는 Type 클래스를 반환합니다.

    public class ExposedClass

    {

      public void ExposedMethod(object anyThing)

      {

         if(anyThing != null)

         {

            Type myType = anyThing.GetType();

            Console.WriteLine(myType.ToString());

         }

      }

    }

위의 2.3 섹션의 코드를 활용해 보시고 싶으시다면 두 개의 어셈블리를 만드셔야 합니다. 하나는 클래스 라이브러리 (DLL)로 위의 코드를 포함하는 파일이어야 하고, 또 하나는 실행 파일로 해당 클래스 라이브러리를 링크하고 있고 다음의 코드가 포함되어야 합니다.

    public class MyClass

    {

      public int myType = 1;

    }

    public class MainClass

    {

      [STAThread()]

      public static void Main(string[] arguments)

      {

         ExposedClass.ExposedMethod(new MyClass());

      }

    }

참고: ExposedMethod 자체는 static이어도 문제는 없습니다. 어떤 Object를 인수로 받을 요량으로 만들어진것이니까요. 하지만 저 ExposedMethod가 static이 되게 된다면 "this" 키워드는 사용을 못하겠지요. 이런 차이점이 있습니다.

Posted by penguindori
2008/C#2008. 7. 25. 08:57

2.2. System.Object의 활용

프레임워크에서 정의되는 모든 개체들의 최상위 클래스는 반드시 System.Object입니다. 심지어는 구체적인 형식을 알 수 없는 개체마저도 System.Object로 형변환 처리가 되는 것도 정당합니다. 이럴 경우 형식의 모호성이라는 문제점이 발생합니다. 즉, 전달받은 개체가 구체적으로 어떤 개체인지 알 길이 없을 수도 있으며 본래의 형식으로 복원하는 것이 불가능해질 수도 있다는 것입니다.

앞의 경우와는 달리 System.Object로의 형변환은 매우 극단적으로 추상화된 형변환이기 때문에 이러한 문제점이 발생하게 됩니다. 하지만 반드시 심각한 문제점인 것만은 아닙니다. 오히려 이것이 리플렉션이 왜 중요한지 알려주는 중요한 연습 문제가 되는 것입니다.

오늘 강좌에서는 언어 구문을 활용한 원시적인 리플렉션을 사용해 보도록 하겠습니다. 바로 is 연산자입니다. is 연산자의 문법 구조는 다음과 같습니다.

[생성된 개체명] is [확인하고자 하는 형식명];

is 연산자로 계산된 값은 System.Boolean 형식으로 반환됩니다. (즉, True 또는 False입니다.) is 연산자가 예외를 일으키지 않고 True 또는 False를 반환하려면 개체가 null이 아니어야 하고 확인하고자 하는 형식명이 컴파일러가 인식할 수 있는 형식 이름이어야 한다는 것, 그리고 생성된 개체가 해당 형식을 직접 구현했거나 해당 형식이 생성된 개체 형식보다는 추상 형식이어야 한다는 것입니다.

이것을 사용하여 예상할 수 있는 형식 몇가지를 검사해 보는 것이 가능합니다. 하지만 여기에는 몇 가지 한계가 있습니다.

  • 찾고자 하는 형식이 상속을 활용한다면 정확히 들어맞는 형식임을 보장할 수는 없게 된다.
  • 찾고자 하는 형식의 수가 많다면 굉장히 많은 수의 조건문이나 3항 연산자를 중첩 사용해야 한다.
  • 찾고자 하는 형식이 컴파일러가 인지할 수 있는 이름 목록 가운데 없으면 이 방법은 사용할 수 없다.

이런 문제점을 해결하기 위해서 몇가지 방법을 더 찾아야 하겠습니다.

오늘 강좌는 우선 여기까지 쓰도록 하겠습니다. 다음 강좌를 보시기 전까지 과제가 하나 있습니다. 과연 위에서 언급했던 문제점을 해결하기 위하여 어떤 방법을 어떻게 활용하여야 할지에 대해서 진지하게 고민해 보십시오. 다음 강좌에서 그 답을 속시원하게 알려드리도록 하겠습니다. ^^

* 지난번 문제에 관하여: is 연산자를 사용하는 방법으로 아주 원시적인 리플렉션이 가능하다고 말씀드린 적이 있었습니다. 하지만 이것만으로는 리플렉션의 전부를 살펴볼 수 없다고 말씀드린 적이 있었습니다. 그에 대한 해답은 앞으로 올라오는 강좌에서 적절한 내용을 활용하시는 것입니다.


Posted by penguindori
2008/C#2008. 7. 25. 08:55

1. 리플렉션의 의미와 그 필요성

리플렉션은 사전적 의미인 "어떤 사물을 비추어 보다"와 동일한 기능상 의미를 지닙니다. 즉, 리플렉션은 코드 구문 상에서는 사용할 수 없는 제 3의 형식 개체 (클래스, 대리자, 나열 상수, 구조체, 인터페이스 등)를 동적으로 다루는 기술을 의미합니다.

리플렉션은 그닥 활용하기 쉽지도 않을 뿐더러 활용할 만한 곳을 찾기도 어렵습니다. 따라서 사람들이 잘 뒤져보지 않는 기술이기도 합니다. 하지만 리플렉션을 빼면 닷넷은 이빨빠진 호랑이, 더 심한 표현을 쓰면 뼈대 없는 건물로 전락하고야 맙니다. 그만큼 리플렉션을 활용하는 곳이 많다는 것을 강조하고 싶습니다.

2. 쉬운 리플렉션부터 살펴봅시다!

리플렉션에 대해서는 차근차근히 수순을 밟아나가는 것이 이해에 도움이 됩니다. 가장 쉬운 리플렉션부터 공략해 봅시다.

사용하는 디자인 패턴에 따라서 상속을 받는 자식 클래스를 만드는 디자인 패턴을 사용하는 경우도 가끔있습니다. 이 경우 리플렉션의 가장 대표적인 예를 시험해 볼 수 있습니다. 한가지 실험을 해봅시다.

배열을 가지고 우리는 두 가지의 리플렉션을 시험해 볼 수 있겠습니다. 프레임워크 (주: CLS 규격을 구현하는 프레임워크의 수가 많기 때문에 특정 프레임워크를 지칭할 수는 없습니다. 따라서 Microsoft .NET, Rotor, Mono, DotGNU 등을 한꺼번에 아울러 프레임워크라고 표현하겠습니다.)는 언어 문법에서 사용하는 배열의 인스턴스를 System.Array 클래스를 기초해서 동적으로 생성합니다.

System.Array 클래스는 배열에 관한 기본적인 기능을 정의한 클래스이지만 System.Array 클래스의 생성자를 우리가 직접 호출할 수는 없습니다. 그리고 CLS 규격에서 명시하였던 바와 같이 System.Object가 System.Array에 대한 상위 클래스임은 변함이 없습니다. 이와 같은 전제 조건하에서 시험을 해보겠습니다.

2.1. System.Array의 활용

배열은 가지고 있는 원소 (Atom/Element)의 형식에 따라서 각각 다른 배열로 취급되며 배열 vs. 배열 단위의 형변환은 비록 두 배열의 원소의 형식 관계가 상속 관계라고 할지라도 기본적으로는 허용되지 않습니다. 하지만 "배열" 이라는 특성은 원소의 형식과는 관계없이 공통적인 것입니다. 우리는 각기 다른 원소 형식을 가지는 배열을 System.Array 라는 클래스로 동일하게 취급할 수 있습니다. 어떤 형태의 원소 형식을 가지는 배열이 되었던간에 상관없이 말입니다.

Array test = new string [5];
test.SetValue("Test", 2);
string[] test2 = (string[])test;
Console.WriteLine(test2[2]);

기본적으로 System.Array는 추상 클래스이므로 System.Array의 생성자는 사용할 수 없습니다. 하지만 어떻게 인스턴스가 만들어지게 된 것일까요? 명시되어 있지는 않지만 컴파일러 내부적으로는 또 하나의 클래스를 System.Array로부터 동적으로 파생시켰다고 가정하고 다루게 됩니다. 다시 말하여 test 라는 인스턴스는 파생된 클래스의 멤버들 가운데서 System.Array의 멤버들과 일치하는 멤버들만을 가르키게 됩니다.

Array 클래스에 값을 대입하기 위해서 SetValue 메서드를 호출합니다. Array 클래스에서는 인덱서 연산자를 구현하지 않으므로 원시 함수인 SetValue 메서드를 직접 호출하게 되었습니다. 이 상태에서 string[] 클래스로 형변환을 다시 시도합니다. 그리고 값을 확인해 봅니다. Test 라는 문자열이 그대로 유지된 것을 확인하실 수 있습니다.

위의 예에서 중요한 원리 하나를 확인할 수 있습니다. 첫 번째는 형변환에는 방향성이 존재한다는 것입니다. 형식의 변환이 추상화될 수록 (위로 갈수록) 가급적 공통 부분으로만 표현됩니다. 반대로 형식의 변환이 구체화될 수록 (아래로 갈수록) 가급적 상세하게 표현됩니다.

데브피아 남정현님

Posted by penguindori