2014년 1월 19일 일요일

닷넷, C#윈도우프로그램, 컨트롤 LabelTextBox 컨트롤의 확장, c#교육,닷넷교육[재직자무료교육/프로그래머교육/구로디지털IT교육,오라클/자바/닷넷/C#/iOS/안드로이드/아이폰교육]

닷넷, C#윈도우프로그램, 컨트롤 LabelTextBox 컨트롤의 확장, c#교육,닷넷교육[재직자무료교육/프로그래머교육/구로디지털IT교육,오라클/자바/닷넷/C#/iOS/안드로이드/아이폰교육]



닷넷, C#윈도우프로그램, 컨트롤 LabelTextBox 컨트롤의 확장, c#교육,닷넷교육, LabelTextBox 컨트롤의 확장

1. VS.NET에서 윈도우 응용 프로젝트를 만들고 LabelText 콘트롤을 폼위에 올려 놓자.

<>

2. 그런데 레이블이나 텍스트 박스의 텍스트를 변경이 불가능 하다. 이를 가능하게 하기 위해 LabelText와 TextboxText라는 두 속성을 추가하자.(LabelTextboxControl 프로젝트에 추가하자)
//레이블 텍스트를 수정 가능 하게 하기 위해
  public string LabelText
  {
   get
   {
    return lblLabelText.Text;
   }
   set
   {
    lblLabelText.Text = value;
    MoveControls();   //텍스트 박스의 크기 조절을 위해
   }
  }
 
  //텍스트 박스의 텍스트를 수정 가능 하게 하기 위해
  public string TextBoxText
  {
   get
   {
    return txtLabelText.Text;
   }
   set
   {
    txtLabelText.Text = value;
    MoveControls();
   }
  }

3. 이번에는 컨트롤이 제공 할 이벤트에 대해 생각해 보자. 이 컨트롤은 UserControl 클래스에서 파생된 것이므로 컨트롤에 필요한 기능들이 이미 완성 되어 있다. 그러나 몇몇 이벤트의 경우 손질이 필요 하며 예를 들어 KeyDown, KeyPress, KeyUp 이벤트들은 일반적인 이벤트와 동작 방식이 다르게 만들어야 한다. 왜냐하면 이 이벤트는 텍스트 박스안에서 키를 눌렀을 때 동작하는 것으로 생각하기 때문이다. 현재 상태로는 컨트롤 자체가 포커스를 가진 상태에서 사용자가 키를 눌렀을 때만 이 이벤트가 발생하며 또한 이벤트는 텍스트 박스가 아니라 이벤트 자체로 전달된다. 사용자의 기대를 충족 시키려면 이벤트가 텍스트 박스로 전달되게 한 후 텍스트 박스가 사용자에게 이벤트를 발생 시키도록 해야 한다. 우선 폼의 생성자에서 이벤트를 등록 하는 것부터 처리를 해 보도록 하자.
생성자에 3개의 이벤트를 등록하자.
//텍스트박스 키보드 이벤트들
   this.txtLabelText.KeyDown += new KeyEventHandler(this.txtLabelText_KeyDown);
   this.txtLabelText.KeyUp += new KeyEventHandler(this.txtLabelText_KeyUp);
   this.txtLabelText.KeyPress += new KeyPressEventHandler(this.txtLabelText_KeyPress);
 
4. 다음으로 세개의 이벤트 처리기를 추가 한다.
private void txtLabelText_KeyDown(object sender, KeyEventArgs e)
 {
  OnKeyDown(e);
 }
 private void txtLabelText_KeyUp(object sender, KeyEventArgs e)
 {
  OnKeyUp(e);
 }
 private void txtLabelText_KeyPress(object sender, KeyPressEventArgs e)
 {
  OnKeyPress(e);
 }
5. 커스텀 이벤트 처리기의 추가 : 기반 클래스에 존재하지 않는 이벤트를 만들려면 조금의  작업이 필요 하다. 예제에서는 Position 속성이 변할 때 발생 할 이벤트를 PositionChanged라는 이벤트를 추가해 보자. 커스텀 이벤트를 만들기 위해서는 세가지의 작업이 필요 하다.
- 이벤트에 등록된 메소드를 호출하는데 쓰이는 적절한 대리자가 있어야 한다.
- 사용자 이벤트 처리기를 등록 할 수 있게 하는 메소드가 필요 하다.
- 사용자가 등록 한 이벤트 처리기를 적절히 호출 해야 한다.
여기에서는 EventHandler라는 대리자(Delegate)를 이용하며 , 이벤트는 event 라는 키워드를 이용하여 선언 한다. 아래의 경우처럼 이벤트를 선언 한다.
public event System.EventHandler PositionChanged;
6. 다음으로는 Position 속성의 set 부분에서 등록된 이벤트가 존재하는지 확인 후 그 이벤트 처리 메소드를 불러 주는 코드를 추가 한다.
//속성(Position)을 추가하자
public PositionEnum Position
{
 get
 {
  return mPosition;
 }
 set
 {
  mPosition = value;
  MoveControls();
  //////////////////////////////////////
  if (PositionChanged != null)  //등록된 이벤트 처리기가 존재하는지?
  {
   //호출할 처리기 메소드의 목록을 얻는다.
   System.Delegate[] subscribers = PositionChanged.GetInvocationList();
   //루프를 돌면서 각 메소드를 호출 한다.
   foreach(System.EventHandler target in subscribers)
   {
    target(this, new EventArgs()); //메소드 호출
   }
  }
 }
}
7. 다음은 실제 만들어진 컨트롤을 이용하는 LabelTextBoxTest 프로젝트에서 생성자에서 추가한 콘트롤의 이벤트를 등록하고 이벤트 처리 메소드에서 실제 이벤트 처리를 하는 코드이다. Form1.cs 파일 전체의 소스 코드는 다음과 같다.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace LabelTextBoxTest
{
 public class Form1 : System.Windows.Forms.Form
 {
  private LabelTextControl.ctlLabelText ctlLabelText;
  private System.Windows.Forms.Button button1;
 
  private System.ComponentModel.Container components = null;
  public Form1()
  {  
   InitializeComponent();  
   ctlLabelText.PositionChanged += new EventHandler(this.ctlLabelText_PositionChanged);
  }
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }
  #region Windows Form 디자이너에서 생성한 코드
  /// <summary>
  /// 디자이너 지원에 필요한 메서드입니다.
  /// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
  /// < /summary>
  private void InitializeComponent()
  {
   this.ctlLabelText = new LabelTextControl.ctlLabelText();
   this.button1 = new System.Windows.Forms.Button();
   this.SuspendLayout();
   //
   // ctlLabelText
   //
   this.ctlLabelText.LabelText = "ctlLabelText";
   this.ctlLabelText.Location = new System.Drawing.Point(0, 0);
   this.ctlLabelText.Name = "ctlLabelText";
   this.ctlLabelText.Position = LabelTextControl.ctlLabelText.PositionEnum.Below;
   this.ctlLabelText.Size = new System.Drawing.Size(360, 38);
   this.ctlLabelText.TabIndex = 0;
   this.ctlLabelText.TextBoxMargin = 0;
   this.ctlLabelText.TextBoxText = "ㄷㄱㅈㄹㄷㅈ";
   //
   // button1
   //
   this.button1.Location = new System.Drawing.Point(104, 72);
   this.button1.Name = "button1";
   this.button1.Size = new System.Drawing.Size(232, 64);
   this.button1.TabIndex = 1;
   this.button1.Text = "PositionChanged Event 발생기";
   this.button1.Click += new System.EventHandler(this.button1_Click);
   //
   // Form1
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
   this.ClientSize = new System.Drawing.Size(448, 182);
   this.Controls.Add(this.button1);
   this.Controls.Add(this.ctlLabelText);
   this.Name = "Form1";
   this.Text = "Form1";
   this.ResumeLayout(false);
  }
  #endregion
  /// <summary>
  /// 해당 응용 프로그램의 주 진입점입니다.
  /// < /summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new Form1());
  }
  private void ctlLabelText_PositionChanged(object sender, EventArgs e)
  {
   MessageBox.Show("PositionChanged Event 발생...");
  }
  //버튼을 누르는 경우 PositionChanged Event를 발생 시키자.
  private void button1_Click(object sender, System.EventArgs e)
  {
   if (ctlLabelText.Position == LabelTextControl.ctlLabelText.PositionEnum.Below)
   {
    ctlLabelText.Position = LabelTextControl.ctlLabelText.PositionEnum.Right;
   }
   else
   {
    ctlLabelText.Position = LabelTextControl.ctlLabelText.PositionEnum.Below;
   }
  }
 }
}

8. 마지막으로 다음은 LabelTextControl의 전체 소스 이다.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace LabelTextControl
{
 /// <summary>
 /// UserControl1에 대한 요약 설명입니다.
 /// </summary>
 public class ctlLabelText : System.Windows.Forms.UserControl
 {
  private System.Windows.Forms.TextBox txtLabelText;
  public enum PositionEnum
  {
   Right,
   Below
  }
  //속성값을 실제로 저장 할 두 필드
  private PositionEnum mPosition = PositionEnum.Right;
  private int mTextBoxMargin = 0;
  private System.Windows.Forms.Label lblLabelText;
  //속성(Position)을 추가하자
  public PositionEnum Position
  {
   get
   {
    return mPosition;
   }
   set
   {
    mPosition = value;
    MoveControls();
    //////////////////////////////////////
    if (PositionChanged != null)  //등록된 이벤트 처리기가 존재하는지?
    {
     //호출할 처리기 메소드의 목록을 얻는다.
     System.Delegate[] subscribers = PositionChanged.GetInvocationList();
     //루프를 돌면서 각 메소드를 호출 한다.
     foreach(System.EventHandler target in subscribers)
     {
      target(this, new EventArgs()); //메소드 호출
     }
    }
   }
  }
  //속성(TextBoxMargin)을 추가하자
  public int TextBoxMargin
  {
   get
   {
    return mTextBoxMargin;
   }
   set
   {
    mTextBoxMargin = value;
    MoveControls();
   }
  }
 
  //레이블 텍스트를 수정 가능 하게 하기 위해
  public string LabelText
  {
   get
   {
    return lblLabelText.Text;
   }
   set
   {
    lblLabelText.Text = value;
    MoveControls();   //텍스트 박스의 크기 조절을 위해
   }
  }
 
  //텍스트 박스의 텍스트를 수정 가능 하게 하기 위해
  public string TextBoxText
  {
   get
   {
    return txtLabelText.Text;
   }
   set
   {
    txtLabelText.Text = value;
    MoveControls();
   }
  }

  /// <summary>
  /// 필수 디자이너 변수입니다.
  /// < /summary>
  private System.ComponentModel.Container components = null;
  public event System.EventHandler PositionChanged;
  public ctlLabelText()
  {
   // 이 호출은 Windows.Forms Form 디자이너에 필요합니다.
   InitializeComponent();
   // TODO: InitComponent를 호출한 다음 초기화 작업을 추가합니다.
   //SizeChanged 이벤트 추가
   this.SizeChanged += new System.EventHandler(this.OnSizeChanged);
   //Load 이벤트 처리기 등록
   this.Load += new EventHandler(this.OnLoad);
   //텍스트박스 키보드 이벤트들
   this.txtLabelText.KeyDown += new KeyEventHandler(this.txtLabelText_KeyDown);
   this.txtLabelText.KeyUp += new KeyEventHandler(this.txtLabelText_KeyUp);
   this.txtLabelText.KeyPress += new KeyPressEventHandler(this.txtLabelText_KeyPress);
  }
  private void txtLabelText_KeyDown(object sender, KeyEventArgs e)
  {
   OnKeyDown(e);
  }
  private void txtLabelText_KeyUp(object sender, KeyEventArgs e)
  {
   OnKeyUp(e);
  }
  private void txtLabelText_KeyPress(object sender, KeyPressEventArgs e)
  {
   OnKeyPress(e);
  }
  private void OnLoad(object sender, EventArgs e)
  {
   this.lblLabelText.Text = this.Name;
   //컨트롤의 높이를 설정
   this.Height = txtLabelText.Height + lblLabelText.Height;
   MoveControls();
  }
  private void OnSizeChanged(object sender, EventArgs e)
  {
   MoveControls();
  }

  private void MoveControls()
  {
   switch (mPosition)
   {
    case PositionEnum.Below:
     //텍스트 박스를 레이블의 아래에
     this.txtLabelText.Top = this.lblLabelText.Bottom;
     this.txtLabelText.Left = this.lblLabelText.Left;
     //텍스트박스의 너비를 컨트롤의 너비와 같게 만든다.
     this.txtLabelText.Width = this.Width;
     this.Height = this.txtLabelText.Height + this.lblLabelText.Height;
     break;
    case PositionEnum.Right:
     //텍스트 박스의 top과 레이블의 top을 같게
     this.txtLabelText.Top = this.lblLabelText.Top;
    
     //여백이 0이면 텍스트박스를 레이블의 바로 옆에 위치 시킨다.
     if (this.mTextBoxMargin == 0)
     {
      int width = this.Width - this.lblLabelText.Width - 3;
      this.txtLabelText.Left = this.lblLabelText.Right + 3;
      this.txtLabelText.Width = width;
     }
     else
     {
      this.txtLabelText.Left = this.mTextBoxMargin;
      this.txtLabelText.Width = this.Right - this.mTextBoxMargin;
     }
     break;
   }
  }
 
  /// <summary>
  /// 사용 중인 모든 리소스를 정리합니다.
  /// < /summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if( components != null )
     components.Dispose();
   }
   base.Dispose( disposing );
  }
  #region 구성 요소 디자이너에서 생성한 코드
  /// <summary>
  /// 디자이너 지원에 필요한 메서드입니다.
  /// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
  /// < /summary>
  private void InitializeComponent()
  {
   this.lblLabelText = new System.Windows.Forms.Label();
   this.txtLabelText = new System.Windows.Forms.TextBox();
   this.SuspendLayout();
   //
   // lblLabelText
   //
   this.lblLabelText.AutoSize = true;
   this.lblLabelText.Location = new System.Drawing.Point(0, 0);
   this.lblLabelText.Name = "lblLabelText";
   this.lblLabelText.Size = new System.Drawing.Size(36, 17);
   this.lblLabelText.TabIndex = 0;
   this.lblLabelText.Text = "Label";
   //
   // txtLabelText
   //
   this.txtLabelText.Location = new System.Drawing.Point(16, 48);
   this.txtLabelText.Name = "txtLabelText";
   this.txtLabelText.Size = new System.Drawing.Size(96, 21);
   this.txtLabelText.TabIndex = 1;
   this.txtLabelText.Text = "";
   //
   // ctlLabelText
   //
   this.Controls.Add(this.txtLabelText);
   this.Controls.Add(this.lblLabelText);
   this.Name = "ctlLabelText";
   this.ResumeLayout(false);
  }
  #endregion
 
 }
}

9. 이번에는 만들어진 User Control을 웹으로 올려보자. 아래의 html(UserControl.html)을 만들어 c:\inetpub\wwwroot 폴더에 두고 Browser에서 http://localhost/UserControl.html 이라고 하여 실행하자. (LabelTextControl.dll을 wwwroot 폴더에 복사 하자)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ks_c_5601-1987">
<title> Windows UserControl </title>
</head>
<body>
<object id=ctlLabelText
 classid="http://localhost/LabelTextControl.dll#LabelTextControl.ctlLabelText"
 width=300
 height=100
>
</object>
</body>
</html>
아래는 그 실행 화면이다.
<
 
 

  • 자바
  • 오라클/빅데이터
  • 아이폰/안드로이드
  • 닷넷/WPF
  • 표준웹/HTML5
  • 채용/취업무료교육
  • 초보자코스

  • 댓글 없음:

    댓글 쓰기