개발 노트

알람 작업 본문

프로그래밍/C#

알람 작업

알 수 없는 사용자 2024. 1. 31. 10:38

[알람 작업을 위한 데이터그리드뷰 속성 파악]

 

AllowUserToAddRows : 행 추가 옵션이 사용자에게 표시되는지 여부 확인

 

AllowUserToDeleteRows : 사용자가 DataGridView에서 행을 삭제 할 수 있는지 여부 확인

 

AllowUserToOrderColumns : 수동으로 열의 위치를 변경 할 수 있는지 여부 확인

 

AllowUserToResizeColumns : 사용자가 열의 크기를 조정할 수 있는지 여부 확인

 

AllowUserToResizeRows : 사용자가 행의 크기를 조정할 수 있는지 여부 확인

 

AlternatingRowsDefaultCellStyle : 홀수 번호 행에 적용된 기본 셀 스타일

======================================================================================

 

알람 작업 - 텍스트 파일 - 데이터그리드 뷰 - 메모리

 

코드를 구성할때 자료구조 메모리에 값을 저장하고, 그 저장된 메모리 값을 이용하여 데이터 그리드 뷰에 값을 전달하고,

데이터 그리드 뷰에 값을 저장했다면 텍스트 파일에 저장한 값을 쓰는 구조로 이루어진다. 여기서 처음으로 이루어져야 하는 것은 메모리에 값을 미리 저장후 꺼내다 써야하는 것 같다.

 

특정 열을 선택하여 수정을 하기 위한 폼을 열고 그 안에서 작업을 하여 작업한 값이 데이터그리드뷰 특정 열에 수정된 값이 들어가게 한다.

 선택한 row값을 누르고 선택된 index값을 int index에 저장

행에 있는 cell위치들의 값들을 자료형 메모리에 저장.

메모리 저장후 폼2에서 작업하는 도구들 밸류 값에 저장한 메모리를 삽입.

이후 다른 폼을 연다.

다른 폼에서 작업한 값들을 메모리에 새로 저장한 후, 새로 저장된 메모리를 데이터그리드뷰 선택된 행과 cell값에 다 넣어준다.

이후 파일을 열고 값을 넣기 위해  for문으로 0부터 마지막 열까지 카운트를 해주고(배열은 0부터시작)  

데이터그리드뷰 클래스로 변수하나 설정 후 데이터그리드뷰 행의 배열값들을 넣어준 후, 새로 저장된 밸류 값들을 메모리에 넣고 String line에 구성했던 한줄로 값을 넣어주어 반복한다.

 

같은 맥락으로 버튼을 눌러 수정된 값을 저장하거나 취소하려고 할 때,

공동으로 사용할 변수 설정하고,  취소 저장 버튼마다 누르면 활성화 할 상태 값 넣기(OK, Cancle)

이후 조건문으로 사용하여 저장 취소버튼이 제 기능을 할 수 있게 한다. 


[데이터그리드 뷰에 프로그레스 바 기능하기]

https://stackoverflow.com/questions/4646920/populating-a-datagridview-with-text-and-progressbars

 

Populating a DataGridView with Text and ProgressBars

I am creating a multi-threaded application in which each thread will appear as a row in my DataGridView. I want a ProgressBar in each row indicating the corresponding thread progress. The question...

stackoverflow.com

이 채널에 클래스를 참고하여 프로그레스 바를 만들었다.

 

이 채널에 클래스를 활용하여 데이터그리드 뷰 컬럼을 만들고 값을 넣어서 보여주는데, 혹시나 미리 작업한 데이터그리드 뷰에서 참고하려면 데이터 그리드 뷰에 값을 넣어줘야한다는 사실을 잊지않는게 중요하다.

 

  public void Data_Load()
  {
      /*DataGridViewProgressColumn progressColumn = new DataGridViewProgressColumn();*/
      dataGridView1.Rows.Clear();
      string line;
      StreamReader rd = new StreamReader(@"./MyTimer.txt");



      while (!rd.EndOfStream)
      {


          

          line = rd.ReadLine();
          Console.WriteLine(line);
          if(line.Trim() == "")
          {
              break;
          }
          string[] cols = line.Split(',');

         /* MessageBox.Show(cols[12].ToString());*/
          dataGridView1.Rows.Add(cols[0], cols[1], cols[2], cols[3], cols[4], cols[5], cols[6], cols[7], cols[8], cols[9], cols[10], cols[11], cols[12]);
          dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[12].Value = Convert.ToInt32(cols[12].ToString());
      }

      rd.Close();
      
    

  }

이 코드는 텍스트 파일에서 데이터를 불러와 데이터그리뷰 컬럼과 행에 값을 저장하여 보여주는 코드인데,  프로그레스 바를 설정한 cols[12]의 값에 직접적으로 값을 넣어주지 않고 텍스트 파일을 사용하여 값을 보여주는 것이기 때문에 

직접 데이터그리드 뷰에 값을 넣어주어야만 프로그레스바 값이 활성화 되는 것을 확인했다.

 

dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[12].Value = Convert.ToInt32(cols[12].ToString());

 

이 부분을 넣으며 프로그레스 바가 활성화 된 것인데, 직접적으로 데이터그리드뷰 행마다 cell[12]인 13번째 값(0~12)에

텍스트에서 불러온 cols[12]의 값을 직접 넣어줌으로써 데이터그리드 뷰에 활성화가 된다.

 


[데이터그리드 뷰 시간 값을 통해 알람이 울리기 위한 작업]

              DateTime currentTime = DateTime.Now;
             foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (Convert.ToBoolean(row.Cells[0].Value) == true)
                    {
                        if (Convert.ToBoolean(row.Cells[(int)currentTime.DayOfWeek + 3].Value) == true)
                        {
                       
                            DateTime rowTime;
                            if (DateTime.TryParse(row.Cells[1].Value?.ToString(), out rowTime))
                            {
                                if (currentTime.Hour == rowTime.Hour &&
                                currentTime.Minute == rowTime.Minute &&
                                currentTime.Second == rowTime.Second)
                                {
                                }
                            }
                        }
                    }
                }

여기서  foreach (DataGridViewRow row in dataGridView1.Rows) 이 코드로 시작하여 datagridview1에 Rows들을 탐색한다.

 

그 이후  if (Convert.ToBoolean(row.Cells[0].Value) == true) 사용 유무를 설정한 Cell[0]값이 true를 확인하여 그 다음 조건문을 확인한다.

 

if (Convert.ToBoolean(row.Cells[(int)currentTime.DayOfWeek + 3].Value) == true) 이 코드는 Cell의 밸류

(int)currentTime.DayOfWeek + 3 가  참이면 그 다음 조건문을 실행하는데 여기서 중요한 점이 있다.

이 코드는 요일별 체크박스를 체크하는 조건문인데 나의 요일 cell값 위치는 Cell[3~9]에 있다.

 

그러면 왜 DayOfWeek + 3 로 설정이 되었을까 

그 이유는 요일 별 주어진 값들이 있다

 

요일은 열거형으로써 일요일 : 0 값부터 시작하여 월 : 1 ~ 토 : 6이 설정되어있다.

그래서 이렇게 일 ~ 토로 위치시키어 DayOfWeek를 활용하여 실제 그 요일의 값 + 3이 적용하여 

예를 들어 일요일이면 0 + 3의 값이기 때문에 Cell[3]이 되어 만약 일요일 체크박스가 활성화 되어있다면 그 해당의 조건문이 활성화 되어 다음 조건문으로 넘어갈 수있다. 

 

그리고 또한 요일별마다 참 거짓 체크를 하지 않고, 한줄로 조건문을 만들 수 있게 된 것이다.

 

 

마지막 조건문으로써

DateTime rowTime;
if (DateTime.TryParse(row.Cells[1].Value?.ToString(), out rowTime))
{
    if (currentTime.Hour == rowTime.Hour &&
    currentTime.Minute == rowTime.Minute &&
    currentTime.Second == rowTime.Second)

 

시간 값을 설정한 Cell[1]번째의 값을 DateTime자료형을 가진 rowTIme으로 반환하여  현재 시간인 currentTime의 시분초 값과 Cell[1]의 값을 가진 rowTime 타임의 시분초가 같다면 그때서야 알림이 울릴 수 있는 모든 조건이 완성이 된다.


[데이터그리드 뷰 알람 정렬]

 

https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.forms.datagridview.sort?view=windowsdesktop-8.0

 

DataGridView.Sort 메서드 (System.Windows.Forms)

DataGridView 컨트롤의 내용을 정렬합니다.

learn.microsoft.com

이 채널의 데이터그리드뷰 정렬을 사용하였다.  하지만 알람 작업을 하면서 텍스트 파일을 가져와서 데이터그리드 뷰에 적용하는 기반으로 했기 때문에 실질적으로 해당하는 코드는 이 부분이다.

 string[] lines = File.ReadAllLines(filePath);

  Array.Sort(lines);
  if (direction == ListSortDirection.Descending)
  {
      Array.Reverse(lines);
  }

텍스트 파일에 있는 라인별 내용들을 line에 담아서  위 채널에 있는 설정된 코드로  헤더 타이틀 화살표를 클릭했을때 

Descending으로 할것이냐 Ascending으로 할 것이냐 조건문을 주어 간단히 텍스트 파일의 라인별 정렬이 가능하다.

 


[데이터그리드 뷰 선택된 열의 알람 삭제]

            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                if (dataGridView1.Rows[i].Selected == true)
                {
                    var mb = MessageBox.Show("정말로 삭제하시겠습니까?", "알람 삭제", MessageBoxButtons.YesNo);
                    if (mb == DialogResult.Yes)
                    {
                        dataGridView1.Rows.Remove(dataGridView1.Rows[i]);
                        UpdateTextFile();
                    }
                    else
                    {

                    }
                }
            }

이 것은 데이터그리드 뷰에 삭제하고 싶은 열을 클릭해서 삭제하는 코드이다. 하지만 늘 말했듯 텍스트 파일을 기반으로 했기 때문에 해당열을 삭제해도  다시 디버그를 했을때는 삭제 전의 값으로 돌아 온다.

 

이유는 데이터그리드 뷰의 값만 삭제했지 텍스트 파일의 값을 삭제한게 아니기 때문이다.

 

 private void UpdateTextFile()
 {

     List<string> lines = new List<string>();
     foreach (DataGridViewRow row in dataGridView1.Rows)
     {
         string line = string.Join(",", row.Cells.Cast<DataGridViewCell>().Select(cell => cell.Value.ToString()));
         lines.Add(line);
     }

     File.WriteAllLines(@"./MyTimer.txt", lines);
 }

그래서 이 함수를 이용하여 삭제 이후의 데이터 그리드 뷰의 값들을 lines에 넣어주어  File.WriteAllLines함수로 저장한 lines를 해당 텍스트 파일 경로로 가서 차례대로 값을 넣어준다.

 

즉, 데이터 그리드 뷰에서 선택된 행의 값들을 삭제하고 그 삭제된 값을 기반으로 lines에 값을 넣어준다음 텍스트 파일에 넣어서 다시 로드 시키면된다.


[ini파일을 활용한 알람 시간, 알람 볼륨 저장된 값 불러오기]

이번에 한 작업은 ini 파일을 통해서 값을 저장하고 불러와서 실행창에 저장한 값을 보여주는 작업이다.

 

총 2개의 작업을 했는데 하나는 10분동안 알림 울리기, 5분 동안 알림 울리기, 설정 없음이란 라디오 버튼 3개를 활용해서 

초기 설정은 설정없음으로 하되 다른 버튼을 눌르고 다시 시작했을 때 변경된 값이 설정되게 하는 것이다.

 

다른 하나는 알람 추가를 할때 고정된 볼륨 값에서 볼륨을 움직이고 다시 실행했을 때 그 볼륨 값이 고정 되게 하는 것이다.

 

막상 할때는 해맸는데  구조는 간단했다.

 

먼저 ini파일 함수를 활용할 수 있는 DIIImport를 이용했다.

  [DllImport("kernel32")]
  static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

  [DllImport("kernel32")]
  private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

 public void Form1_Load(object sender, EventArgs e)
 {
     if (File.Exists(fileiniPath) == false)
     {
        FileStream fsIni= File.Create(fileiniPath);
        fsIni.Close();
        WritePrivateProfileString("limitedtime", "limitedtime", "-1", fileiniPath);
        WritePrivateProfileString("value", "value", "50", fileiniPath);

        
     }
     if (File.Exists(filetxtPath) == false)
     {
        FileStream fsTxt = File.Create(filetxtPath);
         fsTxt.Close();
     }


     GetPrivateProfileString("limitedtime", "limitedtime", "", sblimitedtime, sblimitedtime.Capacity, Application.StartupPath + @"./MyTimer.ini");
     GetPrivateProfileString("value", "value", "", sbvalue, sbvalue.Capacity, Application.StartupPath + fileiniPath);

     limitedtime = Convert.ToInt32(sblimitedtime.ToString());
     if (limitedtime == -1 )
     {
       
         rdblimitedtimenull.Checked = true;
     }
     else if (limitedtime == 300)
     {
       
         rdblimitedtime5min.Checked = true;
     }
     else if (limitedtime == 600)
     {
        
         rdblimitedtime10min.Checked = true;
     }
 }
 
 
  private void btnalarmadd_Click(object sender, EventArgs e)
 {
 	  GetPrivateProfileString("value", "value", "", sbvalue, sbvalue.Capacity, Application.StartupPath + fileiniPath);
  	  volume = Convert.ToInt32(sbvalue.ToString());
      
      Form2 tm_select = new Form2();
      tm_select.ShowDialog();
      
      volume = tm_select.trackBar1.Value;

	  sbvalue.Clear();
	  sbvalue.Append(volume.ToString());
	  WritePrivateProfileString("value", "value", sbvalue.ToString(),  Application.StartupPath + fileiniPath);
}

  private void rdblimitedtime5min_CheckedChanged(object sender, EventArgs e)
  {
      WritePrivateProfileString("limitedtime", "limitedtime", "300", fileiniPath);
      limitedtime = 300;
  }

  private void rdblimitedtimenull_CheckedChanged(object sender, EventArgs e)
  {
      WritePrivateProfileString("limitedtime", "limitedtime", "-1", fileiniPath);
      limitedtime = -1;
  }

  private void rdblimitedtime10min_CheckedChanged(object sender, EventArgs e)
  {
      WritePrivateProfileString("limitedtime", "limitedtime", "600", fileiniPath);
      limitedtime = 600;
  }

간략하게 설명하면 form1_load에서 파일이 존재하지 않으면 파일 생성후 파일을 닫고 그 이후 ini파일에 값을 쓰는 WritePrivateProfileString함수를 쓰고 GetPrivateProfileString함수로 그 값을 불러온다.

 

 limitedtime = Convert.ToInt32(sblimitedtime.ToString());
 if (limitedtime == -1 )
 {
   
     rdblimitedtimenull.Checked = true;
 }
 else if (limitedtime == 300)
 {
   
     rdblimitedtime5min.Checked = true;
 }
 else if (limitedtime == 600)
 {
    
     rdblimitedtime10min.Checked = true;
 }

이 작업은 10분,5분, 설정없음의 알람시간을 처리하기 위해 int타입으로 변경후 그 값에 해당하면 그 해당 라디오 체크를 참으로 하고 rdblimitedtime의 라디오 버튼에게

 WritePrivateProfileString("limitedtime", "limitedtime", "300", fileiniPath);
 limitedtime = 300;

이러한 값들을 설정한다.

 

마지막으로 알람추가버튼에서의 작업은 추가창인 form2가 나오기 전  GetPrivateProfileString함수로 볼륨의 밸류값을 불러와 실제 들어갈 트랙바 volume에 값을 넣어주고 form2를 활성화 시킨다.

 

그 이후 tm_select.ShowDialog(); 를 통해 form2가 활성화가 되면, form2에서 작업한 다음

 

volume = tm_select.trackBar1.Value;

sbvalue.Clear();
sbvalue.Append(volume.ToString());
WritePrivateProfileString("value", "value", sbvalue.ToString(),  Application.StartupPath + fileiniPath);

다시 볼륨에 값을 넣고 그 저장된 볼륨값을  WritePrivateProfileString함수에 넣어준다.

(Clear후 Append를 통해 기존의 값을 지우고 새 값을 추가 시켰다.)


 

'프로그래밍 > C#' 카테고리의 다른 글

c# 배열  (0) 2024.02.06
c# 클래스  (0) 2024.02.05
C# 기초 문법 정리  (0) 2024.01.24
C# 자료형  (0) 2024.01.24
바이너리파일 공부하기  (0) 2022.04.22