Visual Studio Code 자동 줄바꿈

Preferences > Settings 

 

 

검책창에서 wordWrap 검색 

그리고 wordWrap을 off에서 on으로 변경하면 자동줄바꿈이 된다.

c# 텍스트박스 실시간 적용하기

 

Application.DoEvents();

이 명령을 사용하시면 컨트롤 상태에 대한 변경 처리를 즉시 수행할수 있습니다.

 

txt1.Text = i ; 

 

youtu.be/LYSOJa9zpaw

 

using System.Runtime.InteropServices;

 

[DllImport("user32.DLL",EntryPoint = "ReleaseCapture")]

private extern static void ReleaseCapture();

[DllImport("user32.DLL",EntryPoint="SendMessage")]

private extern static void SendMessage(System.IntPtr hwnd, int wmsg, int wparam, int lparam);

 

 

private void ... MoseDown ...

 

ReleaseCapture();

SendMessage(this.Handle, 0x112,0xf012,0);

TextBox 출력 라인에 제한을 두자 ( C#/.Net 4.0 ) 

  

문제상황

TextBox에 원격 장비로 부터 수신되는( COM포트 및 TCP 소켓을 통해) 모든 메시지를 출력해 주는 로그창이 있었다.  아주 많은 로그들이 창에 뿌려지고, 상황에 따라서 하루종일 이 로그메시지를 뿌리고 있을 수 있는 상황이었다. ( 물론 거의 그럴일은 없지만.. ) 메모리가 워낙 넉넉하고 가상메모리를 사용하기 때문에 OutOfMemoryException 예외가 발생할일이야 있겟나 싶어서 별다른 처리를 해주지 않았는데 고객으로 부터 요구사항이 왔다.  

 

"TextBox에 문자열 출력 중에 OutOfMemoryExeption 예외가 발생할 수 있으니, 출력 라인을 제한하고 제한 라인 수를 초과할 경우에는 오래된 라인부터 삭제하도록 해주세요." 

 

요구사항을 들었을 때는 뭐 어려울 게 있겠나 싶어서 알겠다고 그렇게 하겠다고 햇는데 구현을 위해 검토를 조금 해보니 그 당시 내가 가진 지식으로는 해결하기가 만만치 않았다.

결론적으로 내가 작성한 코드이다. 내가 격었던 이슈들 및 해결 방법을 아래에 정리한다.

 

해결 코드

    ..........

    using System.Runtime.InteropServices;

  

    public partial class SbcTransferMessageView : Form    {        [DllImport("user32.dll")]        public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);        private const int WM_SETREDRAW = 11;

 

        .............

 

        private void _Print(string message)        {            const int nLimitPrintLines = 1000;

 

            SendMessage(this.Handle, WM_SETREDRAW, false, 0);

 

            try            {                tbView.AppendText(message);

 

                if (tbView.Lines.Length >nLimitPrintLines)                {                    LinkedList<string> tempLines = new LinkedList<string>(tbView.Lines);

 

                    while ((tempLines.Count - nLimitPrintLines) >0)                    {                        tempLines.RemoveFirst();                    }

 

                    tbView.Lines = tempLines.ToArray();

 

SendMessage(this.Handle, WM_SETREDRAW, true, 0);

 

                    tbView.Select(tbView.Text.Length, 0);                    tbView.ScrollToCaret();                }

            }            finally            {                SendMessage(this.Handle, WM_SETREDRAW, true, 0);            }

        }

 

    ................

 

이슈 1 - TextBox에 출력문자열 추가 시 자동 스크롤 다운되도록 하는 방법.

 

1. TextBox.AppendText() 함수를 이용하면 자동으로 스크롤 다운되는 기능이 제공된다. 

 

2. TextBox.Text = str; 와 같이 직접 문자열을 치환하려는 경우  

 

TextBox.Select( TextBox.Text.Length, 0 ); 

TextBox.ScrollToCaret(); 

 

와 같이 하면 치환한 텍스트의 끝으로 스크롤 다운 수행한다.  

 

이슈 2 - 자동 스크롤 다운 기능 구현 시 스크롤이 깜빡거리는 문제 해결방법.  

 

결론이야 아래의 Windows API 하나를 이용하면 되는데 찾기가 어렸엇던 부분이다. 

WM_SETREDRAW 메시지는 윈도우가 일시적으로 화면 Update를 활성화/비활성화 할 수 있는 기능을 제공한다. 자세한 설명은 MSDN을 참조..

 

[DllImport("user32.dll")]public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);

 

소스코드를 보면 SendMessage(this.Handle, WM_SETREDRAW, true, 0) 코드가 어디에 삽입되었는가가 중요하다. 잘 보면  스크롤한 후에 그리기를 활성화 해주는 것이 아니라 문자열을 치환해 준후 그리기를 활성화 해 준다. 만약 스크롤을 수행한 후 그리기를 활성화 하면 아예 아무런 문자열이 TextBox에 출력되지 않는다. 아래와 같이 하면 문자열 치환 동작과 스크롤 다운 동작이 한번에 그려짐으로 깜빡임이 제거 된다

 

tbView.Lines = tempLines.ToArray();

 

SendMessage(this.Handle, WM_SETREDRAW, true, 0);

 

tbView.Select(tbView.Text.Length, 0);tbView.ScrollToCaret();

 

이슈 3 - TextBox에 출력되는 문자열에서 앞에 라인을 잘라는주는 방법.  

  

방법은 위의 소스코드를 보면 어렵지 않게 알 수 있을 거다. 몇 가지 코멘트를 달면 아래 줄이 중요했던 것 같다.

 

처음에는 TextBox.Lines 프로퍼티를 직접 수정해서 앞에 줄을 삭제해주려했는데 TextBox.Lines는 읽기 전용으로 되어 있어서 수정이 안되었다.

 

그래서 아래와 같이 수정을 위해 LinkedList를 별도로 생성해 주었다. 이렇게 하면 O(n) ( n = TextBox.Lines.Length ) 연산이 필요하지만 어쩔 수 없는 것 같다.

 

LinkedList<string> tempLines = new LinkedList<string>(tbView.Lines); 

 

그리고 아래와 같이 필요한 라인만큼 제거를 해주는데 여기서 중요한 점은 LinkedList를 사용했다는 것이다. 일반 List 제너릭 클래스를 사용하면 내부적으로 배열을 사용하기 때문에 요소 삭제시 또 다시 O(n)의 연산을 필요로 한다. 반면 LinkedList를 사용하면 O(1)의 연산으로 삭제 연산이 처리가능하다.

 

tempLines.RemoveFirst();

 

+ Recent posts