728x90

C#에서 폼의 크기를 고정하고 싶을 경우에




블로그 이미지

Link2Me

,
728x90

이벤트 개념을 잡고 이벤트를 만들어서 코드 작성을 하면 훨씬 더 좋을거 같아서 C#이 자동으로 만들어주는 이벤트를 분석해보기로 했다.



button1 을 더블 클릭하면 자동으로 코드가 만들어진다.


private void button1_Click(object sender, EventArgs e)
{

}


모든 이벤트는 이벤트를 발생시킨 객체(object) 와 해당 이벤트의 정보를 가지는 이벤트 객체로 구성되는 두개의 인자를 가진다.


Designer.cs 파일에도 자동으로 만들어진 코드가 있다.

this.button1.Click += new System.EventHandler(this.button1_Click);


이걸 분석해보자.

마우스 우클릭을 눌러서 정의 피킹(Alt + F12)을 해보면 연결된 정의가 뭔지 나온다.

이걸 도식화해서 그려봤다.



결국 .NET 기본 클래스 라이브러리에 존재하는 미리 정의된 delegate 타입을 사용한 것이다.


this.btnTest.Click += new System.EventHandler(this.MyHandler);

명칭을 변경해주면

자동으로

private void MyHandler(object sender, EventArgs e)
{

}

로 변경된다.


이벤트를 직접 만들어서 사용하려면 어떻게 해야 할까?

지정자 event event-delegate event_name;

이라는 걸 알 수 있다.

이벤트(event)는 어떤 사건이 발생했을 때 호출되어야 하는 메서드의 목록이다.

이벤트는 내부적으로 delegate로 구현되므로 이벤트를 선언하기 전에 delegate를 먼저 선언해두어야 한다.

delegate는 이벤트가 어떤 인수를 전달하는지를 정의하며, 이벤트 핸들러의 형태를 규정한다.


http://link2me.tistory.com/853 게시물의 delegate 개념 이해하기 와 http://link2me.tistory.com/856 폼간 데이터 전송 게시물에 보면 delegate 를 활용한 이벤트가 나온다.


영문 대신에 이해하기 쉽게 우리말로 적어보면

의 과정으로 동작되는 걸 알 수 있다.

- 하나의 delegate 로 여러개의 event 를 생성할 수 있다.

- 실행메서드명은 delegate 에서 정의한 이벤트핸들러 명칭 대신 다른 명칭을 사용하고 시그너처(string data)는 동일하다.


타 블로그에 작성된 글을 보고 코드를 만들어서 실행은 해봤는데 명확하게 이해가 안되었었다.

좀 더 분석을 해보니 이런 흐름이라는 걸 어렴풋이 이해하게 되었고 다음부터는 이벤트 만들어서 활용하는 걸 어렵지 않게 할 수 있을 거 같다.


빠른 개념 이해는 역시 파워포인트를 활용해서 그림으로 도식화해보는 것이다.


개념 이해가 된 상태에서 http://www.csharpstudy.com/CSharp/CSharp-delegate3.aspx 게시물을 보면 좀 더 이해하는데 도움이 된다.


델리게이트와 이벤트 핸들러에 대한 이해를 완벽하게 하려면 위 그림 가지고는 부족하다.

같은 폼내에서 이벤트 핸들러 처리하는 것은 별로 어렵지 않다.

다른 폼으로 값을 전달하기 위해서는 어떻게 해야 할까?

다른 폼에서 값을 전달받기 위해서는 어떻게 해야 할까?


그 해답은 http://link2me.tistory.com/928

블로그 이미지

Link2Me

,
728x90

delegate(대리자)는 참조형으로 메서드를 대신 호출하는 역할을 한다.

지정자 delegate 리턴타입 이름(인수목록);

delegate int Mydelegate(int a, int b) ;  // delegate 선언

delegate 는 타입이므로 그 자체만으로 메서드를 가리킬 수는 없으며,

인스턴스를 생성한 후 메서드를 가리키도록 초기화해야 한다.

(** 메소드(Method)는 하나의 실행 가능한 코드의 블럭( { } )으로 정의할 수 있으며, 함수라고 부르기도 한다.)

이 delegate 의 입력 파라미터와 반환값의 타입은 서로 같아야 한다.

입력 파라미터로 정수형(int) a, b 를 받아서 그 결과를 정수형(int)로 반환해주는 형태로 delegate를 정의한다.

delegate 만 빼면 메소드와 같다.


// delegate 와 연결할 함수 선언

class Calculator
{
    public int Plus(int a, int b)
    {
        return a + b;
    }

    public static int Minus(int a, int b)
    {
        return a - b;
    }


    public int Multiply(int a, int b)
    {
        return a * b;
    }

}


Calculator cal = new Calculator(); // 클래스형인 cal 개체 초기화(메모리 할당)

Mydelegate callback;  // delegate 타입의 객체를 생성(인스턴스 참조변수 선언)

// delegate 에 실제 함수를 할당해준다.

callback = new Mydelegate(cal.Plus);  //  delegate에 Plus() 메소드 주소 바인딩
Console.WriteLine(callback(3, 4));  // delegate 수행

Console.WriteLine("원래 함수 이용한 값 더하기 " + cal.Plus(3, 4));


// delegate 인스턴스 참조변수 선언 및 delegate에 정적 메소드인 Minus() 메소드 바인딩

Mydelegate mysub = new Mydelegate(Calculator.Minus);  // delegate 수행
Console.WriteLine("두 값의 차이는 " + mysub(11, 5) + " 입니다");


Mydelegate multiply = cal.Multiply;  // new Mydelegate(cal.Multiply) 의 축약형

Console.WriteLine("두 값의 곱셈은 " + multiply(3, 4) + " 입니다");


델리게이트(delegate) 는

- 정적, 비정적 메소드 구분없이 사용

- 특정 틀래스에 소속되지 않음

- 타입만 일치하고 접근만 허용되면 어떤 메소드도 접근 가능


위 코드를 직접 실행해 볼 수 있는 소스코드이다.


delegate-01.zip


Ctrl + F5 키를 누르면 콘솔창에 값이 표시된다.

아니면 마지막 줄에 Console.ReadLine(); 을 추가해주고 F5 키를 눌러도 된다.


블로그 이미지

Link2Me

,
728x90

C# 델리게이트를 어떻게 사용해야 하는지 예제를 통해서 살펴보자.

그동안 델레게이트를 어떻게 처리해야 할지 개념이 잡힐 듯 잡힐 듯 하면서도 잘 잡히지 않았는데 구글링하다가 발견한 예제를 통해서 폼간에 값을 어떻게 전달해야 하는지 확실하게 감을 좀 잡은거 같다.


1. 메인 폼(MainForm)에서 자식폼으로 값을 전달해야 할 경우

2. 자식폼에서 메인폼으로 값을 전달해야 할 경우


세가지 경우만 알면 폼간에 값을 넘기는 것에 대한 이해는 다 했다고 볼 수 있다.

ㅇ 델리게이트(delegate)는 Class 밖에 선언한다.

ㅇ 델리게이트 타입과 실행메서드 타입은 동일 해야 한다.

ㅇ 이벤트는 값을 전달하는 쪽에서 선언해야 한다.



namespace DelegatesDemo
{
    public delegate void DataPushEventHandler(string value);  // 메인폼 --> 자식폼 으로 값 전달 델리게이트
    public delegate void DataGetEventHandler(string item); // 자식폼 --> 메인폼으로 값 전달 델리게이트

    public partial class MainForm : Form
    {
        // 값을 보내는 곳의 Form 쪽에 이벤트 선언해야 한다
        public DataPushEventHandler DataSendEvent

        public MainForm()
        {
            InitializeComponent();
        }


1. 메인 폼(MainForm)에서 자식폼으로 값을 전달해야 할 경우



=== 메인폼 코드 ===

private void btnOpenFrm1_Click(object sender, EventArgs e)
{
    // 같은 폼이 2개 이상 뜨지 않도록 처리하는 코드
    foreach (Form openForm in Application.OpenForms)
    {
        if (openForm.Name == "ChildForm1")
        {
            if (openForm.WindowState == FormWindowState.Minimized)
            {
                openForm.WindowState = FormWindowState.Normal;
            }
            openForm.Activate();
            return;
        }
    }

    ChildForm1 frm1 = new ChildForm1();
    this.DataSendEvent += new DataPushEventHandler(frm1.SetActionValue1);
    frm1.StartPosition = FormStartPosition.Manual;
    frm1.Location = new Point(this.Location.X + this.Width + 5, this.Location.Y);
    frm1.Show();
}

private void txtParam_TextChanged(object sender, EventArgs e)
{
    // 텍스트박스에 값을 입력하면 실시간적으로 자식폼으로 값이 전달됨
    DataSendEvent(txtParam.Text);
}

private void btnOpenFrm2_Click(object sender, EventArgs e)
{
    // 같은 폼이 2개 이상 뜨지 않도록 처리하는 코드
    foreach (Form openForm in Application.OpenForms)
    {
        if (openForm.Name == "ChildForm2")
        {
            if (openForm.WindowState == FormWindowState.Minimized)
            {
                openForm.WindowState = FormWindowState.Normal;
            }
            openForm.Activate();
            return;
        }
    }

    ChildForm2 frm2 = new ChildForm2();
    this.DataSendEvent += new DataPushEventHandler(frm2.SetActionValue2);
    frm2.StartPosition = FormStartPosition.Manual;
    frm2.Location = new Point(this.Location.X + this.Width + 5, this.Location.Y + 100);
    frm2.Show();
}


=== 자식폼 코드 ===

public void SetActionValue1(string param)
{
    txtParam.Text = param;
}


2. 자식폼에서 메인폼으로 값을 전달해야 할 경우



=== 자식폼 코드 ===

namespace DelegatesDemo
{
    public partial class FormDialog : Form
    {
        // Declare delagete callback function
        // 값을 보내는 곳의 Form 쪽에 이벤트 선언해야 한다
        public DataGetEventHandler DataSendEvent;

        public FormDialog()
        {
            InitializeComponent();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (textBoxItem.Text.Length == 0)
            {
                MessageBox.Show("값이 입력되지 않았습니다");
                return;
            }
            else
            {
                DataSendEvent(textBoxItem.Text);
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}


=== 메인폼 코드 ===

private void btnScenario2_Click(object sender, EventArgs e)
{
    // 같은 폼이 2개 이상 뜨지 않도록 처리하는 코드
    foreach (Form openForm in Application.OpenForms)
    {
        if (openForm.Name == "FormDialog")
        {
            if (openForm.WindowState == FormWindowState.Minimized)
            {
                openForm.WindowState = FormWindowState.Normal;
            }
            openForm.Activate();
            return;
        }
    }

    FormDialog frm3 = new FormDialog();
    frm3.DataSendEvent = new DataGetEventHandler(this.Form3DataAction);
    frm3.StartPosition = FormStartPosition.Manual;
    frm3.Location = new Point(this.Location.X + this.Width + 5, this.Location.Y + 250);
    frm3.Show();
}

private void Form3DataAction(string item)
{
    listBox.Items.Add(item);
}


예제에 사용된 소스코드가 포함된 자료


DelegatesDemo.zip


본 예제는 http://www.c-sharpcorner.com/uploadfile/mosessaur/winformsdelegates09042006094826am/winformsdelegates.aspx 에서 받은 파일을 더 이해하기 쉽게 파일을 수정했다.

원본 예제는 파일 창 중복체크도 없고, 창을 띄울 때 Location 설정하는 것이 반영되지 않았다.

명칭은 변경해서 이해하기 쉽게 정리를 했다.



블로그 이미지

Link2Me

,
728x90

C# 에서 자식폼을 띄울 때 MainForm 의 위치가 변경되도 항상 MainForm 위에 뜨도록 하는 방법을 알아봤다.


자식폼의 위치를 고려하지 않고 폼을 띄우는 방법은

Form2 frm2 = new Form2();

frm2.Show();

라고 하면 된다.


메인폼(MainForm) 의 위치가 변경되더라도 자식폼이 메인폼의 위에 뜨게 하고  싶었다.

메인폼을 종료하고 나서 다음에 실행할 때 메인폼의 시작위치를 마지막 종료시점의 위치를 기억하게 하는 방법은

http://link2me.tistory.com/863 게시글에 설명되어 있다.


자식폼을 띄울 때 메인폼 위에 위치하도록 하는 방법은

Point parentPoint = this.Location;
Form2 frm2 = new Form2();
frm2.StartPosition = FormStartPosition.Manual;  // 폼의 위치가 Location 의 속성에 의해서 결정
frm2.Location = new Point(parentPoint.X + 100, parentPoint.Y + 100);
frm2.Show();


메인폼의 위치, 높이, 너비를 가지고 자식폼을 띄울때 같이 반영해주면 된다.

Point parentPoint = this.Location; // 메인폼(현재폼)의 위치
int parentHeight = this.Height; // 메인폼
(현재폼)의 높이
int parentWidth = this.Width; // 메인폼
(현재폼)의 너비


자식폼의 위치를 메인폼의 우측에 위치하게 하고 싶다고 하면

frm2.Location = new Point(parentPoint.X + int parentWidth, parentPoint.Y);

로 해주면 된다.


화면사이즈까지 고려해서 화면내에서 보이게 하려고 하면 모니터 사이즈를 알아내야 한다.

int screenWidth = Screen.PrimaryScreen.WorkingArea.Width;

int screenHeight = Screen.PrimaryScreen.WorkingArea.Height;
MessageBox.Show(screenWidth.ToString() + " X " + screenHeight.ToString());

내 모니터의 크기를 알아보니 1920 X 1040 으로 나온다.


int screenWidth = Screen.PrimaryScreen.Bounds.Width; //모니터 스크린 가로크기
int screenHeight = Screen.PrimaryScreen.Bounds.Height; //모니터 스크린 세로크기
이걸로 확인해보면 1920 X 1080 으로 나온다.

WorkingArea 와 Bounds 차이다.


가 차치하는 공간은 작업공간이 아니라고 계산을 한 것이다.


듀얼모니터의 가로크기와 세로크기는

int screenWidth = System.Windows.Forms.SystemInformation.VirtualScreen.Width; //듀얼 모니터 가로 크기
int screenHeight = System.Windows.Forms.SystemInformation.VirtualScreen.Height; //듀얼 모니터 세로 크기
로 알아낼 수 있다.


모니터 크기를 알아냈다면, 이제 자식폼의 높이와 너비도 알아내야 한다.

int childWidth = frm2.Width;
int childHeight = frm2.Height;


이제 parantPoint.X + parentWidth + childWidth > screenHeight 가 넘어가는 조건이 발생할 때에는 X좌표의 값을 어떻게 주겠다. 마찬가지로 Y좌표에 대해서도 어떻게 주겠다고 계산을 해서 if else 조건문을 적어서 표시되도록 하면 된다.


** https://msdn.microsoft.com/ko-kr/library/system.windows.forms.formstartposition(v=vs.110).aspx

FormStartPosition 설명이 나와있다.

구글링해서 찾은 자료도 적어놓는다. 아래 두 코드는 서로 내용이 동일하다.

Form2 frm2 = new Form2();
frm2.StartPosition = FormStartPosition.CenterParent;
frm2.Show(this);

Form2 frm2 = new Form2();
frm2.StartPosition = FormStartPosition.Manual;
frm2.Location = new Point(this.ClientSize.Width / 2, this.ClientSize.Height / 2);
frm2.Show();

블로그 이미지

Link2Me

,
728x90

C# 에서 자식창을 띄울때 창의 마지막 크기와 위치를 저장하고 싶을 때


먼저, 솔루션 탐색기에서 Properties 를 선택하고 Settings.settings 를 더블 클릭한다.



아래 그림처럼 이름과 형식을 설정해준다.



이제 이벤트를 생성하여 코드를 추가한다.


private void WBrowser_FormClosing(object sender, FormClosingEventArgs e)
{
    Properties.Settings.Default.FormSize = this.Size;
    Properties.Settings.Default.Location = this.Location;
    Properties.Settings.Default.Save();
}


private void WBrowser_Load(object sender, EventArgs e)
{
    this.Size = Properties.Settings.Default.FormSize;
    this.Location = Properties.Settings.Default.Location;
}



창의 최소 사이즈는 속성에서 설정해준다.




블로그 이미지

Link2Me

,
728x90



로그인 ID를 매번 입력해야 하는 번거로움을 없애는 방법이 뭘까?


Registry 에 정보를 저장하고 읽어오는 방법도 있는거 같은데 정보를 저장할때 관리자 권한으로 실행을 해야 저장이 가능한거 같다.


현재 상태의 설정값(로그인 ID, 비밀번호 등)을 저장하여 다음번 Load 시 불러다 이용하려고 할 경우

Properties.Settings 를 이용한다.


먼저, 솔루션 탐색기에서 Properties 를 선택하고 Settings.settings 를 더블 클릭한다.




이름 적는 곳에 기록할 이름을 적어준다. 그리고 필요하면 값부분에 적어준다.



이제 Load 될 때와 Form 이 Closing 될 때 코드를 추가해준다.


private void frmLogin_Load(object sender, EventArgs e)
{
    txtID.Text = Properties.Settings.Default.LoginIDSave;
}

private void frmLogin_FormClosing(object sender, FormClosingEventArgs e)
{
    if (!CK)
    {
        Application.Exit();
    }
    else
    {
        Properties.Settings.Default.LoginIDSave = txtID.Text;
        Properties.Settings.Default.Save();
    }
}


최초 로그인할 때는 아이디 입력창이 빈 상태이겠지만 프로그램을 한번 실행하고 나서 다음에 로그인하면 아래 그림처럼 ID 정보가 자동으로 불러와 있다.



이 정보는 C:\Users\사용자\AppData 하위의 해당 App 폴더에 값이 저장된다.




아이디 저장을 체크한 경우에 저장되도록 하고자 한다면,  Form_Closing 되는 곳에서는 삭제하고 로그인 OK 되는 이벤트에서 값을 저장해준다.


private void btnOK_Click(object sender, EventArgs e)
{
    if (this.txtID.Text == "")
    {
        MessageBox.Show("로그인 아이디를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.txtID.Focus();
    }
    else if (this.txtPwd.Text == "")
    {
        MessageBox.Show("로그인 비밀번호를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.txtPwd.Focus();
    }
    else
    {
        if (IDSave.Checked) // 로그인 OK 버튼 실행할 때 저장
        {
            Properties.Settings.Default.LoginIDSave = txtID.Text;
            Properties.Settings.Default.Save();
        }
        mySqlLogin();
    }
}



아래 코드는 윈도우 운영체제 부팅하면서 입력창 나오는 곳에서 입력한 ID 정보를 얻어내는 방법이다.


string userName = null;
using (System.Security.Principal.WindowsIdentity wi = System.Security.Principal.WindowsIdentity.GetCurrent())
{
    userName = wi.Name;
}


MessageBox.Show(userName);


블로그 이미지

Link2Me

,
728x90

C# 에서 폼간에 데이터를 전송한다는 의미를 정리해두려고 한다.

몇번의 수정을 하고 나서 이제는 거의 완벽하게 이해가 된 자료로 정리가 된 거 같다.

물론 실습으로 코딩을 하면서 막히면 자료를 보고 또 보면서 이 Properties 는 막힘없이 사용할 수 있게 되었다.


먼저 https://www.youtube.com/watch?v=PI3ad-TebP0

이 유투브 동영상을 보면 폼간에 데이터 전송하는 것이 나온다.


먼저 Form1 과 Form2 를 생성하고 UI를 작성해보자.


 


이제 F7키를 눌러서 코드를 살펴보자.



같은 Namespace 인데 class 이름은 Form1 과 Form2 로 서로 다르다.

C# 에서는 클래스가 다르면 원칙적으로 데이터에 접근할 수가 없다.

어느 클래스에서든지 접근이 가능하게 하려면 public 을 앞에 붙여줘야 한다.


속성(Properties)는 클래스의 인스턴스나 클래스 안의 데이터를 나타내는 하나의 멤버이다.

속성을 선언하는 형식은

데이터타입 속성이름

{

    get { return this.변수; }

    set { this.변수 = value; }

}


먼저, Form1 에서 Form2 를 호출하기 위한 코드

private void button1_Click(object sender, EventArgs e)
// Form1 에서 Form2 로 값을 전달하기 위한 이벤트 생성   
    Form2 frm2 = new Form2(); // Form2형 frm2 인스턴스화(객체 생성)
    frm2.ShowDialog();
}


이 코드는 Form2 창만 띄우는 것만 가능하지, 값을 전달하는 코드는 없다.

Form1의 textBox1 에서 입력한 값을 Form2 로 전달한다는 것은

Form2 에서 Form1의 값을 받아야 한다는 의미이다.



=== Form2 코드 ===

private string Form2_value;
public string Passvalue
{
    get { return this.Form2_value; }
    set { this.Form2_value = value; }  // 다른폼(Form1)에서 전달받은 값을 쓰기
}

private void Form2_Load(object sender, EventArgs e)
{
    textBox1.Text =
Passvalue; // 다른폼(Form1)에서 전달받은 값을 변수에 저장
}


=== Form1 코드 ===

private void button1_Click(object sender, EventArgs e)
{   // Form1 에서 Form2 로 값을 전달하기 위한 이벤트 생성
    if (textBox1.Text.Length == 0)
    {
         MessageBox.Show("값이 입력되지 않았습니다");
         return;
    }

    Form2 frm2 = new Form2(); // Form2형 frm2 인스턴스화(객체 생성)
    frm2.Passvalue = textBox1.Text;  // 전달자(Passvalue)를 통해서 Form2 로 전달
    frm2.ShowDialog();
}




이제 Form2 에서 입력한 값을 Form1 으로 전달하기 위한 코드를 추가해보자.

=== Form2 코드 ===

private string Form2_value;
public string Passvalue
{
    get { return this.Form2_value; } // Form2에서 얻은(get) 값을 다른폼(Form1)으로 전달 목적
    set { this.Form2_value = value; }  // 다른폼(Form1)에서 전달받은 값을 쓰기
}

private void button1_Click(object sender, EventArgs e)
{

    if (textBox2.Text == string.Empty)
    {
        MessageBox.Show("textBox2에 값이 입력되지 않았습니다");
        return;
    }

    Passvalue = textBox2.Text; // Form1 으로 값을 전달하기 위해
    this.Hide();
}


=== Form1 코드 ===

private void button1_Click(object sender, EventArgs e)
{   // Form1 에서 Form2 로 값을 전달하기 위한 이벤트 생성

    if (textBox1.Text.Length == 0)
    {
         MessageBox.Show("값이 입력되지 않았습니다");
         return;
    }

    Form2 frm2 = new Form2(); // Form2형 frm2 인스턴스화(객체 생성)
    frm2.Passvalue = textBox1.Text; // 전달자(Passvalue)를 통해서 Form2 로 전달
    frm2.ShowDialog();

    textBox2.Text = frm2.Passvalue; // 전달자(Passvalue)를 통해서 전달받은 값
}


테스트를 해보니 이런 방식은

Form2 를 띄우고 닫으면서 값을 전달하는 방식인거 같다.

frm2.ShowDialog(); 대신에 frm2.Show(); 로 대체하고 테스트를 해보니까

Form1 으로 다시 값이 반환되지 않는다.


아래는 테스트에 사용된 소스코드이다.


Properties.zip





기존의 속성 선언시 static 키워드를 붙여주면 어떤 변화가 생길까?

클래스의 인스턴스를  생성할 필요없이 직접 접근이 가능해진다.

정적(static)필드로는 모든 클래스의 인스턴스에 의해 공유된다는 점이 가장 큰 차이점이다.

정적 변수는 오직 하나만 존재한다.

인스턴스 변수(비정적 변수)는 인스턴스화(메모리를 할당)할 때마다 생성된다.


this.Form2_value 를 사용할 수 없게 에러가 표시된다. 즉, this 인 Form2 에서만 사용되는 범주를 벗어난다

=== Form2 코드 ===

private static string Form2_value;
public static string Passvalue
{
    get { return Form2_value; } // Form2에서 얻은(get) 값을 다른폼(Form1)으로 전달 목적
    set { Form2_value = value; }  // 다른폼(Form1)에서 전달받은 값을 쓰기
}


에러가 생기는 부분을 수정해줘야 한다.

객체 생성에 영향을 받지 않으므로 frm2 대신에 Form2 로 수정해준다.


=== Form1 코드 ===

private void button1_Click(object sender, EventArgs e)
{

    if (textBox1.Text.Length == 0)
    {
         MessageBox.Show("값이 입력되지 않았습니다");
         return;
    }
   

    Form2 frm2 = new Form2(); // Form2형 frm2 인스턴스화(객체 생성)
    Form2.Passvalue = textBox1.Text; // 전달자(Passvalue)를 통해서 Form2 로 전달
    frm2.ShowDialog();

    textBox2.Text = Form2.Passvalue; // 전달자(Passvalue)를 통해서 전달받은 값
}




그런데

private static string Form2_value;
public static string Passvalue
{
    get { return Form2_value; } // Form2에서 얻은(get) 값을 다른폼(Form1)으로 전달 목적
    set { Form2_value = value; }  // 다른폼(Form1)에서 전달받은 값을 쓰기
}

위 코드를

public static string Passvalue { get; set; }

* 참조 : prop 을 치고 + tab키를 누르면 자동으로 코드가 만들어진다.


한줄로 변경하면 어떤 변화가 생길까?

코드도 간단해지만, Passvalue 는 전달자 역할만 하면서 어떤 값을 대입할지 고민하지 않아도 된다.


=== Form2 코드 ===

public static string Passvalue { get; set; }  // 자동 구현 Properties
private void Form2_Load(object sender, EventArgs e)
{
    textBox1.Text = Passvalue; // 다른폼(Form1)에서 전달받은 값을 변수에 저장
}

private void button1_Click(object sender, EventArgs e)
{
    Passvalue = textBox2.Text; // Form1 으로 값을 전달하기 위해
    this.Hide();
}


=== Form1 코드 ===

private void button1_Click(object sender, EventArgs e)
{
    Form2 frm2 = new Form2(); // Form2형 frm2 인스턴스화(객체 생성)
    Form2.Passvalue = textBox1.Text; // 전달자(Passvalue)를 통해서 Form2 로 전달
    frm2.ShowDialog();

    textBox2.Text = Form2.Passvalue; // 전달자(Passvalue)를 통해서 Form2 값을 받음
}


Properties2.zip


static 을 추가하지 않으면 Form2 객체 생성을 통해서 값이 전달된다는 차이점만 있다.


결론은 전달받을 Form 에 Properties 를 추가한다는 것만 기억하자...





공통으로 사용할 것이라면 별도의 클래스를 따로 만들어서 Properties 를 추가하는 게 좋다.

prop 를 누르고 탭탭을 누르면 Properties 가 자동으로 완성시킬 수 있는 형태가 나온다.



블로그 이미지

Link2Me

,
728x90

자식폼에서 메인폼으로 값을 전달하는 방법으로
public 을 선언하여 넘겨주는 방법만 사용했었는데 이번에 검색해서 좋은 정보를 알게되었다.

배운지도 얼마 안되고 독학을 하다보니 C# 기능을 제대로 몰라서 애로사항이 많다.

몇번 더 적용해보면 확실하게 내것이 될 수 있을 거 같다.

(작성일자 : 2015.11.29) -- delegate 를 제대로 이해하지 못한 상태에서 작성한 자료


목적1 : 자식폼(Form2) 에서 메인폼으로 데이터 전달


=== 자식폼에서 설정하는 것들 =====
public delegate void Form2_EventHandler(string data); // string 을 반환값으로 같은 대리자를 선언
public event Form2_EventHandler TextSendEvent// 대리자 타입의 이벤트 처리기를 설정

// 클릭하여 실제 전달되는 값
TextSendEvent(dlgOpen.FileName.ToString()); // 스트링값을 메인폼에게 보내줌


=== 메인폼에서 설정하는 것들 ===
// 자식폼(Form2)를 띄우는 이벤트
private void pictureBoxOpen_Click(object sender, EventArgs e)
{
    foreach (Form openForm in Application.OpenForms)
    {
        if (openForm.Name == "Form2") //폼 중복 열기 방지
        {
            openForm.Activate();
            return;
        }
    }

    Form2 frm2 = new Form2();

    // 자식폼이 가지고 있는 TextSendEvent 이벤트 처리기에 frm2_getTextEvent 이벤트 연결

    frm2.TextSendEvent += new Form2.Form2_EventHandler(frm2_getTextEvent);
    frm2.Show();  // 자식폼이 활성화된  상태에서 값을 전달받기 위해서
}

void frm2_getTextEvent(string text)
{
    // 값을 넘겨 받아서 실제 처리할 함수
    CurrentData = text; // Form2 에서 넘겨받는 값
}


참고한 자료는 http://blog.naver.com/kjh258999/20043308380 이며, 테스트를 통해서 동작되는 걸 확인하면서 이름 변경을 해보면서 어떤 이름들이 변경되는지 확인하였다.

그래서 좀 더 이해가 되도록 이름을 변경했고, 색상으로 표시를 했다.

다른 블로그(http://notull.tistory.com/entry/C-%ED%8F%BC%EA%B0%84-%EA%B0%92%EC%A0%84%EB%8B%AC-Event%EB%B0%9C%EC%83%9D)에도 예제 비슷하게 되어 있는데 설명은 없다.



목적2 : 메인폼에서 자식폼으로 데이터를 전송하는 방법


=== 메인폼에서 설정하는 것들 ===
// 자식폼(Form2)를 띄우는 이벤트
private void pictureBoxOpen_Click(object sender, EventArgs e)
{
    foreach (Form openForm in Application.OpenForms)
    {
        if (openForm.Name == "Form2") //폼 중복 열기 방지
        {
            openForm.Activate();
            return;
        }
    }

    Form2 frm2 = new Form2();

    frm2.Owner = this;  // 이 한줄을 추가해준다

    // 자식폼이 가지고 있는 TextSendEvent 이벤트 처리기에 frm2_getTextEvent 이벤트 연결

    frm2.TextSendEvent += new Form2.Form2_EventHandler(frm2_getTextEvent);
    frm2.Show();  // 자식폼이 활성화된  상태에서 값을 전달받기 위해서
}

void frm2_getTextEvent(string text)
{
    // 값을 넘겨 받아서 실제 처리할 함수
    CurrentData = text; // Form2 에서 넘겨받는 값
}



=== 자식폼에서 설정하는 것들 =====
public delegate void Form2_EventHandler(string data); // string 을 반환값으로 같은 대리자를 선언
public event Form2_EventHandler TextSendEvent// 대리자 타입의 이벤트 처리기를 설정

// 클릭하여 실제 전달되는 값
TextSendEvent(dlgOpen.FileName.ToString()); // 스트링값을 메인폼에게 보내줌


// 메인폼의 이름이 Form1 이라고 한다면

Form1 f1 = (Form1)this.Owner;

한줄을 추가해주고 나서, 값을 뿌릴 곳에다가 뿌려준다.

MessageBox.Show(f1.textBox1.Text);

textBox1 의 속성 중에서 Modifies 를 public 으로 반드시 변경해야 한다.

넘겨줄 값이 labelSubtitle1.Text 라서 아래 화면처럼 속성을 변경해줬다.



Form2 를 Load 하면서 메인폼의 값을 전달하는게 맞을거 같아서 Load 이벤트에 내용을 추가했다.

private void Form2_Load(object sender, EventArgs e)
{
    MainForm f1 = (MainForm)this.Owner;
    SearchBox.Text = System.IO.Path.GetFileNameWithoutExtension(f1.labelSubtitle1.Text);
    // Modifiers 를 public 으로 설정해줘야 된다.
}


블로그 이미지

Link2Me

,
728x90

새로운 폼을 띄운 다음 그 폼에서 값을 받아서 처리해야 할 경우가 있다.

이때 폼을 띄울 때 처리해야 할 코드이다.


//폼 중복 열기 방지
foreach (Form openForm in Application.OpenForms)
{
    if (openForm.Name == "FindForm")
    {
        openForm.Activate();
        return;
    }
}

FindForm searchf = new FindForm();
searchf.StartPosition = FormStartPosition.Manual;
searchf.Location = new Point(100, 100);
if (searchf.ShowDialog() == DialogResult.OK)
{
    // 값을 넘겨 받아서 실제 처리할 함수
}


======= 값을 넘겨주는 Form 창 =======

public partial class FindForm : Form
{
    private int listView1_No;
    private int listView2_No;
    private int LV_No;

    public int LV1_No
    {
        get { return listView1_No; }
    }
    public int LV2_No
    {
        get { return listView2_No; }
    }
    public int SelectedViewNo
    {
        get { return LV_No; }
    }

    public FindForm()
    {
        InitializeComponent();
    }

    private void btnOK_Click(object sender, EventArgs e)
    {
        string Value1 = textBox1.Text;
        string Value2 = textBox2.Text;

        if (LV1.Checked)
        {
            LV_No = 1; // Value1
        }
        else
        {
            LV_No = 2; // Value2
        }

        int.TryParse(Value1, out listView1_No);
        if (Value1.Length == 0)
        {
            MessageBox.Show("Value1 의 값을 입력하지 않았습니다");
            return;
        }
        else if (listView1_No == 0)
        {
            MessageBox.Show("1 이상의 숫자를 입력해야 합니다");
            return;
        }

        int.TryParse(Value2, out listView2_No);
        if (Value2.Length == 0)
        {
            MessageBox.Show("Value2 의 값을 입력하지 않았습니다");
            return;
        }
        else if (listView2_No == 0)
        {
            MessageBox.Show("1 이상의 숫자를 입력해야 합니다");
            return;
        }
        DialogResult = DialogResult.OK;
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.Cancel;
    }       

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        //숫자,백스페이스만 입력받는다.
        if (!(Char.IsDigit(e.KeyChar)) && e.KeyChar != 8) //8:백스페이스,45:마이너스,46:소수점
        {
            e.Handled = true;
        }
    }

    private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
    {
        //숫자,백스페이스만 입력받는다.
        if (!(Char.IsDigit(e.KeyChar)) && e.KeyChar != 8) //8:백스페이스,45:마이너스,46:소수점
        {
            e.Handled = true;
        }
    }
}



블로그 이미지

Link2Me

,
728x90

Panel 이나 Tabpage 로 Layout 을 구성하였는데, 다른 폼을 Panel / TabPage 안에 띄우고 싶을 때 처리하는 방법을 구글검색과 직접 테스트를 하면서 분석하여 알게 된 것을 적어둔다.


아래 화면을 보면 tabPage4 에 원래 보이는 화면과 아래에는 달력폼이 있는 화면을 가져와서 보여주고 있다.




어떻게 하면 새로운 Form2 의 화면을 tabPage4 에 보이도록 할 수 있을까?


https://msdn.microsoft.com/ko-kr/library/system.windows.forms.control%28v=vs.110%29.aspx

에 Control 클래스의 정의를 보면 시각적으로 표시되는 구성 요소인 컨트롤의 기본 클래스를 정의한다고 설명되어 있다.

http://www.csharpstudy.com/Threads/uithread.aspx 에 보면 WinForm의 UI 컨트롤들은 Control 클래스로부터 파생된 클래스들 이라고 되어 있다.


Designer.cs 파일을 열어서 tabPag4 부분을 찾아보면 ...tabPage4.Controls.Add 에 splitContainer4 를 추가한 것을 알 수 있다. 물론 마우스 몇번 까딱까딱하면 자동으로 만들어진다. 만들어진 내용이 바로 여기에 적혀 있다.

//
// tabPage4
//
this.tabPage4.Controls.Add(this.splitContainer4);
this.tabPage4.Location = new System.Drawing.Point(4, 22);
this.tabPage4.Name = "tabPage4";
this.tabPage4.Padding = new System.Windows.Forms.Padding(3);
this.tabPage4.Size = new System.Drawing.Size(1118, 396);
this.tabPage4.TabIndex = 1;
this.tabPage4.Text = "tabPage4";
this.tabPage4.UseVisualStyleBackColor = true;
//


원래 화면에 추가했던 Control 클래스 대신에 버튼을 누르면 다른 클래스가 추가되도록 하고 싶다.

거기다가 새로 추가하는 것은 New Form2 를 추가하고 싶다.

순서는 tablPage5 로 화면 이동시키고, tabPage4 에 추가된 Control 을 전부 제거(Clear) 한 다음, tabPage4 에 추가된 모든 Control 들을 제거(remove) 했다.

그 다음에 새폼의 Control 을 추가(Add)했다.

불필요한 게 있을 수도 있다. 일단은 이렇게 추가해서 테스트를 해봤다.


private void Form2Tab_Click(object sender, EventArgs e)
{
     // tabPage5 선택창으로 화면 이동시키기
     tabControl2.Enabled = false;
     tabControl2.SelectedTab = tabPage4;
     tabControl2.Enabled = true;

     tabPage4.Controls.Clear(); // Controls 전부 제거
     foreach (Control item in tabPage4.Controls.OfType<Control>())
     {
         tabPage4.Controls.Remove(item);
     }

     this.Invoke(new MethodInvoker(delegate ()
     {
         // 다른 폼을 Tabpage/Panel 에 띄우기
         Form2 tabfrm = new Form2();
         tabfrm.TopLevel = false;
         tabfrm.TopMost = true;
         //panel1.Controls.Add(tabfrm);  // panel1 에다 추가
         //splitContainer6.Panel1.Controls.Add(tabfrm); //
splitContainer6.Panel1 에다 추가
         tabPage4.Controls.Add(tabfrm);
         tabfrm.Show();
     }));
}



원래 화면으로 복구시키는 것은 Designer.cs 파일에 있는 걸 Conrol.Add 해주면 된다.


private void toolStripButton5_Click(object sender, EventArgs e)
{
     // tabPage4 원래 화면으로 복구시키기
     tabControl2.Enabled = false;
     tabControl2.SelectedTab = tabPage4;
     tabControl2.Enabled = true;

     tabPage4.Controls.Clear(); // Controls 전부 제거
     foreach (Control item in tabPage4.Controls.OfType<Control>())
     {
         tabPage4.Controls.Remove(item);
     }
     tabPage4.Controls.Add(this.splitContainer4);
}


구글링해서 찾은걸 적어 놓는다.

private void btn_Click(object sender, EventArgs e)
{
    panel1.Controls.Clear(); //to remove all controls

    //to remove all comboboxes
    foreach (Control item in panel1.Controls.OfType<ComboBox>())
    {
        panel1.Controls.Remove(item);
    }

   //to remove control by Name
    foreach (Control item in panel1.Controls.OfType<Control>())
    {
        if (item.Name == "bloodyControl")
            panel1.Controls.Remove(item);
    }

    //to remove just one control, no Linq
    foreach (Control item in panel1.Controls)
    {
        if (item.Name == "bloodyControl")
        {
             panel1.Controls.Remove(item);
             break; //important step
        }
    }
}






블로그 이미지

Link2Me

,
728x90

부모폼/자식폼이 아닌 New Form 으로 Form 을 띄울 때 중복 실행이 되는 걸 방지하는 방법이다.

폼 중복 실행방지, 폼의 위치를 원하는 위치에 설정, 자식폼으로 값을 넘기는 부분,

자식폼을 Show() 로 실행할 것인지 ShowDialog() 로 실행할 것인지를 모두 기록한 코드이다.


private void btnDictionary_Click(object sender, EventArgs e)
{
    //폼 중복 열기 방지
    foreach (Form openForm in Application.OpenForms)
    {
        if(openForm.Name == "WBrowser") // 열린 폼의 이름 검사
        {
            if(openForm.WindowState == FormWindowState.Minimized)
            {  // 폼을 최소화시켜 하단에 내려놓았는지 검사
                openForm.WindowState = FormWindowState.Normal;

                openForm.Location = new Point(this.Location.X + this.Width, this.Location.Y);

            }
            openForm.Activate();
            return;
        }
    }
    WBrowser wb = new WBrowser();  // 폼이 실행되지 않았으면 New Form 객체 생성
    // 자식폼으로 값을 넘겨줄 것이 있으면 이 부분에 코드를 추가

    wb.StartPosition = FormStartPosition.Manual;  // 원하는 위치를 직접 지정해서 띄우기 위해
    wb.Location = new Point(this.Location.X + this.Width, this.Location.Y); // 메인폼의 오른쪽에 위치토록
    wb.Show();
}


자식폼을 띄울 때 Show() 로 할 것인지, ShowDialog() 로 할 것인지에 코드가 약간 달라진다.

ShowDialog() 로 하려면 Show() 대신에 아래와 같이 코드를 작성해야 한다.

if (wb.ShowDialog() == DialogResult.OK)

{

     // 자식폼에서 받아서 처리할 내용

}


자식폼에서는 DialogResult = DialogResult.OK;  가 추가되어야 한다.


처음 인터넷에서 정보를 찾아서 헤매고 다닐때에는 무슨 의미인지도 몰랐는데 이제는 의미 파악이 되었다.

그래서 처음에 기록해두었던 것을 보완해서 작성을 했다.

혹시라도 이 게시글을 보는 초보자분은 도움되면 공감 꾸욱 눌러주세요.

블로그 이미지

Link2Me

,
728x90

1개의 폼안에 다수의 자식폼을 포함하는 형태의 프로그램들이 실생활에서 사용되고 있다.


1. 부모폼을 만드는 방법

    부모폼으로 만들고자 하는 Form 에서 아래 그림과 같이 설정해준다.



설정을 하고 나면 폼의 형태가 아래처럼 바뀐다.



2. 자식폼을 호출하는 방법

네이버, 구글링을 해보면 대부분 나오는 내용은

Form2 f2 = new Form2();
f2.MdiParent = this;  // 현재 폼의 자식폼임을 알림
f2.Show();

이다.

이 코드는 폼을 호출할 때마다 새로운 폼이 생성되기 때문에 실제 코드에서는 사용하는데 애로사항이 생긴다.


현재 폼이 열려있는지 체크하는 기능을 추가해야 한다.

부모폼의 ActiveMdiChild 속성을 이용하여 닫아주면 된다. ActiveMdiChild.Close();

자식폼 Form1 과 자식폼 Form2 를 생성하여 구별할 수 있게 만들었다.


 

부모폼에서 자식폼을 띄우는 소스코드


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace MDI
{
    public partial class Main : Form
    {
        private Form1 mChildForm1 = null;
        private Form2 mChildForm2 = null;
 
        public Main()
        {
            InitializeComponent();
        }
 
        private Form ShowOrActiveForm(Form form, Type t)
        {
            if (form == null)
            {
                form = (Form)Activator.CreateInstance(t);
                form.MdiParent = this;
                form.WindowState = FormWindowState.Maximized;
                form.Show();
            }
            else
            {
                if (form.IsDisposed)
                {
                    form = (Form)Activator.CreateInstance(t);
                    form.MdiParent = this;
                    form.WindowState = FormWindowState.Maximized;
                    form.Show();
                }
                else
                {
                    form.Activate();
                }
            }
            return form;
        }
 
        private void miForm1_Click(object sender, EventArgs e)
        {
            if (ActiveMdiChild != null)  // 자식폼이 열려 있으면
            {
                if(this.ActiveMdiChild != mChildForm1)  // 열려있는 자식폼이 Form1 이 아니면
                {
                    ActiveMdiChild.Close(); // 현재 활성화된 창을 닫아라
                }
                mChildForm1 = ShowOrActiveForm(mChildForm1, typeof(Form1)) as Form1;
            } else
            {
                mChildForm1 = ShowOrActiveForm(mChildForm1, typeof(Form1)) as Form1;
            }                 
        }
 
        private void miForm2_Click(object sender, EventArgs e)
        {            
            if (ActiveMdiChild != null)  // 자식폼이 열려 있으면
            {
                if (this.ActiveMdiChild != mChildForm2)  // 열려있는 자식폼이 Form2 가 아니면
                {
                    ActiveMdiChild.Close(); // 현재 활성화된 창을 닫아라
                }
                mChildForm2 = ShowOrActiveForm(mChildForm2, typeof(Form2)) as Form2;
            }
            else
            {
                mChildForm2 = ShowOrActiveForm(mChildForm2, typeof(Form2)) as Form2;
            }
        }
 
        private void miExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
 
        }
 
    }
}
 
 
cs


위 코드를 직접 다운로드 받아서 실행해볼 수 있는 파일


MDI.zip

구글링해서 찾은 소스를 약간 수정 보완해서 부모폼에서 자식폼이 1개만 실행되도록 수정했다.

if 문을 없애면 Form1, Form2 각각 둘다 실행된다.

폭풍 검색으로 구글링해서 찾아낸 가장 쓸만한 코드인거 같다. 좀더 실력이 쌓이면 더 좋게 만들날이 오겠지만~


원코드 출처 : http://www.codeproject.com/Tips/257281/Single-Instance-Form-in-a-MDI-application


참고 : http://colorscripter.com/ 는 소스코드를 보기 좋게 정렬해주는 사이트인데 저질 기억이라 이걸 찾는데 애를 먹어 아예 기록을 해둔다.


블로그 이미지

Link2Me

,
728x90

화면 Layout 을 보기 좋게 하기 위해서 SplitContainer 클래스를 이용한다.

유투브 동영상을 보면서 익힌 사용법을 나중에 다시 보려고 기록해둔다.

tabControl Layout 에서 아래 번호 순서대로 하면 된다.



SplitContainer 클래스를 사용하면 기본적으로 수직분할이 된다.

A Split Container is a combination of three components.  Panel1 and Panel2 are separated either horizontally or vertically by a splitter.


수직으로 분할하기 위해서는

먼저 splitContainer2 를 찾아서 선택한다. (최초로 splitContainer 를 사용한 경우에는 splitContainer1 을 선택)

그래야만 Orientation 속성이 보인다. Horizontal 로 변경하면 ....


수직으로 분할된 창이 보일 것이다.

Panel1, Panel2 를 선택하면 7번처럼 창의 위치를 조정할 수가 없다.

마찬가지로 splitContainer2 속성이 선택되어야만 가능하다.


상단에 검색할 버튼을 만들기 위함이고 하단에는 dataGridView 을 추가하기 위한 Layout 이다.




Panel1 과 Panel2 사이를 움직이지 못하게 하는 방법은

split container 속성의 IsSplitterFixed true 로 설정하면 고정된다.




고정하고 싶은 Panel 부분에 2줄을 추가해주면 된다.

this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainer1.IsSplitterFixed = true;

Designer.cs 파일에 기록된 정보를 확인해 보니...

// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainer1.IsSplitterFixed = true;
this.splitContainer1.Location = new System.Drawing.Point(3, 3);
this.splitContainer1.Name = "splitContainer1";
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.lbl_View);
this.splitContainer1.Panel1.Controls.Add(this.comboBox2);
this.splitContainer1.Panel1.Controls.Add(this.comboBox1);
this.splitContainer1.Panel1.Controls.Add(this.lbl_totalcnt1);
this.splitContainer1.Panel1.Controls.Add(this.totalcnt1);
this.splitContainer1.Panel1.Controls.Add(this.btnSave);
this.splitContainer1.Panel1.Controls.Add(this.btnSearch);
this.splitContainer1.Panel1.Controls.Add(this.searchBox);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.dataGridView1);
this.splitContainer1.Size = new System.Drawing.Size(1146, 462);
this.splitContainer1.SplitterDistance = 39;
this.splitContainer1.TabIndex = 0;



관련 추가 자료는 참조

http://www.c-sharpcorner.com/uploadfile/6897bc/container-controls-3-splitcontainer/


C# 에 대해 좀더 알아보면 좋은 사이트

http://www.java2s.com/Code/CSharpAPI/CatalogCSharpAPI.htm



블로그 이미지

Link2Me

,
728x90

Layout 구성을 하는 방안으로 TabControl 기능을 이용하여 작업을 해봤다.


tabControl1 의 TabPages 컬렉션을 클릭하면



컬렉션 편집기 창이 뜬다.

칼럼을 추가하거나 삭제 또는 칼럼명을 수정한다.

tabPage 는 기본으로 2개가 생성된다.



TabConrol 의 위치를 변경하고 싶다면






tabControl1.TabPages.Remove(tabPage1); // tabPage1 안보이게 처리

tabControl1.TabPages.RemoveAt(1); // RemoveAt(index) 을 사용하면 인덱스 번호를 적어준다.

인덱스번호를 적어주는 것보다는 직접 해당 이름을 적어주는게 더 편하다.


splitContainer1.Panel1Collapsed = true;  // 한 Panel Load 되지 않았으므로 Panel1 공간 제거

tabControl.TabPages.Insert(0, tabPage1); // Show the tab page (insert it to the correct position)
tabPage1.Enabled = false; // this disables the controls on it
tabPage1.Visible = false; // this hides the controls on it.


블로그 이미지

Link2Me

,
728x90

출처 : http://blog.daum.net/modong518/84


간단한것인데 어려웠다. 으헝헝헝

인터넷에 검색을 해서 제일 그럴듯하게 찾았던 것이 Form1 -> Form2를 전환하기위해서

버튼을 누르면 Form1을 숨기고 Form2를 보여주는 방식이었는데

윈도우 Form이 많아지면 많아질 수록 꽁수는 들통이 나게 되어있었다 ㅠ_ㅠ

 

답은 여기에 있다 !

 

곰곰히 생각해보니 Form1에서 Form2를 부르게 되는 것은 상속을 통해 호출하는 것과 같으니

Form1 클래스에 Form2 객체를 하나 만들고 Form2를 부르게 되는곳에서 생성하면서 Show()함수를 통해 보여주면 된다. 주의할것은 이 Show함수는 Form1의 Show함수가 아니라 Form2의 객체 이름.Show()함수이다. 

 

 this.form2 = new Form2(this);
this.form2.Show();

 

그리고 나서 또 주의할것은 이 Form2를 닫게 되면 Form1은 남아있다는 것이다. 함께 닫게 하기 위해서 필요한 것이 있는데 바로 상위 Form1에서의 선언이다.

객체를 만들고 보여주기 전에 다음과 같이 선언한다. 이는 Form2가 닫혀지는 이벤트가 발생시에 Form1의

exit_Click이벤트를 발생시킨다. exit_Click이벤트에서는 this.Close() 함수만 호출하면 폼이 닫혀진다.

 

 this.form2.FormClosed += new FormClosedEventHandler(exit_Click);

 

정말 나와 같이 헤매는 학생들에게 도움이 되었으면 좋겠다. 아악 ㅜㅜ 힘내자 +_+ !

 

블로그 이미지

Link2Me

,