728x90

Auto Update 를 만들어보면서 겪은 버그현상이다.

현재 버전과 서버버전이 서로 같으면

"최신버전을 사용하고 있습니다" 라는 메시지창을 띄우고 나서 this.Close() 를 실행했더니

다시 실행하려고 하면 "삭제된 개체에 액세스할 수 없습니다" 라는 문구를 뿌리면서 에러가 발생한다.


폼을 정상적으로 띄우고나서 this.Close() 로 닫기를 한 경우에는 절대로 이런 메시지가 나오지 않았다.

가만 생각해보니까

정상적으로 폼을 띄우지 않은 상태에서 폼닫기를 실행해버리까 메모리에서 아예 삭제되어 버리는거 같다.


해결은 아래 두가지 방법 중의 하나로 해결을 했다.

1. 폼을 띄우면서 정보를 보여주고 다운로드 버튼은 생성하지 않는다.

2. 폼을 띄우고 나서 바로 this.Close() 로 닫기를 하고 "최신버전을 사용하고 있습니다" 라는 메시지창을 띄운다.


잠시 착각해서 발생한 코딩 실수였다.

버그는 기본기가 약해서 발생한다. 삽질을 엄청하고서야 알게되는 허탈감, 시간낭비

더 효과적인 방법으로 구현할 수 있게 될 날을 기대하며....

블로그 이미지

Link2Me

,
728x90

웹서버에 새로운 설치파일을 올려두고, setup.txt 파일 내용을 탐색하여 PC에 설치된 버전과 다르면 프로그램을 다운로드 받게 하는 기능을 추가해봤다.


메인화면이  실행되면서 버전을 서로 체크하여 다르면 자동으로 팝업화면을 띄우도록 처리를 했는데 화면이 가려져서 숨는다.



TopMost 를 true 로 설정하면 항상 최상단에 뜬다.

알림창 효과로 알려주려면 이 기능이 도움된다.

블로그 이미지

Link2Me

,
728x90

C# 에서 자동 업데이터를 만들어보고 있는데 Program Files(x86) 폴더 하단에 설치된 파일은 자동 업데이터를 구동시켜 보니까 Access 권한이 없다고 나온다.


Program.cs 파일 내용을 아래와 같이 수정해주면

파일 실행시 관리자 권한으로 실행할 것인지를 물어본다.

컴파일한 파일을 Program Files(x86) 폴더 해당폴더에 복사하고 나서 실행하니까 웹에서 파일을 다운로드 받아서 해당 폴더 파일을 업데이트한다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Security.Principal;

namespace AutoUpater
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            if (IsAdministrator() == false)
            {
                try
                {
                    ProcessStartInfo procInfo = new ProcessStartInfo();
                    procInfo.UseShellExecute = true;
                    procInfo.FileName = Application.ExecutablePath;
                    procInfo.WorkingDirectory = Environment.CurrentDirectory;
                    procInfo.Verb = "runas";
                    Process.Start(procInfo);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message.ToString());
                }
                return;
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }

        public static bool IsAdministrator()
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            if (null != identity)
            {
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            return false;
        }

    }
}




블로그 이미지

Link2Me

,
728x90

C# comboBox 에 테이블명을 가져오는 걸 알고 싶다는 질문이 있어서 테이블명 가져오기를 해봤다.

이런 걸 하기 위한 첫번째 요건은 MySQL 검색어로 테이블명 찾는 명령어가 무엇인지부터 알아내는 것이다.

나머지는 C# 코드에 맞게 작성해서 화면에 뿌려주면 된다.

어떤 DB에 있는 테이블명을 알고 싶은지 적어주면 된다. Where 조건을 빼면 모든 테이블명 리스트가 검색된다.

단, MySQL 접속권한에 따라 모든 테이블 검색이 안될 수도 있다.


private void getTablecomboBox()
{
    comboBox1.Items.Clear();
    comboBox1.Items.Add("테이블명");
    try
    {
        myConn = new MySqlConnection(ConnectionString);
        myConn.Open();
        string strqry = "select table_name from information_schema.tables where TABLE_SCHEMA='DB명'";

        MySqlCommand cmd = new MySqlCommand(strqry, myConn);
        cmd.CommandType = CommandType.Text;
        MySqlDataReader R = cmd.ExecuteReader();

        if (R.HasRows)
        {
            while (R.Read())
            {
                comboBox1.Items.Add(R.GetString(0));
            }
        }
        else
        {
            MessageBox.Show("테이블이 하나도 없습니다");
        }
        R.Dispose();
        myConn.Close();

    } catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

블로그 이미지

Link2Me

,
728x90

응용 프로그램의 크기를 마우스로 변경할 때 C# listView 에서 칼럼 사이즈가 자동으로 변경되게 하는 방법을 알아냈다.

화면을 변경하면 칼럼 사이즈가 변경되지 않아서 좀 눈에 거슬렸었다.

"닷넷프로그래밍 정복" 책을 처음에 볼 때에는 무슨 말인지 이해를 못한 부분이 많았는데, 지금 필요한 부분을 훑어보면서 이벤트 부분을 보다보니 Resize 이벤트가 눈에 띄었다.

Resize : 폼의 크기가 변경될 때

폼의 크기가 변경되는 이벤트를 이용하면 되겠다 싶어서 해봤더니 원하는 결과가 된다.


먼저 listView1 의 이벤트 아이콘을 찾아서 Resize 에서 마우스 더블클릭을 하면 이벤트 코드가 자동으로 추가된다.


아래 메서드(함수)를 추가해주면 된다.

원하는 부분이 마지막 칼럼의 크기를 창의 크기에 맞게 최대로 나오도록 하기 위한 것이다.


private void listView_ColumnSizeAutoChange(ListView LV)
{
    LV.Columns[LV.Columns.Count - 1].Width = -2;
}

private void listView1_Resize(object sender, EventArgs e)
{
    listView_ColumnSizeAutoChange((ListView)sender);
}

private void listView2_Resize(object sender, EventArgs e)
{
    listView_ColumnSizeAutoChange((ListView)sender);
}


블로그 이미지

Link2Me

,
728x90

C# listView 에서 편집하는 자료를 DB에 추가/수정/삭제하는 코드이다.

소스코드를 참조하면 내용 이해가 되리라 보며 설명은 생략한다.

좀 더 이해를 원하면 http://link2me.tistory.com/779 자료를 참조하면 된다.


private void listView_DBInsert()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "INSERT INTO items VALUES (@uid, @ItemName, @Price, @Quantity, @d_regis);";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters.Add("@ItemName", MySqlDbType.VarChar, 100);
    cmd.Parameters.Add("@Price", MySqlDbType.Decimal, 10);
    cmd.Parameters.Add("@Quantity", MySqlDbType.Int16, 11);
    cmd.Parameters.Add("@d_regis", MySqlDbType.DateTime); 

    cmd.Parameters["@uid"].Value = null;  // 값이 자동으로 증가하기 때문에 null 로 해주면 됨
    cmd.Parameters["@ItemName"].Value = ItemNameBox.Text;
    cmd.Parameters["@Price"].Value = PriceBox.Text;
    cmd.Parameters["@Quantity"].Value = QuantityBox.Text;
    cmd.Parameters["@d_regis"].Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

    cmd.ExecuteNonQuery();

    ItemNameBox.Text = "";
    PriceBox.Text = "";
    QuantityBox.Text = "";

    listView1Table();

    cmd.Dispose();
    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}

private void listView_DBSave()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "UPDATE items SET ItemName=@ItemName, Price=@Price, Quantity=@Quantity, d_regis=NOW() WHERE uid=@uid;";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters.Add("@ItemName", MySqlDbType.VarChar, 100);
    cmd.Parameters.Add("@Price", MySqlDbType.Decimal, 10);
    cmd.Parameters.Add("@Quantity", MySqlDbType.Int16, 11);

    cmd.Parameters["@uid"].Value = listView1.SelectedItems[0].SubItems[2].Text;
    cmd.Parameters["@ItemName"].Value = ItemNameBox.Text;
    cmd.Parameters["@Price"].Value = PriceBox.Text;
    cmd.Parameters["@Quantity"].Value = QuantityBox.Text;
    //cmd.Parameters["@d_modify"].Value = DateTime.Now.ToString("yyyyMMddHHmmss");

    cmd.ExecuteNonQuery();

    listView1Table();

    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}


private void listView_Delete()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "DELETE FROM items WHERE uid = @uid;";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters["@uid"].Value = listView1.SelectedItems[0].SubItems[2].Text;
    cmd.ExecuteNonQuery();

    // DB 테이블 자료를 삭제했으므로 화면상의 텍스트박스 내용 초기화
    ItemNameBox.Text = "";
    PriceBox.Text = "";
    QuantityBox.Text = "";

    listView1Table();

    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}


블로그 이미지

Link2Me

,
728x90

C# 에서 MySQL 등 DB에 있는 자료를 ListView 에 가져오는 소스코드다.

읽어온 자료는 R.GetString(0) 부터 나온다.

가령 Select uid, id, name, email FROM 테이블명;

이라고 할 경우 R.GetString(0) 는 uid 칼럼이고, R.GetString(1) 은 id, R.GetString(2) 는 name, R.GetString(3) 은 email 칼럼이다.

listView 에 자료를 추가하는 것에 대해 이해하고자 하면 listView 기능 분석 게시글을 참조하면 도움된다.


private void listView1Table()
{
    myConn = new MySqlConnection(ConnectionString);
    try
    {
        myConn.Open();

        string strqry = "select * from items ";
        if (searchBox.Text.Trim().Length > 0)
        {
            strqry += "where Quantity='" + searchBox.Text.Trim() + "' ";
        }
        strqry += "order by uid";

        MySqlCommand cmd = new MySqlCommand(strqry, myConn);
        cmd.CommandType = CommandType.Text;
        MySqlDataReader R = cmd.ExecuteReader();

        listView1.Items.Clear();
        if (R.HasRows)
        {
            int i = 0;
            while (R.Read())
            {
                i = i + 1;
                ListViewItem lvt = new ListViewItem();
                lvt.SubItems.Add(i.ToString());
                lvt.SubItems.Add(R["uid"].ToString());
                lvt.SubItems.Add(R.GetString(1));
                lvt.SubItems.Add(R.GetString(2));
                lvt.SubItems.Add(R.GetString(3));
                lvt.SubItems.Add(R.GetString(4));
                listView1.Items.Add(lvt);
            }
            lvt1totalcnt.Text = "총 " + i.ToString() + " Row";
        }
        else
        {
            MessageBox.Show("데이터가 없습니다");
        }
        R.Close();
        SetHeight(listView1, 20);  // 행높이 지정 --> 사용자 정의 함수로 없어도 된다. 다른 게시글 참조하면 나옴
        listView1.HeaderStyle = ColumnHeaderStyle.Nonclickable;
        myConn.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }           
}




블로그 이미지

Link2Me

,
728x90

C# 에서 사용하는 DataGridView의 폰트를 각각의 부분에 지정할수 있다.


// 전체적으로 폰트 적용하기
this.dataGridView1.Font = new Font("Tahoma", 10, FontStyle.Regular);

// Colum 의 해더부분을 지정하기
this.dataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

// Row 해더부분을 지정하기
this.dataGridView1.RowHeadersDefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

// Cell 내용부분을 지정하기
this.dataGridView1.DefaultCellStyle.Font = new Font("Tahoma", 10, FontStyle.Bold);

블로그 이미지

Link2Me

,
728x90

C# 을 배우면서 부족하지만 프로그램 하나를 만들었다.

설치 프로그램을 통해서 설치하고 uninstall 하는 걸 할 수 있도록 하는 걸 해보려고 찾아보니 Inno Setup 프로그램이 있다. Inno Setup 프로그램은 freeware 프로그램이다.


Inno Setup 프로그램 다운로드 : http://www.jrsoftware.org/isdl.php


Korean.isl


Inno Setup 파일을 설치하고 나서, 위 파일을 Languages 폴더에 복사한다.

그러면 프로그램 설치시에 한글로 메뉴가 나온다.


한두번 연습을 해보면서 기본적으로 터득한 것만 적어두려고 한다.

아직 부족한 부분은 나중에 알게되면 추가로 적어놓을 생각이다.


Inno Setup 실행파일을  실행하고 나면 아래 화면이 나온다.

New 아이콘을 눌러서 새로운 iss 파일을 만든다.






설치하는 파일에 ico 파일도 미리 만들거나 받아서 같이 설치해줘야 아이콘 모양이 같이 나온다.

아이콘 파일이 없으면 http://www.iconfinder.com 에서 받는다.




프로그램  설치전에 보여줄 텍스트파일 메시지와 설치되고 나서 버전업이 되면서 변화된 내용이 뭔지 알 수 있도록 보여주는 Chaneglog.txt 파일을 추가해준다.

파일은 반드시 UTF8 로 저장해야 글씨가 깨지지 않고 보인다.


미리 다운로드받아 Languages 폴더에 복사한 korean.isl 파일이 있으면 자동으로 선택할 수 있게 나온다.


아이콘 파일은 http://www.iconfinder.com 에서 찾아서 추가를 해줬다.

아이콘 편집기를 이용하여 본인만의 아이콘을 제작할 필요가 있다.



설치가 끝나고 나서 바로 compile 을 할 것인지 물어보는데

아니오를 선택했다.


EesyWig 으로 만들어진 파일을 저장한다.

가능하면 Setup 파일을 만들 폴더에 같이 저장하는게 편하다.

나중에 수동으로 편집하기가 편리하기 때문이다.


아래처럼 파일명을 생성할 때 버전정보가 같이 포함되게 작성하는 것도 팁의 하나라 볼 수 있다.


이제 make 를 하면 자동으로 Setup 파일이 만들어진다.


만들어진 setup 파일을 설치하면 Program Files(86) 폴더밑에 폴더가 생성되면서 프로그램이 생성된다.


참조하면 도움되는 블로그

http://blog.naver.com/empty_wagon/20141935914


부족하지만 이정도로 작성해둔다.

아직 바탕화면 아이콘 모양이 나오게 하는 것까지는 성공하지 못했다.

uninstall 도 실행해보니까 잘 된다.

Inno Setup 정말 멋진 프로그램 인거 같다.


바탕화면 아이콘이 나오게 하는 걸 알아냈다.

Files 라인에 ico 파일도 같이 복사하게 한 다음에

Source: "C:\LInkSutitle\LinkSubtitles.ico"; DestDir: "{app}"; Flags: ignoreversion


[Icons]

Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; WorkingDir: {app}; IconFilename: {app}\LinkSubtitles.ico; IconIndex: 0; Tasks: desktopicon


부분을 추가해주면 바탕화면 아이콘이 제대로 반영된다.


아직 의미파악은 안되었지만 다른 샘플들을 보고 추가한 부분을 적어둔다.

DisableProgramGroupPage=false
DisableReadyPage=true
PrivilegesRequired=admin
ShowLanguageDialog=yes
DisableDirPage=false
CloseApplications=true
AlwaysUsePersonalGroup=true


블로그 이미지

Link2Me

,
728x90

int.PryParse(string str, out int result) 는 문자열(string)을  숫자로 변환할 때 사용한다.

str : 변환할 숫자가 포함된 문자열

result : 변환이 성공한 경우 str에 포함된 숫자의 정수 값을 반환하고, 변환이 실패한 경우 0을 반환

int 대신에 double, int32 를 쓸 수도 있다.


string Str = Console.ReadLine();
double Num;
bool isNum = double.TryParse(Str, out Num);
if (isNum) {
    Num = Num * 2.54;
    Console.WriteLine(Num + "cm");
}
else {
     Console.WriteLine("Invalid number");
}


private void listView_CellUpdate(ListView LV)
{
    int value = 0;
    foreach (ListViewItem row in LV.Items)
    {
        int.TryParse(row.SubItems[5].Text, out value);
        if (value == 10)
        {
            row.SubItems[4].Text = "보통";
        }
    }
}


private void dataGridView_CellUpdate()
{
    int value = 0;
    for (int row = 0; row < dataGridView1.Rows.Count; row++)
    {
        int.TryParse(dataGridView1.Rows[row].Cells[5].Value.ToString(), out value);
        if (value == 10)
        {
            dataGridView1.Rows[row].Cells[5].Value = 6000;
        }
    }
}

'C# > 문법 및 기능' 카테고리의 다른 글

C# 시간 메소드  (0) 2016.01.15
C# 파일 입출력 개념 정리  (0) 2016.01.05
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
C# 메소드 오버로딩 개념잡기  (0) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
블로그 이미지

Link2Me

,
728x90

상속(Inheritance) : 부모 클래스에 정의된 데이터 및 메소드들을 파생클래스에서 이용할  수 있는 기능을  상속이라고 한다.

C#에서 파생클래스를 정의하기 위해서는 클래스명 뒤에 Colon (:)을 찍고 Base 클래스명을 써 주면 된다. 제약점은 C#에서는 파생클래스가 단 하나의 Base 클래스로부터 상속되어져야 한다는 것이다. 즉, 하나의 파생클래스는 2개 이상의 Base 클래스를 가질 수 없다.


오버로딩(Overloading)은 한 클래스 내에서 동일한 이름의 메서드를 추가 정의하는 것이다.

반면에 오버라이딩(Overriding)은 클래스간 상속 관계에서 메서드를 재 정의하는 기법이다.


두 클래스가 상속 관계에 있으면 부모 클래스의 public, protected 으로 선언된 메서드는 자식 클래스로 그대로 상속되어 자식클래스에서 사용이 가능하게 된다. 즉 이미 정의된 메서드를 재 사용하게 되는 것이다.

메서드를 오버라이딩 할 때 부모 클래스에서는 virtual 로, 자식 클래스에서는 override 키워드로 메서드를 정의해야 한다.


방법 1 : 부모 클래스에 virtual, 자식 클래스에 override 키워드를 사용하는 경우

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Override
{
    class BaseClass // 부모 클래스
    {
        public virtual void MethodA() // 부모클래스의 MethodA 메소드
        {
            Console.WriteLine("In the BaseClass ...");
            // 부모클래스로 객체를 생성하고 MethodA 메소드를 호출하면 이 문구가 출력
        }
    }
    class DerivedClass : BaseClass // DerivedClass (자식) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public override void MethodA()
        {
            // 부모클래스와 동일 메소드(매개변수 똑같음)를 자식 클래스에서 생성하는것을 오버라이딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overriding !!!");
            // DerivedClass클래스로 객체를 생성하고 MethodA를 호출하면 이 문구가 출력된다
        }
        public void MethodA(int i) // 이경우는 메소드 이름은 같은데 매개변수가 다르다. int형 변수가 입력될 경우 이 메소드가 실행된다.
        {
            // Overloading : 메소드 이름은 동일하고 매개변수가 다른경우를 오버로딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overloading !!!");
            // Derivedclass클래스로 객체를 생성하고 MethodA메소드에 매개변수(int형)을 포함해 호출하면 이 문구가 출력된다.
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.MethodA(); // 부모 객체에서 MethodA 메소드 호출 -> In the BaseClass ... 출력
            child.MethodA(); // 자식 객체에서 MethodA 메소드 호출 -> In DerivedClass ... Overriding !!! 출력
            child.MethodA(1); // 자식 객체에서 MethodA(1) 메소드 호출 -> In DerivedClass ... Overloading!!! 출력
        }
    }
}



방법 2 : 부모 클래스에 virtual 를 미정의 시, 자식 클래스에서 메소드 앞에 new를 붙이면 된다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Override
{
    class BaseClass // 부모 클래스
    {
        public void MethodA() // 부모클래스의 MethodA 메소드
        {
            Console.WriteLine("In the BaseClass ...");
            // 부모클래스로 객체를 생성하고 MethodA 메소드를 호출하면 이 문구가 출력
        }
    }
    class DerivedClass : BaseClass // DerivedClass (자식)클래스는 BaseClass(부모클래스)를 상속받는다
    {
        new public void MethodA()
        {
            // 부모클래스의 MethodA 와 이름이 똑같은데 new 를 붙이면 부모클래스의 메소드를 덮어씌운다.

            // new 를 통해 메서드를 재 정의하게 되면 부모 클래스의 원 메서드는 숨기게(가려지게) 된다.

            // 부모클래스와 동일 메소드(매개변수 똑같음)를 자식 클래스에서 생성하는것을 오버라이딩
            Console.WriteLine("In DerivedClass ... Overriding !!!");
            // DerivedClass클래스로 객체를 생성하고 MethodA를 호출하면 이 문구가 출력된다
        }
        public void MethodA(int i) // 이경우는 메소드 이름은 같은데 매개변수가 다르다. int형 변수가 입력될 경우 이 메소드가 실행된다.
        {
            // Overloading : 메소드 이름은 동일하고 매개변수가 다른경우를 오버로딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overloading !!!");
            // Derivedclass클래스로 객체를 생성하고 MethodA메소드에 매개변수(int형)을 포함해 호출하면 이 문구가 출력된다.
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.MethodA(); // 부모 객체에서 MethodA 메소드 호출 -> In the BaseClass ... 출력
            child.MethodA(); // 자식 객체에서 MethodA 메소드 호출 -> In DerivedClass ... Overriding !!! 출력
            child.MethodA(1); // 자식 객체에서 MethodA(1) 메소드 호출 -> In DerivedClass ... Overloading!!! 출력
        }
    }
}
 


실행결과


자식 클래스의 메소드 앞에 new를 붙이지 않았을 경우


오류목록에 숨기려면 new 를 붙이라고 에러 메시지를 보여준다.


예제로 사용한 코드


Override.zip



참고하면 좋은 글

ㅇ 클래스의 상속 : https://blog.hexabrain.net/142


'C# > 문법 및 기능' 카테고리의 다른 글

C# 파일 입출력 개념 정리  (0) 2016.01.05
C# int.TryParse  (0) 2015.12.25
C# 메소드 오버로딩 개념잡기  (0) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
C# 배열 개념 이해 및 실전 응용  (0) 2015.12.13
블로그 이미지

Link2Me

,
728x90

C# 에서 함수(메소드)는 동일한 것을 여러개 만들 수가 있다는 걸 알게 되었다.

유투브 동영상 강좌를 보고, 구글링으로 얻은 지식 중에서 핵심내용만 적어두려고 한다.


오버로딩(OverLoading) : 한 클래스 내에서 동일한 이름의 메서드(함수)를 추가 정의



하나의 클래스에 같은 이름을 가진 메소드(함수)를 여러개 정의 할 수 있다.

메소드 이름은 동일하지만 시그너처의 갯수는 다르게 할 수 있다.

시그너처를 유일하게 하면 메서드의 이름은 얼마든지 같을 수 있다



public class MathClass
{
    public static int Max(int i, int j)
    {
        return i > j ? i : j;     //둘 중 큰수를 반환한다
    }
    public static int Max(int i, int j, int k)
    {
        return Max(Max(i, j), k); //Max(int, int) 를 호출한다
    }
    public static int Max(int i, int j, int k, int l)
    {
        return Max(Max(i, j, k), l); //Max(int, int, int) 를 호출한다
    }
    public static int Max(int[] arrays)
    {
        int maxValue = 0;
        foreach (int i in arrays)
        {
            maxValue = Max(maxValue, i); //Max(int,int) 를 호출한다
        }
        return maxValue;
    }
}




시그너처가 다르면 에러가 발생하지 않는다.


메소드 앞의 타입(string, int, double) 은 달라도 시그너처가 같으면 에러가 발생한다.




'C# > 문법 및 기능' 카테고리의 다른 글

C# int.TryParse  (0) 2015.12.25
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
C# 배열 개념 이해 및 실전 응용  (0) 2015.12.13
C# Trackbar 기능 및 타이머 연결  (0) 2015.12.08
블로그 이미지

Link2Me

,

C# DataSet

C#/C# SQL 2015. 12. 20. 13:13
728x90

PC , 스마트폰(아이폰, 안드로이드폰) 상에서 사용하는 로컬 데이터베이스로는 SQLite 가 많이 사용된다.

SQLite 는 직접 다루게 될 때 정리를 해볼 생각이다.


DataSet 은 클라이언트 메모리 상의 데이터베이스다.


메모리상에 만드는 데이터베이스는 PC를 끄거나 프로그램을 종료하면 데이터가 날라가 버린다.

따라서, 실제 데이터베이스(오라클, MySQL, MS-SQL, SQLite, 엑셀, MS Access 등)에 있는 자료를 불러다가 DataSet 과 연결하여 작업을 하고 Update, Delete, Insert 를 수행하게 된다.

DataTable 클래스는 메모리상에 테이블을 표현하는 클래스이다.
DataSet(메모리 상의 데이터베이스)은 여러개의 DataTable 들을 포함한다.



일반적으로 SqlDataAdapter 를 이용하여 데이타를 서버로부터 가져와 메모리상의 DataSet에 할당 후 사용한다.

MySQL 과 연결하는 것은 앞에 My만 붙여준다고 이해하면 된다.


static string ConnectionString = string.Format("SERVER={0};DATABASE={1};UID={2};PASSWORD={3};",server_ip,dbname,username,password);  // 실제 연결할 DB의 정보를 입력해야 함
MySqlConnection myConn;
MySqlDataAdapter adapter;

myConn = new MySqlConnection(ConnectionString);
if (myConn.State == ConnectionState.Closed)
{
    myConn.Open();
}
string strqry ="SELECT * FROM Table_A";

strqry += " Where 조건문";

adapter = new MySqlDataAdapter(strqry, myConn);

DataSet ds = new DataSet(); // DataSet 객체에 메모리 할당
adapter.Fill(ds, "DSTables"); // DataSet에 테이블 데이타를 넣음


for 문, foreach 문, while 문을 활용하여 데이터를 콘솔화면에 출력하거나

dataGridView와 바인딩하여 dataGridView 화면에 출력한다.

또는 listView, TreeView 에 출력할 수도 있다.


if (myConn.State == ConnectionState.Open)
{
    MyConn.Close();
}


ds.Tables["DSTables"].Rows.Count 는 총 레코드수를 반환한다.

dataGridView1.DataSource = ds.Tables[0]; // DataSet을 DataGridView 컨트롤에 바인딩

ds.Tables[0].Rows.Count.ToString(); // DB에서 가져온 총 Record 수

DataTable dt = ds.Tables["DSTables"];


메모리상의 DB인 DataSet 과 실제 DB인 SQL 간에 SqlDataAdapter 를 이용하여 Select, Update, Insert, Delete 를 한다.

블로그 이미지

Link2Me

,
728x90

listView 와 textBox 을 연동하여 textBox 에서 값이 변화하면 자동으로 listView 의 해당 Line 에 변경이 발생하도록 처리하려고 했는데, 로직을 잘못 생각하여 버그가 계속 발생하는 원인을 못찾다가 겨우 해결했다.

코드를 작성할 때 Focused 가 되었을 경우에만 해당 이벤트가 발생하도록 코드를 해야한다는 걸 알아냈다.

구글링 검색해서 그런 부분까지 자세히 설명이 안되어 있다보니 오류가 발생했다.

물론 구글에 나오는 자료는 자료가 발생하는 상황이 단순한 상황이라 답변해주는 코드가 정답일 수도 있다.

하지만 내가 작성하는 코드는 다른 부분까지 엮여있어서인지 문제가 발생했고, 이 문제는 심각한 문제로 이어졌다.

물론 textBox_TextChanged 이벤트 이용을 포기하면 간단하게 해결될 수 있다. 하지만 이용자의 편의성 측면에서 매우 불편해진다.


C# listView 에서 포커스가 되지 않도록 처리하는 방법

if (listView1.SelectedItems.Count != 0)
{
    listView1.SelectedItems[0].Selected = false;
}
를 해당 이벤트에 추가해주면 된다.


listView 와 연계된 텍스트박스에서 포커스 처리하는 방법

텍스트박스에서 Alt + 화살표 방향키를 누르면 listView 선택된 행이 위아래로 변경되면서 변경된 값을 텍스트박스에 자동연동하여 처리하는 코드이다.


private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt && e.KeyCode == Keys.Down)  // Alt + 아래방향화살표키를 누르면
    {
        int index = listView1.FocusedItem.Index;
        listView_FocusedLIneChange(listView1, index + 1);
    }
    if (e.Alt && e.KeyCode == Keys.Up)  // Alt + 윗방향화살표키를 누르면
    {
        int index = listView1.FocusedItem.Index;
        listView_FocusedLineChange(listView1, index - 1);
    }
}

private void listView_FocusedLineChange(ListView LV, int index)
{
    if (index < 0 || index >= LV.Items.Count || LV.Items.Count == 0) return;
    LV.SelectedItems.Clear();
    LV.Items[index].Selected = true;
    LV.Items[index].EnsureVisible();
    LV.Items[index].Focused = true;
    LV.Focus();
    listView_Focused();  // User Make 함수
    LV.Items[index].BackColor = SystemColors.Highlight;
    if (LV == listView1)
    {
        textBox1.Focus();
        textBox1.SelectionStart = textBox1.Text.Length; // 마지막을 선택
        textBox1.ScrollToCaret(); // 선택된 위치에 스크롤을 움직인다
    }
    else if (LV == listView2)
    {
        textBox2.Focus();
        textBox2.SelectionStart = textBox2.Text.Length;
        textBox2.ScrollToCaret();
    }
}


블로그 이미지

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# listView 에서 칼럼 너비를 지정하는 방법이다.

사용법이 미숙해서인지 테스트를 하다보면 원하지 않는 결과가 나와서 당황스러워 적어둔다.


listView1.Columns[3].Width = 0;  // 칼럼을 보이지 않게 처리
listView1.Columns[1].Width = -2; //Text Column Header 셀 자동 크기
listView1.Columns[1].Width = 679;


listView1.Columns[1].Width = -2; 로 지정하면, 해당 칼럼의 Text 길이에 따라 가변적으로 변한다.

길이가 변하지 않고 고정적으로 하고 싶다면, 숫자를 직접 지정해준다.


Header 칼럼의 사이즈를 임의로 조정하지 못하게 하는 방법은

ListView.ColumnWidthChanging 이벤트(열 너비가 변경되고 있을 때 발생)를 이용한다.


마우스 더블클릭하여 생성된 코드에다가 아래와 같이 내용을 추가한다.

private void listView1_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
{
    e.NewWidth = listView1.Columns[e.ColumnIndex].Width;
    e.Cancel = true;
}


블로그 이미지

Link2Me

,
728x90

C# List 는 동적으로 할당하는 가변배열(동적배열)이라고 볼 수 있는데 좀 더 강력하다.

List 클래스는 닷넷 프레임워크를 바탕으로 만들어져 있어서 배열로는 할 수 없는 다양한 것을 할 수 있다.


List <T> 변수명 = new List <T>();


T에 원하는 타입을 지정하면 치환이 가능하다.

int, float, string 외에 어떠한 형태의 타입도 지정이 가능하다.


보통 예제가 콘솔에 뿌리는 형태인데 난 그냥 폼에 뿌리는 방식으로 해봤다.


using System;
using System.Collections.Generic;  // 리스트 사용하기 위해
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace List
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            List<int> number = new List<int>();
 
            number.Add(10);  // 리스트 추가
            number.Add(20);  // 리스트 추가
            number.Add(30);  // 리스트 추가
            number.Add(40);  // 리스트 추가
 
            var sb = new StringBuilder();
            foreach (var item in number)
            {
                sb.AppendLine(item.ToString());                
            }
            textBox1.Text = sb.ToString();
 
            number.Remove(30); // 리스트 삭제
            number.RemoveAt(1); // 해당 인덱스의 리스트 삭제
            number.Insert(0100); // 0번째 인덱스에 100 추가
 
            sb = null;  // 변수 초기화
            sb = new StringBuilder(); // 메모리 재할당
            for (int i = 0; i < number.Count; i++)
            {
                sb.AppendLine(number[i].ToString());
            }
            MessageBox.Show(sb.ToString());
        }
    }
}


실행결과는 아래와 같다.

텍스트박스에 뿌리기 위해 StringBuilder 를 이용하여 값을 합쳐나갔고,

리스트를 삭제, 삽입하는 결과는 메시지박스에 표시되도록 했다.

소스코드를 복사해서 http://colorscripter.com/ 에 붙여넣기를 하고 언어를 C#을 선택한 다음, 클립보드에 복사를 선택하여 붙여넣기를 하면 된다.


배열과 달리 리스트는 원하는 곳에 데이터를 추가(Insert)할 수도 있다.

필요할 때마다 Add 를 사용해서 리스트를 추가해주고

Remove 나 RemoveAt 을 이용하여 리스트를 삭제할 수 있다.

삭제가 되면 리스트의 index 는 자동으로 하나씩 당겨진다.

배열에서 카운트는 number.Length 인데, 리스트에서는 number.Count 이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        private void button2_Click(object sender, EventArgs e)        {
            int[] arr = new int[3]; // New array with 3 elements.
            arr[0= 2;
            arr[1= 3;
            arr[2= 5;
 
            List<int> number = new List<int>(arr); // 배열을 리스트에 복사
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            List<int> number = new List<int>();
 
            number.Add(10);  // 리스트 추가
            number.Add(20);  // 리스트 추가
            number.Add(30);  // 리스트 추가
            number.Add(40);  // 리스트 추가
 
            int[] arr = number.ToArray(); // 일반 배열로 반환
        }
cs


List 객체는 어떤 유형이든 저장할 수 있다.

List<T> MSDN : https://msdn.microsoft.com/ko-kr/library/6sh2ey19%28v=vs.110%29.aspx

에서 다양한 기능을 확인할 수 있다.

블로그 이미지

Link2Me

,
728x90

배열 : 같은 형식의 여러개의 요소를 가지는 데이터 구조


배열을 선언할 때에는 유형(int, string, float 등) 바로 뒤에 꺽쇠 괄호를 붙인다.

int[] arr1;  // arr1 라는 참조변수는 null 로 설정된다.

 * 배열 선언문은 배열형 변수를 선언하는 것이지, 메모리를 할당하는 것은 아니다.

    배열은 참조형이므로 변수 자체가 실제 데이터를 저장하지 않는다.

arr1 = new int[5];  // 배열은 객체이므로 new 키워드를 써서 배열 객체를 생성

  * 배열 뿐만 아니라 모든 참조형은 new 연산자로 실제 메모리를 할당받아야 한다.


선언문과 할당문을 두 줄로 쓰는 것이 번거롭다면 int[] arr1 = new int[5]; 로 해도 된다.


[5] 꺽쇠 괄호안에 들어가는 숫자를 index 라고 부르며, 배열에서 index 는 0부터 시작한다.

int[] arr1 = new int[] { 1, 2, 3, 4, 5} 처럼 초기값을 할당할 수도 있다.

배열의 길이 5를 생략한 경우로, 이 경우에는 배열의 각 인덱스의 개수는 자동으로 세어준다.


텍스트 파일을 읽어서 Split 키워드를 이용해서 분할하여 배열로 담아야 하는 경우에는 배열의 크기를 알 수가 없는 경우가 대부분이다.

string[] strs = readText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

줄바꿈(\r\n) 구분자로 분할해서 배열 변수 strs 에 담으라는 의미다. (Android 에서 줄바꿈은 \n )

strs.Lenght ; // 배열의 길이를 반환


문자열을 문자 배열로 만들고 싶을 때에는

string text = "My Array Test";

char[] Text = text.ToCharArray(); // 문자열을 문자 배열로 변경

배열 변수 사용중 초기화가 필요한 시점에서 아래 명령어로 초기화를 해준다.

Array.Clear(strs, 0, strs.Length);  // 배열 초기화

  * 배열은 일부러 해제하지 않아도 닷넷라이브러리에 쓰레기 수집 기능이 있어서

    더 이상 사용하지 않는 배열은 해제된다.

    배열 뿐만 아니라 모든 참조형에 공통적으로 적용되는 사항이다.

  * 배열 초기화를 해주는 이유는 배열을 사용하고 다시 다른 배열로 일부만 복사하여 사용하다보니

    처리속도가 늦어지는 것 같아서 배열을 바로 바로 초기화를 해주었더니 속도가 엄청 빨라졌다.


Array.Reverse(strs); // 배열 인덱스 뒤집기는 Array.Reverse(배열명) 을 사용한다

Array.Sort(strs); // 배열 소팅은 Array.Sort(배열명)을 사용한다.


배열 복사를 하고 싶을 때에는

string[] strs = readText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

string[] copy_strs = new string[strs.Lenght];

Array.Copy(strs, copy_strs, strs.Length);


그런데 배열 복사의 index 수가 다르고, 갯수를 정확하게 파악하기 어려운 경우라면 어떻게 복사를 해야 할까?

아래 코드는 smi 자막을 파싱하여 읽어들이기 위해 만든 코드이다.

로직 순서는

1. 파일을 끝까지 읽어들인다.

2. 원하는 부분을 Split 으로 잘라낸다.

3. 잘라낸 부분을 배열로 담는다.

4. 배열로 담긴 부분에서 부분적으로 원하는 자료를 추출하기 위해

    StringBuilder 를 이용하여 조건에 맞는 배열을 합쳐서 하나의 파일로 만든다.

5. 다시 원하는 결과를 뽑아내기 위해 Split 으로 분리한다.


string[] bodyseparator = new string[1] { "<SYNC Start=" };
string[] bodyLines = bodyinfo.Split(bodyseparator, StringSplitOptions.RemoveEmptyEntries);
bodyinfo = null;  // 배열로 전달한 값은 초기화

var sb1 = new StringBuilder();
var sb2 = new StringBuilder();

for (int i = 1; i < bodyLines.Length; i++)
{
    if (bodyLines[i].Contains(ClassName1))
    {
        sb1.Append("<SYNC Start=" + bodyLines[i]);
    }

    if (bodyLines[i].Contains(ClassName2))
    {
        sb2.Append("<SYNC Start=" + bodyLines[i]);
    }
}
Array.Clear(bodyLines, 0, bodyLines.Length);  // 배열 초기화


아직 List 개념만 익힌 상태라서 실전 활용을 못해봐서 좀 무식하게 처리했을 수도 있다.

하나씩 기능을 익히면서 최적화된 코드를 만들 수 있는 날이 오겠지.....

블로그 이미지

Link2Me

,
728x90

문자열에서 숫자만 추출해야 할 경우가 있다.

정규식을 이용하여 문자열에서 숫자만 추출하면 편리하다.

하지만 원하지 않는 결과가 나올 수도 있다는 걸 알았다.

정규표현식 설명 잘된 곳 : http://www.nextree.co.kr/p4327/


using System.Text.RegularExpressions;


// 숫자만 추출
_body = Regex.Replace(_body, @"[^0-9]", "");

// 영문자만 추출
_body = Regex.Replace(_body, @"[^a-zA-Z]", "");

// 한글만 추출
_body = Regex.Replace(_body, @"[^가-힣]", "");


문자열 전체가 숫자인지 검사하여 숫자이면 true 를 반환하는 bool 함수

/// <summary>
/// 문자열이 숫자인지 검사하여 숫자이면 true 를 반환
/// </summary>
public bool isNumeric(string str)
{
    double Num;
    bool isNum = double.TryParse(str, out Num);
    if (isNum)
    {
        return true;
    }
    else
    {
        return false;
    }
}


예외 처리는 무겁기 때문에 꼭 필요하지 않다면 가급적 발생하지 않도록 코딩해야 한다.

문자열에서 숫자만 추출하는 경우에 에러가 발생하지 않을 것이라고 생각한 것 때문에 버그 잡이 하느라고 몇시간을 허비했다.


System.Math.Truncate(double형 숫자); 를 추가하고 나서야 원인 해결이 되었다.


예제를 하나 만들어서 작성해둔다.

private void btnRegex_Click(object sender, EventArgs e)
{
    string msg1 = "2000.34567 을 Math.Truncate 함수를 사용하면 ";
    string msg2 = "2000.34567 을 정규식으로 숫자만 추출하면 ";
    string msg3 = "숫자로 된 문자열에서 double.Parse 함수를 이용하면 ";

    double a = 2000.34567;
    double quotient = System.Math.Truncate(a); // 정수형만 구하기

    string _body = "2000.34567";
    double b = double.Parse(_body);
    _body = Regex.Replace(_body, @"[^0-9]", "");

    MessageBox.Show(msg1 + quotient.ToString() + Environment.NewLine + msg2 + _body + Environment.NewLine + msg3 + b.ToString());
}


결과는

정규식을 잘못 사용하면 소수점을 무시하고 전혀 엉뚱한 결과를 초래할 수 있다는 것 !!!

숫자로 결과를 만드는 경우에는 철저한 검증을 하지 않으면 오류가 나기 쉽다는 걸 몸소 체험했다.


private void checkForUpdate()
{
    // 문자열에서 숫자만 추출해서 버전을 비교하여 서버 버전이 높으면 업데이트 파일 다운로드
    if (int.Parse(Regex.Replace(getLVersion(), @"\D", "")) < int.Parse(Regex.Replace(getSVersion(), @"\D", "")))
    {
        btnDownload.Visible = true;
        SetupGuide.Visible = true;
    }
    else
    {
        SetupGuide.Visible = true;
        SetupGuide.Text = "현재 최신버전을 사용하고 있습니다";
    }
}

블로그 이미지

Link2Me

,
728x90

Trackbar.Scroll 은 마우스나 키보드 조작을 통해 스크롤 상자가 이동될 때 발생한다.
TrackBar.ValueChanged : 트랙 표시줄의 Value 속성이 스크롤 상자 이동이나 코드 조작을 통해 변경될 때 발생



private void trackBar1_Scroll(object sender, EventArgs e)
{
    label1.Text = trackBar1.Value.ToString();
}


위 경우에는 마우스로 수동으로 Scroll 바를 움직여서 값을 변동되게 하는 방법이다.


Timer 와 연결해서 Trackbar 가 자동으로 움직이게 하려면

도구상자에게 timer 를 선택해서 Form에 Drag & Drop 한다.

그리고 timer1 이벤트를 생성한다.


private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Enabled = true;
    trackBar1.Value += 1;
    if (trackBar1.Value >= trackBar1.Maximum) timer1.Enabled = false;
    label1.Text = trackBar1.Value.ToString();
}


타이머를 ON 하고 trackBar1 의 값이 1씩 증가하도록 등록한다.

trackBar1 의 최대값을 넘어가면 타이머를 종료시킨다.

그리고 변동되는 값을 label1.Text 에 기록한다.


MP3 플레이에서 노래가 재생될 때 구동시키려고 배우고 있는 중이다.


노래와 연결한다고 하면 아래와 같은 것이 필요하지 않을까 싶다.

trackBar1.Maximum 의 값은 100 으로 놓는다.

lbl_Time.Text = "00:00";  // 노래 한곡의 전체 재생시간

lbl_Duration.Text = "00:00";  // 플레이되는 동안의 시간 표시


Play 상태에서는

timer1.Enabled = true;

PlayState = true;


Stop 상태에서는

timer1.Enabled = false;

PlayState = false;

trackBar1.Value = 0;


이 밖에 또 뭐가 필요할지, 어떻게 구현해야 할지는 좀 더 샘플을 찾아보고 정리를 해보려고 한다.

초보자라 갈 길이 참으로 멀다.


블로그 이미지

Link2Me

,