사용자 도구

사이트 도구


kb:csharpsnippets

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:csharpsnippets [2014/11/10 16:23] (현재)
줄 1: 줄 1:
 +{{INLINETOC}}
 +\\
 +
 +====== C# Snippets ======
 +.NET Tip이라고 불러야 하나?
 +
 +====== ShellExecute ======
 +<code c#>
 +using System;
 +using System.Diagnostics;​
 +...
 +ProcessStartInfo psi = new ProcessStartInfo();​
 +psi.Verb = "​open";​
 +psi.FileName = @"​c:​\windows";​
 +psi.UseShellExecute = true;
 +Process.Start(psi);​
 +</​code>​
 +
 +====== 텍스트 파일 인코딩 알아내기 ======
 +<code c#>
 +public System.Text.Encoding DetectEncoding(string fileName)
 +{
 +    System.Text.Encoding result = System.Text.Encoding.Default;​
 +
 +    using (System.IO.FileStream stream = System.IO.File.OpenRead(fileName))
 +    {
 +        if (stream != null && stream.CanRead && stream.CanSeek)
 +        {
 +            byte[] bom = new byte[stream.Length > 4 ? 4 : stream.Length];​
 +            stream.Read(bom,​ 0, bom.Length);​
 +            result = DetectEncoding(bom);​
 +        }
 +    }
 +
 +    return result;
 +}
 +
 +public System.Text.Encoding DetectEncoding(byte[] bom)
 +{
 +    System.Text.Encoding result = System.Text.Encoding.Default;​
 +
 +    do
 +    {
 +        if (bom == null)
 +            break;
 +
 +        if (bom.Length < 2)
 +            break;
 +
 +        if (bom[0] == 0xFF && bom[1] == 0xFE && (bom.Length < 4 || bom[2] != 0 || bom[3] != 0))
 +        {
 +            result = System.Text.Encoding.Unicode;​
 +            break;
 +        }
 +
 +        if (bom[0] == 0xFE && bom[1] == 0xFF)
 +        {
 +            result = System.Text.Encoding.BigEndianUnicode;​
 +            break;
 +        }
 +
 +        if (bom.Length < 3)
 +            break;
 +
 +        if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
 +        {
 +            result = System.Text.Encoding.UTF8;​
 +            break;
 +        }
 +
 +        if (bom[0] == 0x2B && bom[1] == 0x2F && bom[2] == 0x76)
 +        {
 +            result = System.Text.Encoding.UTF7;​
 +            break;
 +        }
 +
 +        if (bom.Length < 4)
 +            break;
 +
 +        if (bom[0] == 0xFF && bom[1] == 0xFE && bom[2] == 0 && bom[3] == 0)
 +        {
 +            result = System.Text.Encoding.UTF32;​
 +            break;
 +        }
 +
 +        if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xFE && bom[3] == 0xFF)
 +        {
 +            result = System.Text.Encoding.GetEncoding(12001);​
 +            break;
 +        }
 +
 +    } while (false);
 +
 +    return result;
 +}
 +</​code>​
 +
 +====== 간단한 TCP & UDP 통신 ======
 +<code c#>
 +public static string TcpSendReceive(string ipStr, int port, string sendMsg, int timeout)
 +{
 +    Socket tcpSocket = new Socket(
 +            AddressFamily.InterNetwork,​ SocketType.Stream,​ ProtocolType.Tcp
 +            );
 +    tcpSocket.ReceiveTimeout = timeout;
 +
 +    StringBuilder result = new StringBuilder();​
 +
 +    tcpSocket.Connect(ipStr,​ port);
 +    if (tcpSocket.Connected)
 +    {
 +        try
 +        {
 +            Byte[] sendBuffer = Encoding.ASCII.GetBytes(sendMsg);​
 +            tcpSocket.Send(sendBuffer,​ sendBuffer.Length,​ 0);
 +
 +            Byte[] recvBuffer = new Byte[1024];
 +            Int32 bytes = tcpSocket.Receive(recvBuffer,​ recvBuffer.Length,​ 0);
 +            result.Append(Encoding.ASCII.GetString(recvBuffer,​ 0, bytes));
 +            while (bytes > 0)
 +            {
 +                bytes = tcpSocket.Receive(recvBuffer,​ recvBuffer.Length,​ 0);
 +                result.Append(Encoding.ASCII.GetString(recvBuffer,​ 0, bytes));
 +            }
 +        }
 +        catch (System.Net.Sockets.SocketException)
 +        {
 +            result.Append("​Error"​);​
 +        }
 +
 +        tcpSocket.Close();​
 +    }
 +    else
 +    {
 +        result.Append("​Error"​);​
 +    }
 +
 +    return result.ToString();​
 +}
 +
 +public static string UdpSendReceive(string ipStr, int port, string sendMsg, int timeout)
 +{
 +    IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ipStr),​ port);
 +
 +    Socket udpSocket = new Socket(
 +            AddressFamily.InterNetwork,​ SocketType.Dgram,​ ProtocolType.Udp
 +            );
 +    udpSocket.ReceiveTimeout = timeout;
 +
 +    string result = "";​
 +
 +    Byte[] sendBuffer = Encoding.ASCII.GetBytes(sendMsg);​
 +    udpSocket.SendTo(sendBuffer,​ sendBuffer.Length,​ SocketFlags.None,​ ip);
 +
 +    IPEndPoint sender = new IPEndPoint(IPAddress.Any,​ 0);
 +    EndPoint remote = (EndPoint)sender;​
 +
 +    Byte[] recvBuffer =  new byte[1024];
 +    try
 +    {
 +        int bytes = udpSocket.ReceiveFrom(recvBuffer,​ ref remote);
 +        if (bytes > 0)
 +            result = Encoding.ASCII.GetString(recvBuffer,​ 0, bytes);
 +    }
 +    catch (System.Net.Sockets.SocketException)
 +    {
 +        result = "​Error";​
 +    }
 +
 +    udpSocket.Close();​
 +
 +    return result;
 +}
 +</​code>​ 블록킹 소켓 만세~
 +
 +
 +====== 파일 이름, 확장자 등 분리하기 ======
 +System.IO.Path 모듈 이용
 +
 +
 +====== OS 종류 알아내기 ======
 +<code c#>
 +OperatingSystem os = Environment.OSVersion;​
 +MessageBox.Show(os.Version.ToString());​
 +MessageBox.Show(os.Platform.ToString());​
 +</​code>​
 +
 +====== 시스템 폴더 경로 알아내기 ======
 +<code c#>
 +Environment.GetFolderPath( Environment.SpecialFolder.Personal )
 +</​code>​
 +
 +====== 실행 파일 경로 알아내기 ======
 +<code c#>
 +Application.ExecutablePath
 +</​code>​
 +or
 +<code c#>
 +Application.StartupPath
 +</​code>​
 +
 +아니면 이렇게도...
 +<code c#>
 +System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0).FullyQualifiedName
 +System.Reflection.Assembly.GetExecutingAssembly.Location
 +</​code>​
 +
 +====== ListView 성능 개선 ======
 +정렬자(sorter)가 설정되어 있는 리스트뷰에 대량의 아이템을 집어넣는 경우, 아이템을 집어넣을 때마다 정렬이 이루어지므로 뒤로 갈수록 매우 느려진다. 이를 해결하기 위해서는 2가지 방법이 있다. ​
 +
 +첫번째는 아이템을 집어넣기 전에 정렬자를 null로 만든 다음, 다 집어넣은 후 정렬자를 새로 세팅하고,​ Sort()를 호출하는 방법이다. 아이템을 집어넣을 때 <​code>​AddRange()</​code>​ 함수를 이용하면 좀 더 나은 성능을 얻을 수 있다. ​
 +
 +<code c#>
 +System.Collections.IComparer<​ListViewItem>​ oldSorter = MyListView.ListViewItemSorter;​
 +MyListView.ListViewItemSorter = null;
 +...
 +아이템 추가
 +...
 +MyListView.ListViewItemSorter = oldSorter;
 +MyListView.Sort();​
 +</​code>​
 +
 +두번째는 리스트뷰의 가상 모드(virtual mode)를 이용하는 방법이다. 가상 모드에서는 아이템의 컬렉션이 리스트뷰 내부에 존재하는 것이 아니라, 외부에 존재하게 된다. 리스트뷰가 이벤트 핸들러를 통해 아이템을 요청하면 유저가 이를 제공해줘야 한다.
 +
 +<code c#>
 +...
 +TListViewItem[] MyItems;
 +MyListView.OnRetrieveVirtualItem += MyListView_RetrieveVirtualItem;​
 +...
 +
 +private void SomeButton_Click(object sender, EventArgs e)
 +{
 +    Array.Sort(MyItems,​ MySorter);
 +    MyListView.VirtualMode = true;
 +    MyListView.VirtualListSize = MyItems.Length;​
 +}
 +
 +private void MyListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
 +{
 +    e.Item = MyItems[e.ItemIndex];​
 +}
 +</​code>​
 +
 +정렬자 안에서 하는 일이 매우 많다면, 즉 리스트 아이템 비교에 들어가는 비용이 크다면 가상 모드보다는 그냥 정렬자 껐다 켯다 하는 것이 낫다.
 +
 +
 +====== ListView 각 컬럼 헤더 클릭시 해당 컬럼을 기준으로 아이템 정렬하기 ======
 +대충 아래와 같은 클래스를 만들고...
 +<code c#>
 +/// <​summary>​
 +/// 리스트뷰 아이템 소팅을 위한 비교 클래스. ​
 +/// 리스트뷰에 있는 아이템을 문자열로서가 아니라, 숫자로 비교하고자 하는 ​
 +/// 경우 Numeric = true로 설정한다.
 +/// </​summary>​
 +class ListViewItemComparer : System.Collections.IComparer<​ListViewItem>​
 +{
 +    private int ColumnIndex = 0;
 +    private bool NumericComparison = false;
 +    private bool AscendingOrder = true;
 +
 +    public int Column ​
 +    { 
 +        get { return ColumnIndex;​ } 
 +        set { ColumnIndex = value; } 
 +    }
 +    public bool Numeric ​
 +    { 
 +        get { return NumericComparison;​ } 
 +        set { NumericComparison = value; } 
 +    }
 +    public bool Ascending ​
 +    { 
 +        get { return AscendingOrder;​ } 
 +        set { AscendingOrder = value; } 
 +    }
 +
 +    public ListViewItemComparer(int col)
 +    {
 +        ColumnIndex = col;
 +    }
 +
 +    public int Compare(object l, object r)
 +    {
 +        ListViewItem lhs = (ListViewItem)l;​
 +        ListViewItem rhs = (ListViewItem)r;​
 +
 +        if (AscendingOrder)
 +        {
 +            if (lhs == null && rhs == null) return 0;
 +            else if (lhs == null) return -1;
 +            else if (rhs == null) return 1;
 +
 +            if (lhs == rhs) return 0;
 +
 +            if (NumericComparison)
 +            {
 +                decimal lhsValue, rhsValue;
 +
 +                if (!Decimal.TryParse(lhs.SubItems[ColumnIndex].Text,​ out lhsValue))
 +                    lhsValue = 0;
 +
 +                if (!Decimal.TryParse(rhs.SubItems[ColumnIndex].Text,​ out rhsValue))
 +                    rhsValue = 0;
 +
 +                return Decimal.Compare(lhsValue,​ rhsValue);
 +            }
 +            else
 +            {
 +                string lhsText = lhs.SubItems[ColumnIndex].Text;​
 +                string rhsText = rhs.SubItems[ColumnIndex].Text;​
 +                return String.Compare(lhsText,​ rhsText);
 +            }
 +        }
 +        else
 +        {
 +            if (lhs == null && rhs == null) return 0;
 +            else if (lhs == null) return 1;
 +            else if (rhs == null) return -1;
 +
 +            if (lhs == rhs) return 0;
 +
 +            if (NumericComparison)
 +            {
 +                decimal lhsValue, rhsValue;
 +
 +                if (!Decimal.TryParse(lhs.SubItems[ColumnIndex].Text,​ out lhsValue))
 +                    lhsValue = 0;
 +
 +                if (!Decimal.TryParse(rhs.SubItems[ColumnIndex].Text,​ out rhsValue))
 +                    rhsValue = 0;
 +
 +                return -(Decimal.Compare(lhsValue,​ rhsValue));
 +            }
 +            else
 +            {
 +                string lhsText = lhs.SubItems[ColumnIndex].Text;​
 +                string rhsText = rhs.SubItems[ColumnIndex].Text;​
 +                return -(String.Compare(lhsText,​ rhsText));
 +            }
 +        }
 +    }
 +};
 +</​code>​
 +
 +<code c#>
 +// 어딘가에서 이벤트 핸들러 추가해주고...
 +...
 +ListView1.ColumnClick += ListView1_ColumnClick;​
 +...
 +
 +private void ListView1_ColumnClick(object sender, ColumnClickEventArgs e)
 +{
 +    ListViewItemComparer sorter =
 +        ListView1.ListViewItemSorter as ListViewItemComparer;​
 +
 +    if (sorter == null)
 +        sorter = new ListViewItemComparer(e.Column);​
 +    else
 +        sorter.Column = e.Column;
 +
 +    ListView1.Sort();​
 +}
 +</​code>​
 +
 +====== TextBox 마지막 라인까지 스크롤 하기 ======
 +로그 출력 같은 걸 텍스트박스에다 하는 경우, 텍스트가 추가될 때마다 마지막 라인까지 스크롤해주는 것이 보기가 좋다. 이를 위해서는 TextBox.ScrollToCaret 함수를 이용하면 된다. 단 포커스를 텍스트박스에다 줘야한다.
 +
 +<code c#>
 +TextBox1.Focus();​
 +TextBox1.SelectionStart = TextBox1.TextLength;​
 +TextBox1.ScrollToCaret();​
 +</​code>​
 +
 +====== Mnemonic Focus Control ======
 +Label과 Textbox가 있을 때 라벨에 있는 mnemonic을 눌렀을 때, Textbox에 포커스가 가게 하려면, 탭순서를 잘 맞춰주면 된다.
 +
 +{{csharpsnippets_focus0.png?​direct|}}{{csharpsnippets_focus1.png?​direct|}}
 +
 +사용자가 ALT+S를 누르면 일단 해당하는 라벨에 포커스를 주려고 시도한다. 그런데 라벨은 기본적으로 포커스를 가질 수 없으므로 그 다음 컨트롤에 포커스가 가게 된다. 그래서 원하는 컨트롤에 포커스가 가게 되는 것이다. 만약 그 다음 컨트롤이 포커스를 가질 수 없는 컨트롤이라면 계속해서 다음 컨트롤을 시도하게 된다.
 +
 +----
 +  * see also [[CSharp|C#​]]
  
kb/csharpsnippets.txt · 마지막으로 수정됨: 2014/11/10 16:23 (바깥 편집)