반응형

C#에서 Line Chart를 사용하고 있는데

Series를 2개 쓰면서 Y축을 주,보조를 사용하게 되었다.

그런데 어느라인이 어떤 축을 사용하는지 명확하지가 않아

표시를 하려는데, 이거 검색으로 도저히 안나오더라.


그래서.. 클래스를 하나씩 하나씩 뒤지면서 테스트해보다가 찾아냈다.


힘들었다... ㅠㅠ





찾아냈지만 뭔가 허무하군.. 적용된 것만 결과물로...




반응형
반응형
매우 간단하다...
그러나 매번 까먹는다는...

결과









반응형
반응형

오늘은 삽질을 꽤나 오래 했다.

DataGridView 간 DataRow를 이동시키려고 했는데 자꾸 예외가 떳다.

상황은 DataGridView에 DataTable을 바인딩 시키고 클릭한 Row를 삭제하고 옆에 있는 DataGrid에 옮기는 것이다.


이 상태에서 홍길동을 클릭하면 오른쪽 으로 옮겨가는 것을 할 것이다.


이런식이다.


   

코드는 이러하다.

dataGridView.DataSource에 DataTable을 넣고 CellClick 이벤트가 발생하면 선택된 Row를 오른쪽에 추가하고 

선택된 Row를 삭제하는 것이다.


우선 첫번째 발생했던 문제는 dataGridView2.Add(row)를 할 경우 발생한다.

위처럼 DataTable을 변경하는 것이 아니라 직접 dataGridView에서 수정하려고 할 경우 바인딩 되어 있어 안된다고 에러가 발생한다. 따라서.. 방법은 바인딩 된 DataTable을 수정하는 것이다.


두번째 발생했던 문제..

선택한 Row를 어떻게 DataRow로 변경할 것인가.!!!!

구글링을 쭉 해본결과 찾아냈다.



이런 식으로하면 해결 !! 어느 외국 커뮤니티에서 발견하였다. 


DataGridViewRowCollection to DataRow 로 검색했던것같다.




세번재 발생한 문제 !!!!!

dt2.Rows.Add(row) 를 할때 발생한다.

"이 행은 이미 다른 테이블에 속해 있습니다" 라는 에러 인데.. 이것도 한참을 헤맨 결과 찾았다.

dt2.Rows.Add(row.ItemArray);


MSDN에 나오니 자세히 보면 될것 같다.

















반응형
반응형

Server/Client 프로그램을 만들던 중

Client가 로그인이나 다른 연결 시도 시 지연이 될 때가 있어서 지연되는 동안 ProgressBar를 띄우려고 했었다.

그런데.. 이것이 닫기버튼이 있어서 예상치 못하게 종료가 되면 ProgressBar가 있는 Form을 닫는 문장에서 에러가 발생했다.

그래서 닫기 버튼을 없애기로 하였다..


우선 기본적으로 셋팅을 하면


위의 사진처럼 최소, 최대, 닫기 버튼이 나온다.


이제 폼의 속성 창으로 이동해서 창 스타일에 가보면

ControlBox 가 True로 되어 있는 것을 확인할 수 있다.

이것이 최소,최대,닫기 버튼에 관한 속성이다.


False로 바꾸어 주자.


False로 바꾼 후 폼을 확인해 보면



이처럼 변한 것을 확인할 수 있다.


닫기 버튼이 없으므로 프로그램상에서 종료해주지 않는이상 계속 떠있게 된다.




반응형
반응형

int 형 정수만 입력을 받아야 하는 일이 생겼다.

만약에 입력을 다 받은 후 검사를 하려면 소스코드가 엄청 길어질 것만 같아서 

방법을 찾아 보았다. 역시나 방법은 있더라.

 

출처 : http://valkyurey.tistory.com/28

 

소스코드를 보면

private void txtInterval_KeyPress(object sender, KeyPressEventArgs e)         
{             //숫자만 입력되도록 필터링             
	if(!(char.IsDigit(e.KeyChar) || e.KeyChar == Convert.ToChar(Keys.Back)))    //숫자와 백스페이스를 제외한 나머지를 바로 처리             
    {          
    	e.Handled = true;             
    }         
}

예전 코드를 넣던 방식이 안되어서.. 

 

 

위와 같다.

간단히 설명하자면 키가 눌렸을 때 char.IsDigit 메소드로 숫자 인지 확인해서 아닌경우는 바로 True로 처리

백스페이스 기능도 필요하므로 Convert.ToChar(Keys.Back)로 백스페이스인지 확인하여 필터링.

 

생각보다 간단하다. 이런식으로 이벤트를 처리하면 간단하다는 걸 느꼇다.

한글 입력 안되게 하는것도... 알아봐야 할텐데... 

찾아보니 많이 나온다. 나중에 정리 하는걸로.

 

 

 

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

 

드디어.. 한글 입력 안되게 하는 아주 간단한 방법을 알아왔다.

아... 어이가 없겠지만 VB에서 힌트를 얻었고 , C#도 동일 하다.

 

우선 TextBox 속성에 가보면 ImeMode가 있다. 

이 모드가 기본 값이 No Control일 것이다.

 

이것을 Disable로 바꾸면 한글로 되어 있는 상태에서 키를 눌러도 영어가 입력되는 것을 볼 수 있다.

 

이거.. 그림 넣을때 도형으로는 못넣는것인가 ? 아시는 분 ?

 

아무튼 이런식으로 한글 입력을 막을 수 있다.

 

IME mode에 alpha 나 alpha full 로 해보았으나 한글 입력이 되어서 disable이 제일 효율적인 방법인것 같다.

 

반응형
반응형

Timer에 각각 다른 인자를 전달하여 생성을 하려고 하였다.

그런데 CallBack만 사용해서는 인자 1개밖에 전달이 되지 않았다.

방법을 찾던 중 MSDN에 생성자 관련 예제가 있어 확인해보니 Class를 생성하여 여러개의 인자를 전달하지 않고도 

각각 다른 값을 가지고 Timer를 생성할 수 있었다.


출처 : https://msdn.microsoft.com/ko-kr/library/2x96zfy7(v=vs.110).aspx




기존 사용하던 소스 코드.


System.Threading.Timer TimerTest;


public MainForm()

{

InitializeComponent();

TimerTest = new System.Threading.Timer(testProc, "test", 1000, 10000);

}


private static testProc(object test)

{

MessageBox.Show(test.ToString());

}


위 처럼 할 경우 10초에 한번씩 "test" 라는 메시지 박스가 생성이 된다.

더 많은 인자가 필요해서 위의 출처에 따라 클래스를 만들고. Test를 진행해보았다.



    class Program

    {

        private static System.Threading.Timer[] testTimer;


        static void Main(string[] args)

        {

            testTimer = new Timer[3];


            testTimer[0] = new Timer(new TimerClass(1, "test1").TestCallBack, "object1", 1000, 1000);

            testTimer[1] = new Timer(new TimerClass(2, "test2").TestCallBack, "object2", 1000, 2000);

            testTimer[2] = new Timer(new TimerClass(3, "test3").TestCallBack, "object3", 1000, 3000);



            Thread.Sleep(10000);

        }

    }


    class TimerClass

    {

        private int value1;

        private string value2;

//각기 다른 값을 넣도록 생성자 정의.

        public TimerClass(int val1, string val2)

        {

            value1 = val1;

            value2 = val2;

        }

//Timer가 주기적으로 실행할 CallBack 함수.

        public void TestCallBack(object data)

        {

            Console.WriteLine("{0}   {1}   {2}", value1, value2, data.ToString());

        }

    }

이해가 쉽게 하기 위해 Console을 사용..



[결과]



내 프로젝트에 적용을 해서 진행해야 겠다. 끝 !



반응형
반응형


DataTable을 Socket으로 전송해야하는 상황이 발생..

DataTable을 Byte로 변환 해야 하는데 그 방법을 찾이 못하였고..(아시는분은 댓글좀...)

DataSet을 Byte로 압축, 변환 시키는 방법을 찾았다.

테스트 및 적용 완료 하였고 잘 돌아간다.

진행 중 문제가 있었는데, 받는 측에서 Buffer를 너무 크게 해서 받으면 DataSet으로 변환이 되지 않는다.

정확한 사이즈를 받아와야 한다.


출처 : http://ndolson.com/479#recentTrackback


매우 효율적인 방법인 듯..


설명은 출처에 잘 되어 있으므로 생략하겠다.


반응형
반응형

DataSet을 Byte로 변환하여 보낼일이 생겼다.

그런데.. DataSet의 크기가 크다. 

문제가 또 생긴 것이 Byte로 받은 측에서 DataSet으로 변경할 때 생긴다.

버퍼 크기대로 받으면. DataSet으로 변경이 안되기 때문이다.

그래서 DataSet의 크기를 먼저 보낸 후 그 사이즈와 버퍼 사이즈를 비교하여 반복적으로 받는 방법이다.


출처 : http://it-jerryfamily.tistory.com/entry/ProgramSocket-%ED%86%B5%EC%8B%A0-%EB%B2%84%ED%8D%BC-%EC%82%AC%EC%9D%B4%EC%A6%88%EB%B3%B4%EB%8B%A4-%EB%A7%8E%EC%9D%80-%EC%96%91%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%83%80%EB%A5%BC-%EB%B0%9B%EC%9D%84-%EC%8B%9C



위의 출처로 가면 소스가 나와 있다.



주요 부분만 설명.


서버 (받는 측)


 private void btnListen_Click(object sender, EventArgs e)
    {
        sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
        sck.Bind(new IPEndPoint(0, 8));
        sck.Listen(0);
 
        acc = sck.Accept();
 
        sck.Close();
 
        new Thread(() =>
        {
            while(true)
            {
                try
                {
///////// 받을 Data의 크기를 먼저 알아온다.
                    byte[] sizeBuf = new byte[4];
 
                    acc.Receive(sizeBuf, 0, sizeBuf.Length, 0);
 
                    int size = BitConverter.ToInt32(sizeBuf, 0);
//////// 데이터를 반복적으로 가져 올때 Stream에다가 저장 한다.
                    MemoryStream ms = new MemoryStream();
                     
/////// 받을 Data의 크기와 버퍼 사이즈를 비교하면서 데이터를 받아 온다.
                    while (size > 0)
                    {
                        byte[] buffer;
                        if (size < acc.ReceiveBufferSize)
                            buffer = new byte[size];
                        else
                            buffer = new byte[acc.ReceiveBufferSize];
 
                        int rec = acc.Receive(buffer, 0, buffer.Length, 0);
 
                        size -= rec;
 
                        ms.Write(buffer, 0, buffer.Length);
                    }
 
                    ms.Close();
 
                    byte[] data = ms.ToArray();
 
                    ms.Dispose();
 
                    Invoke((MethodInvoker)delegate
                    {
                        richTextBox1.Text = Encoding.UTF8.GetString(data);
                    });
                }
                catch
                {
                    MessageBox.Show("서버: DISCONNECTION!");
                    acc.Close();
                    acc.Dispose();
                    break;
                }
            }
            Application.Exit();
        }).Start();
    }


클라이언트 (보내는 측)


private void btnSendText_Click(object sender, EventArgs e)
{
    byte[] data = Encoding.UTF8.GetBytes(richTextBox1.Text);
     //보낼 데이터의 크기를 먼저 보낸다.
    sck.Send(BitConverter.GetBytes(data.Length), 0, 4, 0);
//데이터를 보낸다.
    sck.Send(data);
}


반응형
반응형

수십개의 Sensor와 데이터를 주고 받아야 하는데 Server 입장이 아니라 Clinet로 Telnet 접속을 시켜줘야 하는 상황.

각자 다른 Interval로 접속해서 Data를 받아와야 해서 처음에는 Thread를 사용해서 Sleep을 쓸 생각이었으나...

이렇게 되면 일정 간격으로 log를 남길 수가 없다는 판단... 세션이 늘어날수록 지연될수도 있다는 의견..


그래서 Timer를 써야 하는데 인자 전달하는 방법을 찾아야 했다........




우선.. Timer가 3가지가 있다는... ?


1.System.Windows.Forms.Timer

2.System.Threading.Timer

3.System.Timers.Timer


출처 : http://blog.daum.net/starkcb/117


출처에 가보면 상세한 설명이 나와있음....


그러나 인자 보내는 방법이 없네 ?




그래서 더 찾아보니 방법이 있었다.


출처 : http://blog.naver.com/PostView.nhn?blogId=bluekms21&logNo=10177193993


자세히는 아니더라도 사용방법이 나왔다.

나는 System.Threading.Timer 를 사용해서 인자를 넘기는 방법으로 Timer를 생성할 것이다.


아래 부분은 위의 출처에서 가져온 내가 필요한 부분이다. 해보고 예제를 추가해보도록 하겠다...



System.Threading.Timer

역시 Thread가 짱짱맨이시다. 객체별로 다른 인자값을 넣어줘도 잘 돌아갔다.

인자값의 전달은 생성자의 2번째 인자에 object형으로 넣어주면 된다.

 

System.Threading.Timer timer = new System.Threading.Timer( proc, (object)value, 1000, 1000);

 

1) proc

System.Threading.TimerCallback 으로 인자로 object를 받고, 반환값이 void인 델리게이터이다.

 

2) (object)value

구지 캐스팅을 해주지 않아도 된다. (모든 객체는 object이므로...)

실행될 메서드에서 원래 집어넣었던 형태로 다시 캐스팅해서 사용하면 된다.

 

public void proc( object state )

{

    Console.WriteLine( (string)state );

}

 

3) 1000, 1000

시작전 대기시간과 간격이다. 3번째 인자값을 0으로 주면 즉시 실행하게 되는데

MSDN의 예제에도 10 ~ 1000 정도는 주고있는데 쓰레드가 다 완성된 뒤 시작하게 하려는 의도가 숨어있다.

Threading.Timer의 실행을 멈추려면

timer.Change( System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite ); 로 설정한다.

 


요건.. 내가 만든 예제, 조금 느린 감이 있긴한데... 흠.... 타이머를 다르게 가져가면 잘 안되는 듯 한데...


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;


namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            string value = "test";

            List<Timer> TimerList = new List<Timer>();

            for(int i = 1; i< 10; i++)

                TimerList.Add(new Timer(proc, (object)(value+i), 1000, 1000));


            Thread.Sleep(20000);

        }


        private static void proc(object state)

        {

            Console.WriteLine((string)state);

        }

    }

}























반응형
반응형

Socket 통신으로 Client가 Server에게 요청하는 Packet을 보내는데

명령을 한번에 보내기 위해서는 Server측에서 받아서 문자열을 자르는 방법이 필요..



상황


Login 요청 패킷을 보낼 예정이었는데...


Client가 Server측에게 


"[LOG]ID:test,PW:1234" 라고 보낼 예정.



우선 LOG 문자열 추출


string str = "[LOG]ID:test,PW:1234";

Console.WriteLine(str.Substring(1,3));


결과



이번엔 [LOG]를 제외한 뒷부분 부터 자르기


string str = "[LOG]ID:test,PW:1234";

Console.WriteLine(str.Substring(5));


결과




위의 문자열을 ","를 기준으로 ID와 PW로 나누려고 한다..

Split을 사용


string str = "ID:test,PW:1234";

string[] sp =  str.Split(',');

foreach(string s in sp)

{

Console.WriteLine(s);

}


결과















반응형

+ Recent posts