퇴근5분전

 

  윈폼 만들때 일정 시간 입력이 없으면 뭔가 해야 할때... ( 화면 보호기, 로그아웃 같은... )

 

간단한 샘플코드이다.

 

 

5초간 가만히 두면 텍스트 박스가 잠긴다.

 

Idle 이벤트가 발생하면서 텍스트 박스에 시간(밀리초)이 표시된다.

 

단,  윈도우 전체 <--- 범위라서 ... 응용프로그램 밖에서 마우스나 키보드가 움직여도 값이 초기화 된다.

 

 오늘 이걸로 윈폼 로그인 세션을 구현하기는 했는데... 사용환경 덕분에 고려사항은 아니어서

 

우선 패스... 응용프로그램 범위내에서라면 다른 방법을 찾아봐야 될 것 같다.

 

 

 

 

public partial class Form1 : Form
    {
        [DllImport("User32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        internal struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

        public static uint GetIdleTime()
        {
            LASTINPUTINFO LastUserAction = new LASTINPUTINFO();
            LastUserAction.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(LastUserAction);
            GetLastInputInfo(ref LastUserAction);
            return ((uint)Environment.TickCount - LastUserAction.dwTime);
        }

        TimeSpan limitSessionTime = new TimeSpan(0, 0, 5);
         
        public Form1()
        {
            InitializeComponent();
            Application.Idle += Application_Idle;
            isIdleReset = true;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            button1.PerformClick();
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            Application.Idle -= Application_Idle;
            base.OnFormClosed(e);
        }

        private void Application_Idle(object sender, EventArgs e)
        {
            textBox1.Text = "" + GetIdleTime();

            if (isIdleReset) return;

            if (!isIdleReset && limitSessionTime.TotalMilliseconds < GetIdleTime())
            {
                isIdleReset = true;
                this.textBox1.ReadOnly = true;
                Application.DoEvents();
            }
        }

        bool isIdleReset = true;
        private void button1_Click(object sender, EventArgs e)
        {
            isIdleReset = false;
            this.textBox1.ReadOnly = false;
            Application.RaiseIdle(e);
        }
    }

 

 

질문글...

http://www.hoons.net/Board/QACSHAP/Content/103574

 

풀이... 엄청 쉬운건데...

 

두가지 방법으로 해결해봄...

 

 

         ## 질문 글처럼 join으로 하고자 하면...

            string a = "2019021109462";
            int idx = 0;
            int splitLength = 4;
            List<string> lst = new List<string>();
            for (idx = 0; idx < a.Length;)
            {
                if (a.Length < (idx + splitLength))
                {
                    splitLength = (idx + splitLength) - a.Length;
                }

                lst.Add(a.Substring(idx, splitLength));
                idx += splitLength;
                splitLength = 2;
            }

 

         ## 질문 글처럼 split 으로 잘라서 처리하고자 하면..

            idx = 0; splitLength = 4;
            for (idx = 0; idx < a.Length;)
            {
                if (a.Length < (idx + splitLength))
                {
                    splitLength = (idx + splitLength) - a.Length;
                }
                a = a.Insert(idx + splitLength, " ");
                idx += splitLength + 1;
                splitLength = 2;               
            }

 

   질문글에서 딱히 split이랑 join을 이용한다고 하는데...

  음... 두 방법만 으로 풀려면... 답이 떠오르지 않는다.

 

 우선 원래의 대상 값을 내가 이용가능한 메서드의 기능에 적용할수 있는 값으로 우선 변환을 거친 후...

라면 쉽게 가능할텐데....

 

 질문글에 맞는 답은 아닌것 같다.

 

그래도 출근전에 병원들렀다 가야해서... 잠깐 풀어본다.

 

질문 하나더...

 

http://www.hoons.net/Board/QACSHAP/Content/103584

 

음... 간만에 정규식..


            string str = "(.)update(10123123123)googleapis(3.0)com(0)";

            Regex rex = new Regex(@"\((\d|\.|)+\)");
            string xx = rex.Replace(str, ".").Trim('.');

 

일단 내용에 대한 건 처리는 된것 같은데 예외가 생길수도 있겠네

 

 

 

 

 

  이게 버그가 맞는지 원래 이런건지.. 고칠수 있는건데 잘 못 짠건지... 

잘은 모르겠다.

 

 로딩바! 구현해서 잘 사용하고 있던건데...

 

이번 프로젝트 로딩바가 구리다고 해서... 가져갔는데...

 

덜컹... 데드락이 걸린당?!!!  뭐지??? >>> 오전내내 잡다가 또 다른거 시켜서 못했음..

 

집에와서 코드로 이리저리 만들어보다가...

 

"설마.. MDI 환경에서 폼 로드를 해서?"  ... 설마하며 똑같이 MDI로 변경하고

 

자식폼을 로딩하면서... < 로딩이벤트에서 로딩바 호출...

 

똑같이 DeadLock!! 어랏...

 

Thread로

{

        로딩폼 생성                         <<< 1

        Application.Run( 로딩폼 )

}

 

while( 로딩폼 != null || 로딩폼 핸들 만들어졌나? == 아니 ) <-- 이 구문이 없으면 로딩바가 종료호출후에도 안꺼지고 살아있음.

{

   쓰레드.재우기( 50 );  <<< 2

}

 

1, 2 를 왔다 갔다....  무한반복한다.

 

아... 이런 썩을..

 

그래서 로딩바 호출을 .Shown 이벤트로 옮겨봤다.

잘 되넹? 오호..

 

그래서  이번엔 다시 로딩바 호출을 로드이벤트로 옮겨놓고

자식폼.MDIParent = this; 를 빼봤다.

 

잘 뜬다.

 

그래서 이번엔

 

자식폼.Shown += ( ss, ee )=> 자식폼.MDIParent = this ;

 

했더니 보기 흉해도 잘 뜬다.

 

 

구글링을 30분동안 해봤지만 짧은 영어로는 못찾겠다.

 

그냥 가이드로 로드이벤트 내에서 호출하지 말지어다.

{ 생성자, Shown 이벤트에서 잘됨 }

 

 

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

 

티스토리 발행하면 이상한 사진을 몇번씩이나 고르게 하더니 사라졌네???

 

 

 

 

 

 음... 일단 포기.

 

파워쉘로 터치스크린 기능도 온/오프도 성공은 했었는데...

 

클릭원스 배포하면서 매니패스트 찾다가 우선 포기...

 

Devcon.exe를 이용해서 껐다 켰다 할 수 있다고는 하는데...

 

그냥 나중엔 WPF로 다시 만들어봐야겠구만...

 

 

 

 

 

 

음. 입력이 용이하게 프로그램 하나 만들었는뎅...

입력란은 하나... 나머지는 모두 드래그 앤 드랍...

# 변수명( 영문, 한글 ) 입력하고 값목록 입력( 엔터 구분)하여 [등록] 하면

  플로우 변수목록, 전체변수목록에 자동 추가.

 그리고 proc Before에는 초기값 설정을 위해 VariableObjectView 라는 타입으로 자동 추가됨.

전체변수목록에서 다른 노드에서 등록된 변수들이 있을때 이 변수들을 조건으로 하여 값 설정이 된다면

드래그 앤 드랍으로 http://aseuka.tistory.com/entry/Flow-Condition  요런방식 조건으로 사용하면 됨.

 

변수를 삭제하면 현재 화면에서 사용한 변수들은 삭제..!

음.. 그러면 다른 화면에서 사용한 변수는 ? 어떻게 하지??

창 사이즈를 1180으로겨우 맞췄다. 제공되는 모니터 사이즈가 ㅡ.,ㅡ;; 1280...

 

 원노트에 옮겨서 내일 아침에 또 열심히 타이핑 쳐야겠군. 600라인정도 되니까 30분 정도 걸리려낭...

프로그램에 맞춰 코딩하면 대략 오전 쯤 될것 같은뎅...

 그보다 먼저 해야 할 일 끝내고 오후에 해야되려낭... 출근해서 생각해보장.

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

 가져간 소스 붙이는데 1시간 반쯤 걸려 9시 반쯤 끝냈다. 쉽지 않고만...

 오후 5시 반쯤 적용 및 완성을 마쳤다. 테스트까지 마치느라 오래 걸렸네.

내일부터는 다시 스토리보드를 그려야지.

그나저나... ppt에 뭔가 그리려니까 답답함이 밀려온다.

어떤식으로 그리면 좋을까나?

 프레지라도 가져가면 좋을텐뎅...

# 숫자 포맷 지원하는 텍스트 박스

# 빨간 테두리는 일시적인 효과처리. ( 유효성 체크 후 표시후 원래대로 돌아갈때 사용 )

 

굿센에서 WPF 하면서 항상 부족하다고 느꼈던건 숫자 관련 텍스트박스.

요구사항은 현업에 따라 많았으나...  여러가지 방법들로 만들어 사용해봤었음.

 

이번에 내용들을 정리하며 새로 만들어 샘플로 만들어보았음.

또한 유효성 체크를 마치고 탈락된 컨트롤들에 대한 효과처리가 없어서 그에 대한 효과처리를 진행하기위해

애니메이션 효과를 이용하여 살짝 효과를 주고 다시 원래대로 복구되는 메서드 하나를 만듬.

 

바인딩 테스트도 해보았음.

<ntxt:NumberTextBox x:Name="txtnum" HorizontalContentAlignment="Stretch" Margin="3" VerticalAlignment="Center" Value="{Binding Sum, Mode=TwoWay}" Format="N3" ></ntxt:NumberTextBox>

 

 

 

조회 조건이 바뀔때 조회를 버튼클릭없이 자동으로 하도록 하는 처리임.

 

이때 조회 조건이 일정 시간내에 다른 항목이 변경시 다시 조회대기시간을 늘려서 바로 조회가 일어나지 않도록 한다.

 

## 조회 항목이 변경될때마다 DelayQuery(); 호출해주면서 조회 대기시간이 초기화 되도록 처리함.

한번 호출되면 일정시간을 대기한 후 입력이 없으면 조회를 실행한다.


###################################   지연 쿼리 ########################
 #region 지연 쿼리호출

        bool isDelayRun = false;
        DateTime triggerTime = DateTime.MaxValue;
 
        void DelayCheckFunction()
        {
            while (isDelayRun)
            {
                var Span = DateTime.Now - triggerTime;
                if (Span.Seconds >= 1)
                {
                    Action query = 조회_메서드명;
                    Dispatcher.BeginInvoke(query, System.Windows.Threading.DispatcherPriority.Render, null);
                    isDelayRun = false;
                }
                System.Threading.Thread.Sleep(100);
            }
        }
        void DelayQuery()
        {
            triggerTime = DateTime.Now;
            if (isDelayRun == false)
            {
                isDelayRun = true;
                Action chkAction = DelayCheckFunction;
                chkAction.BeginInvoke(null, chkAction);
            }
        }
        #endregion

 

크리스탈 리포트에서 필드에 고정된 폰트를 글자수에 맞춰 폰트사이즈를 줄여 꽉 차도록 만드는 소스!

 

## 크리스탈 리포트 TextBoxObject 의 꽉 채우기 : 글자수에 따라 FontSize조정하는 방법

-- 바인딩 될 데이타 중 FontSize조정 할 대상 목록을 만듬.
Dictionary<string, string> KeyValues = new Dictionary<string, string>();

 

-- 데이타 바인딩
                        KeyValues.Add("{필드오브젝트ID}", "{필드오브젝트에 바인딩 될 때의 값}" );
                        ...

 

-- 로드 이벤트!
        bool IsContentLoaded = false;
        void Form_Loaded(object sender, RoutedEventArgs e)
        {
            if (IsContentLoaded == false)
            {
                if (CrystalReportViewer1.Created)
                {
                    IsContentLoaded = true;
                    foreach (var tar in KeyValues)
                    {
                        var fieldObject = crRpt.ReportDefinition.ReportObjects[tar.Key];
                        var field = ((CrystalDecisions.CrystalReports.Engine.FieldObject)(fieldObject));
                        Font font = CalcFont(tar.Value, field.Width, field.Font);
                        field.ApplyFont(font);
                    }

                    CrystalReportViewer1.Refresh();
                }
            }
        }


-- 폰트사이즈 조정.

       private Font CalcFont(string txt, double limitTwipsWidth, Font font)
        {
            const double TwipsPerInch = 1440d;

            // todo : 박스안에 들어갈 폰트사이즈 구하기
            // Font.Size 에서 8pt까지 줄여가면서 계산.
            // 1 inch = 1440 twip
            // 1 cm   =  567 twip
            Font newFont = font;
         
            using (var g = CrystalReportViewer1.CreateGraphics())
            {
                //http://stackoverflow.com/questions/1918877/how-can-i-get-the-dpi-in-wpf
                //http://stackoverflow.com/questions/4044397/how-do-i-convert-twips-to-pixels-in-net
                int limitWidth = (int)((limitTwipsWidth / TwipsPerInch) * (g.DpiX));

                for (float size = font.Size; size >= 3f; )
                {
                    SizeF szf = g.MeasureString(txt, newFont);

                    if (szf.Width <= limitWidth)
                    {
                        break;
                    }
                    newFont = new Font(newFont.FontFamily, size, System.Drawing.FontStyle.Bold);
                    size -= 0.1f;
                }
            }

            return newFont;
        }
        

'# 3) .Net ( Vs 2008 ) > C#' 카테고리의 다른 글

Flow 상세내용 입력하기...  (0) 2018.05.01
지연자동 조회 처리  (0) 2016.03.10
Excel 만들기, 엑셀 닫기  (0) 2016.02.17
변환] Unicode <--> 한글  (0) 2013.10.24
ppt 처럼 썸네일과 본화면이 있는 컨트롤!  (0) 2013.09.26

 

 # 엑셀을 만들고, 엑셀을 정상적으로 종료시키는 소스임.

      : 엑셀 파일을 만든 후 엑셀 프로세스가 정상적으로 닫히지 않는 현상을 해결한 소스임.

      : 엑셀 파일을 정상적으로 만든 후 닫히는 것은 매우 잘 닫혔으나,

      : 엑셀의 각 셀 값을 넣거나 변환 하는 과정에서 엑셀관련 처리가 아닌 다른 사유로 예외 발생시

        프로세스에 Excel이 살아있는 현상에 대해서는 강제로 엑셀을 닫는 처리를 추가했다.

      : 엑셀을 만들때 주의 할 점은 한번에 접근하는 객체의 프로퍼티를 두단계 깊이 들어가면 안된다는 것.

        ex)

            바꾼 후

               xlWorkBooks = xlApp.Workbooks; 
               xlWorkBook = xlWorkBooks.Add(Type.Missing);

            바뀌기 전 ( 프로세스 안 닫힘! )

         xlWorkBook = xlApp.Workbooks.Add(Type.Missing);

 

       : 생성하고 닫는 순서가 정해져 있음.

         app > workbooks > workbook > sheets > sheet > irange

   ### 온갖 삽질을 통해서 완성된 소스를 담아둔다.

 

// 소스  ####################################################################

            string exceptionMessage = string.Empty; 
            int exProcessHandle = 0;

            Microsoft.Office.Interop.Excel.Application xlApp = null;
            Microsoft.Office.Interop.Excel.Workbooks xlWorkBooks = null;
            Microsoft.Office.Interop.Excel.Workbook xlWorkBook = null;
            Microsoft.Office.Interop.Excel.Sheets xlSheets = null;
            Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet = null;
            Microsoft.Office.Interop.Excel.Range IRange = null;

            try
            {
                xlApp = new Microsoft.Office.Interop.Excel.Application();
                xlApp.Visible = false;
                xlApp.DisplayAlerts = false;
                
                xlWorkBooks = xlApp.Workbooks;
                xlWorkBook = xlWorkBooks.Add(Type.Missing);
               
                xlSheets = xlWorkBook.Worksheets;
                xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlApp.ActiveSheet;
                //xlWorkSheet.Name = "시트명";  
                xlWorkSheet.Cells.Font.Name = "굴림체";
                xlWorkSheet.Cells.Font.Size = "9";
              
                // 페이지설정
                xlWorkSheet.PageSetup.PaperSize = XlPaperSize.xlPaperA4;
                xlWorkSheet.PageSetup.Orientation = XlPageOrientation.xlLandscape;
                xlWorkSheet.PageSetup.Zoom = 90;
                xlWorkSheet.PageSetup.LeftMargin = xlApp.CentimetersToPoints(0.4d);
                xlWorkSheet.PageSetup.TopMargin = xlApp.CentimetersToPoints(1.5d);
                xlWorkSheet.PageSetup.RightMargin = xlApp.CentimetersToPoints(0.4d);
                xlWorkSheet.PageSetup.BottomMargin = xlApp.CentimetersToPoints(0.7d);
                xlWorkSheet.PageSetup.HeaderMargin = xlApp.CentimetersToPoints(1.3d);
                xlWorkSheet.PageSetup.FooterMargin = xlApp.CentimetersToPoints(0.5d);
                
                //.... 데이타 처리 /* 생략 */ 
            }
            catch (Exception exc)
            {
                exceptionMessage = exc.Message;
            }
            finally
            {
                // 정상적으로 생성시 Excel 은 잘 Kill됨
                // 데이타를 넣다가 예외가 발생하면 안죽음!
                if( string.IsNullOrEmpty(exceptionMessage.Trim()) == false )
                {
                    if (xlWorkSheet != null) xlWorkSheet.Delete();
                    if (xlWorkBook != null) xlWorkBook.Close(null, null, null);
                    if (xlWorkBooks != null) xlWorkBooks.Close();
                    if (xlApp != null) {
                        xlApp.Quit();
                        // todo : Excel Kill
                        GetWindowThreadProcessId((IntPtr)xlApp.Hwnd, out exProcessHandle);
                        System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
                        foreach (System.Diagnostics.Process p in process)
                        {
                            if (p.Id == exProcessHandle)
                            {
                                try
                                {
                                    p.Kill();
                                }
                                catch { }
                            }
                        }
                    }
                }
 
                releaseComObject(IRange);
                releaseComObject(xlWorkSheet);
                releaseComObject(xlSheets);
                releaseComObject(xlWorkBook);
                releaseComObject(xlWorkBooks);
                releaseComObject(xlApp); 
              
                IRange = null;
                xlWorkSheet = null;
                xlSheets = null;
                xlWorkBook = null;
                xlWorkBooks = null;
                xlApp = null;

                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                 
                if (string.IsNullOrEmpty(exceptionMessage.Trim()) == false)
                {
                    MessageBox.Show( exceptionMessage );
                }
            }

 

        /// <summary>
        /// 객체 COM 자원 반환
        /// </summary>
        /// <param name="obj"></param>
        private static void releaseComObject(object obj)
        {
            try
            {
                if (obj != null)
                {
                     Marshal.ReleaseComObject(obj); 
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                obj = null;
            }
        }

 

 

 

  뭐라고 써야 좋을까??? 딱히... 떠오르지는 않네?

 

다양한 컨트롤들의 이벤트들이 즉시 호출되지 않고 일정 시간내에 다른 컨트롤들의 이벤트발생이 없으면

 

지정된 메서드를 호출하는 형태를 만들었다.

 

버튼1, 버튼2, 라디오1, 라디오2 가 있을때

 

버튼들을 1초내에 클릭 또는 체크시 지정된 메서드를 바로 호출하는 것이 아니고 기다린다!

 

1초내에 다른 버튼의 이벤트가 발생하면 계속 기다려주다가 일정 시간동안 이벤트가 없으면 지정된 메서드를 호출한다.

 

이게 필요한곳이 있어서 샘플로 만들어봤을뿐...  다른 개발자분이 맡아서 진행하는 부분이라 ...

 

 

5회 연속 이벤트를 여기저기 컨트롤을 건드려 이벤트를 발생하였다.

 

시간이 되어 3125이벤트 발생 결과를 뿌려주고 있다.

 

프로그래스바는 100%가 되면 이벤트 호출이 되는 시점을 직접 볼 수 있도록 붙여봤다.

소스 (hidden)!