[System.Runtime.InteropServices.DllImport( "user32.dll" )]
  public static extern void BringWindowToTop( IntPtr hWnd );
  [System.Runtime.InteropServices.DllImport( "user32.dll" )]
  public static extern void SetForegroundWindow( IntPtr hWnd );

  [System.Runtime.InteropServices.DllImport( "user32.dll" )]
  public static extern IntPtr FindWindow( string lpClassName, string lpWindowName );

  [System.Runtime.InteropServices.DllImport( "user32.dll" )]
  public static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, int wParam, int lParam );

  [System.Runtime.InteropServices.DllImport( "user32.dll" )]
  static extern bool ShowWindow( IntPtr hWnd, int nCmdShow );

  /// <summary>
  /// 해당 응용 프로그램의 주 진입점입니다.
  /// </summary>
  [STAThread]
  static void Main()
  {
   bool isNew;
   Mutex dup = new Mutex( true, "RunManager", out isNew );

   if ( isNew )
   {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault( false );
    Application.Run( new Form1() );
    dup.ReleaseMutex();
   }
   else
   {
    IntPtr wHandle = FindWindow( null, "RunManager" );
    if(wHandle != IntPtr.Zero)
    {
     ShowWindow( wHandle, 1 );
     BringWindowToTop( wHandle );
     SetForegroundWindow( wHandle );
    }
    Application.Exit();
   }
  }

Posted by 나비:D
:
네이버 사전
구글 번역기

C#

요즘 영어 -_- 대략 좌절 쩝...

구글횽아 번역좀 더 머찌게 해주믄 안될까 ㅠ.ㅠ

사용자 삽입 이미지
사용자 삽입 이미지

2009-07-15 업뎃했삼 ㅎㅎ
2009-06-26 google 번역기 쪽 스크롤바 추가
2009-06-26 ctrl + 1, ctrl + 2 키에 대해서 탭 변경
2009-07-15 항상위 메뉴추가 기본 항상위

대충 이정도 ㅋㅋ
Posted by 나비:D
:
메시지 필터를 이용하여 F1, F2, F3 .. 키 입력을 후킹하기.
 
 
public class MessageFilter : System.Windows.Forms.IMessageFilter
{
    public bool PreFilterMessage(ref Message m)
    {
        switch(m.Msg)
        {
            case 256 : // WM_KEYDOWN    
 
<==== windows message 를 C# 형태로 쓰고 싶었지만..
딱히 만들어져있는게 없더군요 그래서 인터넷에서 windows.h 파일을 검색해서 찾았습니다. WM_KETDOWN = 256 번이더군요.
 
                System.Console.WirteLine(m.LParam.ToInt32());      
                // 이걸로 F1 부터 여러가지 키를 차례데로 눌러본 값들이
                if( m.LParam.ToInt32() == 3866625 ) // F1 Key            
                // <===  이 값들입니다. 3866625 가 F1 이군요.. 이런식으로 Key 값을 찾아서
                {                                                                            
                // 계속 추가하면 키보드 후킹.. 그다지 어려운건 아닐거 같군요 ^^;;
                    System.Console.WriteLine("F1 Press");
                    return true;
                }
                else if( m.LParam.ToInt32() == 3932161 )    // F2 Key
                {
                    System.Console.WriteLine("F2 Press");
                    return true;
                }
                else if( m.LParam.ToInt32() == 3997697 )    // F3 Key
                {
                    System.Console.WriteLine("F3 Press");
                    return true;
                }
                break;
        }
        return false;
    }
}
 
//
//     만들어 놓은 MessageFilter 는 반드시 AddMessageFilter 메서드를 통해 추가해줘야 합니다.
//    static void Main 함수는 기본 Form 에 포함되어 있습니다.  :) 아시죠?
 
static void Main()
{
    Application.AddMessageFilter(new MessageFilter());
    Application.Run(new JapExamples());
}
 
 
아래 있는 것은 windows.h 파일에 정의된 windos message 들입니다. windows.h 파일은 visual studio 안에 INCLUDE_ROOT 에 있습니다.
어딘지는 아시죠?
 
 
WA_ACTIVE 1
WA_CLICKACTIVE 2
WA_INACTIVE 0
WM_ACTIVATE 6
WM_ACTIVATEAPP 28
WM_AFXFIRST 864
WM_AFXLAST 895
WM_APP 32768
WM_ASKCBFORMATNAME 780
WM_CANCELJOURNAL 75
WM_CANCELMODE 31
WM_CAPTURECHANGED 533
WM_CHANGECBCHAIN 781
WM_CHAR 258
WM_CHARTOITEM 47
WM_CHILDACTIVATE 34
WM_CLEAR 771
WM_CLOSE 16
WM_COMMAND 273
WM_COMMNOTIFY 68
WM_COMPACTING 65
WM_COMPAREITEM 57
WM_CONTEXTMENU 123
WM_COPY 769
WM_COPYDATA 74
WM_CREATE 1
WM_CTLCOLORBTN 309
WM_CTLCOLORDLG 310
WM_CTLCOLOREDIT 307
WM_CTLCOLORLISTBOX 308
WM_CTLCOLORMSGBOX 306
WM_CTLCOLORSCROLLBAR 311
WM_CTLCOLORSTATIC 312
WM_CUT 768
WM_DEADCHAR 259
WM_DELETEITEM 45
WM_DESTROY 2
WM_DESTROYCLIPBOARD 775
WM_DEVICECHANGE 537
WM_DEVMODECHANGE 27
WM_DISPLAYCHANGE 126
WM_DRAWCLIPBOARD 776
WM_DRAWITEM 43
WM_DROPFILES 563
WM_ENABLE 10
WM_ENDSESSION 22
WM_ENTERIDLE 289
WM_ENTERMENULOOP 529
WM_ENTERSIZEMOVE 561
WM_ERASEBKGND 20
WM_EXITMENULOOP 530
WM_EXITSIZEMOVE 562
WM_FONTCHANGE 29
WM_GETDLGCODE 135
WM_GETFONT 49
WM_GETHOTKEY 51
WM_GETICON 127
WM_GETMINMAXINFO 36
WM_GETOBJECT 61
WM_GETTEXT 13
WM_GETTEXTLENGTH 14
WM_HANDHELDFIRST 856
WM_HANDHELDLAST 863
WM_HELP 83
WM_HOTKEY 786
WM_HSCROLL 276
WM_HSCROLLCLIPBOARD 782
WM_ICONERASEBKGND 39
WM_IME_CHAR 646
WM_IME_COMPOSITION 271
WM_IME_COMPOSITIONFULL 644
WM_IME_CONTROL 643
WM_IME_ENDCOMPOSITION 270
WM_IME_KEYDOWN 656
WM_IME_KEYLAST 271
WM_IME_KEYUP 657
WM_IME_NOTIFY 642
WM_IME_REQUEST 648
WM_IME_SELECT 645
WM_IME_SETCONTEXT 641
WM_IME_STARTCOMPOSITION 269
WM_INITDIALOG 272
WM_INITMENU 278
WM_INITMENUPOPUP 279
WM_INPUTLANGCHANGE 81
WM_INPUTLANGCHANGEREQUEST 80
WM_KEYDOWN 256
WM_KEYFIRST 256
WM_KEYLAST 264
WM_KEYUP 257
WM_KILLFOCUS 8
WM_LBUTTONDBLCLK 515
WM_LBUTTONDOWN 513
WM_LBUTTONUP 514
WM_MBUTTONDBLCLK 521
WM_MBUTTONDOWN 519
WM_MBUTTONUP 520
WM_MDIACTIVATE 546
WM_MDICASCADE 551
WM_MDICREATE 544
WM_MDIDESTROY 545
WM_MDIGETACTIVE 553
WM_MDIICONARRANGE 552
WM_MDIMAXIMIZE 549
WM_MDINEXT 548
WM_MDIREFRESHMENU 564
WM_MDIRESTORE 547
WM_MDISETMENU 560
WM_MDITILE 550
WM_MEASUREITEM 44
WM_MENUCHAR 288
WM_MENUCOMMAND 294
WM_MENUDRAG 291
WM_MENUGETOBJECT 292
WM_MENURBUTTONUP 290
WM_MENUSELECT 287
WM_MOUSEACTIVATE 33
WM_MOUSEFIRST 512
WM_MOUSEHOVER 673
WM_MOUSELEAVE 675
WM_MOUSEMOVE 512
WM_MOUSEWHEEL 522
WM_MOVE 3
WM_MOVING 534
WM_NCACTIVATE 134
WM_NCCALCSIZE 131
WM_NCCREATE 129
WM_NCDESTROY 130
WM_NCHITTEST 132
WM_NCLBUTTONDBLCLK 163
WM_NCLBUTTONDOWN 161
WM_NCLBUTTONUP 162
WM_NCMBUTTONDBLCLK 169
WM_NCMBUTTONDOWN 167
WM_NCMBUTTONUP 168
WM_NCMOUSEMOVE 160
WM_NCPAINT 133
WM_NCRBUTTONDBLCLK 166
WM_NCRBUTTONDOWN 164
WM_NCRBUTTONUP 165
WM_NEXTDLGCTL 40
WM_NEXTMENU 531
WM_NOTIFY 78
WM_NOTIFYFORMAT 85
WM_NULL 0
WM_PAINT 15
WM_PAINTCLIPBOARD 777
WM_PAINTICON 38
WM_PALETTECHANGED 785
WM_PALETTEISCHANGING 784
WM_PARENTNOTIFY 528
WM_PASTE 770
WM_PENWINFIRST 896
WM_PENWINLAST 911
WM_POWER 72
WM_POWERBROADCAST 536
WM_PRINT 791
WM_PRINTCLIENT 792
WM_QUERYDRAGICON 55
WM_QUERYENDSESSION 17
WM_QUERYNEWPALETTE 783
WM_QUERYOPEN 19
WM_QUEUESYNC 35
WM_QUIT 18
WM_RBUTTONDBLCLK 518
WM_RBUTTONDOWN 516
WM_RBUTTONUP 517
WM_RENDERALLFORMATS 774
WM_RENDERFORMAT 773
WM_SETCURSOR 32
WM_SETFOCUS 7
WM_SETFONT 48
WM_SETHOTKEY 50
WM_SETICON 128
WM_SETREDRAW 11
WM_SETTEXT 12
WM_SETTINGCHANGE 26
WM_SHOWWINDOW 24
WM_SIZE 5
WM_SIZECLIPBOARD 779
WM_SIZING 532
WM_SPOOLERSTATUS 42
WM_STYLECHANGED 125
WM_STYLECHANGING 124
WM_SYNCPAINT 136
WM_SYSCHAR 262
WM_SYSCOLORCHANGE 21
WM_SYSCOMMAND 274
WM_SYSDEADCHAR 263
WM_SYSKEYDOWN 260
WM_SYSKEYUP 261
WM_TCARD 82
WM_TIMECHANGE 30
WM_TIMER 275
WM_UNDO 772
WM_UNINITMENUPOPUP 293
WM_USER 1024
WM_USERCHANGED 84
WM_VKEYTOITEM 46
WM_VSCROLL 277
WM_VSCROLLCLIPBOARD 778
WM_WINDOWPOSCHANGED 71
WM_WINDOWPOSCHANGING 70
WM_WININICHANGE 26

출처 : 데브피아

Posted by 나비:D
:
 

안녕하세요. 굿띠입니다...

 이번 포스트는 Property에 대해 얘기를 해보고 활용방법에 대해 간단하게 정리를 해볼까 합니다... 이것도 팁이 될수 있을까 모르겠네요..^^

Property는 어떤 구조로 되어 있다는거는 누구나 다 아실 겁니다.. 하지만 어떤 property를 얘기하는거지??? 라고 말하시는 분도 있을수도 있기 때문에 한번 다음과 같이 간단하게 소스를 만들어보도록 하겠습니다.


  class TestProperty
  {
    private string m_Test;

    public string Test
    {
      get
      {
        return m_Test;
      }
      set
      {
        m_Test = value;
      }
    }

    public TestProperty()
    {
    }
  }


 아~ 이것은 프로그램 하신 분이라면 누구나 많이 보던 소스아닙니까??? 그쵸??^^ 그럼 제가 한번 정리 해보겠습니다.

일반적으로 필드가 public이면 다른 개체가 해당 필드에 직접 액세스가 가능하고 수정 할 수 있지만 위와 같은 Property는 다른 개체를 통해 수정할수는 있으나 해당 필드를 소유하는 개체에 접근하지 못 하도록 합니다. 그리고 필드의 전용값을 읽고 쓰고 융통성 있는 메커니즘을 제공하는 멤버입니다. 이 Property는 멤버변수 처럼 사용할 수 있지만 실제로는 접근자를 통해 구현이 가능 한것이죠! 접근자는 위의 소스내용을 보시면 get, set을 생성하여 private 데이터에 엑세스 한다는것을 보실수 있습니다.


하지만 여기서 Property와 필드의 명확한 구분이 필요할 것 같습니다. 이 Property와 필드는 모두 개체에 정보를 저장하고 검색합니다. 이런 두개의 속성과 필드 기능의 유사성으로 인해 다음과 같은 경우에 서로 구분하여 프로그래밍 방식을 결정합니다. 다음 내용은 MSDN의 한 부분을 발췌했습니다.


다음 경우는 Perperty를 사용합니다.

  • 값이 설정되고 검색되는 시기와 방법을 제어해야 하는 경우

  • 속성에 유효성을 검사해야 하는 잘 정의된 값 집합이 들어 있는 경우

  • IsVisible 속성처럼 값을 설정했을 때 개체의 상태가 크게 변경되는 경우

  • 속성을 설정했을 때 다른 내부 변수나 다른 속성의 값으로 변경되는 경우

  • 속성을 설정하거나 검색하기 전에 일련의 작업 단계를 수행해야 하는 경우


    다음 경우에 필드를 사용합니다.

  • 값이 자체적으로 유효성을 검사하는 형식인 경우. 예를 들어, Boolean 변수에 True 또는 False 이외의 값이 할당되면 오류가 발생하거나 자동 데이터 변환이 수행됩니다.

  • 데이터 형식에서 지원하는 범위의 값이 유효한 경우. Single 또는 Double 형식의 여러 속성에도 적용됩니다.

  • 속성이 String 데이터 형식이고 문자열의 크기나 값에 대해 제약 조건이 없는 경우

     

    링크 : http://msdn2.microsoft.com/ko-kr/library/9d65as2e(VS.80).aspx




    다음으로 Property의 접근자에 대해서 한번 알아보도록 합시다. get 접근자는 속성 값을 반환하는 데 사용되고, set 접근자는 데이터를 저장할때 사용합니다. 여기서 get접근자는 방금 말씀드렸다시피 Property를 정의할때도 사용되지만 인덱서 요소를 검색하고 정의할때 사용되기도 합니다. 인덱서의 자세한 내용은 여기를 참조하시면 될거 같습니다.^^ http://msdn2.microsoft.com/ko-kr/library/6x16t2tx(VS.80).aspx

     

     

     

    활용 : Property를 활용하여 TextBox의 DataBindings속성을 구현하자(따라하기)

     

    그럼 한번 Property를 이용하여 TextBox컨트롤과 데이타바인딩을 한번 시켜보겟습니다. Control.DataBindings속성은 필드의 데이터와는 바인딩이 되지 않지만 Property와는 데이터 바인딩이 가능하기 때문에 코드의 가독성과 효율적인 프로그래밍을 할 수 있습니다.



    1. 먼저 응용프로그램 프로젝트를 하나 만듭니다. 이름은 TextDataBinding으로 합니다.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    2. 다음 폼디자인 화면에서 다음과 같이 컨트롤을 배치합니다. 이름의 텍스트 박스 컨트롤의 네임은 txt_name, 나이의 텍스트 박스 컨트롤의 네임은 txt_age로 지정합니다.




    3. 다음 두개의 텍스트박스와 데이터 바인딩 되는 Property를 만듭니다. 소스는 다음과 같습니다.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    4. 폼 로드 이벤트에 텍스트박스와 Property가 데이터 바인딩 될수 있도록 다음과 같이 작성합니다.

     

     

     

     

    Add메서드의 3개의 인자중 첫번째는 데이터 바인딩 되는 속성을 말합니다. 저는 텍스트 박스의 Text속성과 데이터바인딩을 하기위해 Text라고 적었습니다. 2번째 인자는 데이터 소스와 3번째 인자 데이터 멤버이므로 현재 클래스의 this와 Property이름을 넣었습니다.




    5. 버튼 컨트롤을 더블 클릭하여 Click이벤트를 등록하고 다음과 같이 작성합니다.

     

     

     

     



    그럼 전체 소스를 보여드리고 테스트를 한번 해보겠습니다.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    테스트를 해볼까요??? ^^ 프로그램을 실행한뒤 텍스트박스에 이름과, 나이를 입력하고 확인을 눌러봅시다.




     

     

     

     

     

     

     

     

     

     

     

     

     

    짠~~ 올바른 결과가 나왔네요...

    정리 : 버튼을 눌렀을경우 Property를 출력하라고 했습니다.  어때요??  Property는 TextBox와 데이터 바인딩이 되어 있기 때문에 Property를 통해 TextBox의 Text의 내용을 간단하게 출력할 수 있는 것입니다. 더 이상 정리는 필요 없을 것 같군요..

     

    한번 여러분도 따라 해보세요...^^!!

     

     

     

    TIP : VS2005의 리페터링으로 Property를 쉽게 만들자!!!

    여러분은 Property를 처음부터 끝까지 입력하시는건 아니죠??? Property를 10개나 만든다고 생각해보세요. 코딩 제대로 못하고 반복되는 Ctrl + C,V를 하면서 고친다면 프로그래밍의 재미를 보기전에 흥미를 잃어버릴수도 있을 겁니다. 저도 처음에는 열심이 입력했답니다.^^

    VS2005 이상 에서는 이러한 귀찮은 작업을 쉽게 만들수 있도록 도와주는 기능이 있습니다. 바로 리펙터링이라는 기능중에 필드 캡슐화라는 기능 인데요. 사용법은 다음과 같습니다.

     

    1. 먼저 private 멤버변수를 하나 만듭니다.








     

     

    2. private 멤버변수에서 우클릭 -> 리펙터링 -> 필드 캡슐화를 선택합니다.



     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    3. 다음 아래 그림과 같이 필드 이름을 적어주고 확인을 눌러줍니다.


    4. 짜잔~~! Property가 쉽게 만들어지는걸 볼 수 있습니다.


     VS2005는 이러한 반복적인 작업을 최소화 하기 위해 여러가지의 리펙터링 기능이 존재합니다. 이러한 리팩터링 작업을 사용하면 기존 필드에서 신속하게 속성을 만든 다음 문제 없이 코드를 새 속성에 대한 참조로 구현할 수 있습니다.^^

  • Posted by 나비:D
    :
    메시지 필터를 이용하여 F1, F2, F3 .. 키 입력을 후킹하기.
     
     
    public class MessageFilter : System.Windows.Forms.IMessageFilter
    {
        public bool PreFilterMessage(ref Message m)
        {
            switch(m.Msg)
            {
                case 256 : // WM_KEYDOWN     <==== windows message 를 C# 형태로 쓰고 싶었지만.. 딱히 만들어져있는게 없더군요 그래서
                                //                                    인터넷에서 windows.h 파일을 검색해서 찾았습니다. WM_KETDOWN = 256 번이더군요.
                    System.Console.WirteLine(m.LParam.ToInt32());        // 이걸로 F1 부터 여러가지 키를 차례데로 눌러본 값들이
                    if( m.LParam.ToInt32() == 3866625 ) // F1 Key            // <===  이 값들입니다. 3866625 가 F1 이군요.. 이런식으로 Key 값을 찾아서
                    {                                                                            // 계속 추가하면 키보드 후킹.. 그다지 어려운건 아닐거 같군요 ^^;;
                        System.Console.WriteLine("F1 Press");
                        return true;
                    }
                    else if( m.LParam.ToInt32() == 3932161 )    // F2 Key
                    {
                        System.Console.WriteLine("F2 Press");
                        return true;
                    }
                    else if( m.LParam.ToInt32() == 3997697 )    // F3 Key
                    {
                        System.Console.WriteLine("F3 Press");
                        return true;
                    }
                    break;
            }
            return false;
        }
    }
     
    //
    //     만들어 놓은 MessageFilter 는 반드시 AddMessageFilter 메서드를 통해 추가해줘야 합니다.
    //    static void Main 함수는 기본 Form 에 포함되어 있습니다.  :) 아시죠?
     
    static void Main()
    {
        Application.AddMessageFilter(new MessageFilter());
        Application.Run(new JapExamples());
    }
     
     
    아래 있는 것은 windows.h 파일에 정의된 windos message 들입니다. windows.h 파일은 visual studio 안에 INCLUDE_ROOT 에 있습니다.
    어딘지는 아시죠?
     
     
    WA_ACTIVE 1
    WA_CLICKACTIVE 2
    WA_INACTIVE 0
    WM_ACTIVATE 6
    WM_ACTIVATEAPP 28
    WM_AFXFIRST 864
    WM_AFXLAST 895
    WM_APP 32768
    WM_ASKCBFORMATNAME 780
    WM_CANCELJOURNAL 75
    WM_CANCELMODE 31
    WM_CAPTURECHANGED 533
    WM_CHANGECBCHAIN 781
    WM_CHAR 258
    WM_CHARTOITEM 47
    WM_CHILDACTIVATE 34
    WM_CLEAR 771
    WM_CLOSE 16
    WM_COMMAND 273
    WM_COMMNOTIFY 68
    WM_COMPACTING 65
    WM_COMPAREITEM 57
    WM_CONTEXTMENU 123
    WM_COPY 769
    WM_COPYDATA 74
    WM_CREATE 1
    WM_CTLCOLORBTN 309
    WM_CTLCOLORDLG 310
    WM_CTLCOLOREDIT 307
    WM_CTLCOLORLISTBOX 308
    WM_CTLCOLORMSGBOX 306
    WM_CTLCOLORSCROLLBAR 311
    WM_CTLCOLORSTATIC 312
    WM_CUT 768
    WM_DEADCHAR 259
    WM_DELETEITEM 45
    WM_DESTROY 2
    WM_DESTROYCLIPBOARD 775
    WM_DEVICECHANGE 537
    WM_DEVMODECHANGE 27
    WM_DISPLAYCHANGE 126
    WM_DRAWCLIPBOARD 776
    WM_DRAWITEM 43
    WM_DROPFILES 563
    WM_ENABLE 10
    WM_ENDSESSION 22
    WM_ENTERIDLE 289
    WM_ENTERMENULOOP 529
    WM_ENTERSIZEMOVE 561
    WM_ERASEBKGND 20
    WM_EXITMENULOOP 530
    WM_EXITSIZEMOVE 562
    WM_FONTCHANGE 29
    WM_GETDLGCODE 135
    WM_GETFONT 49
    WM_GETHOTKEY 51
    WM_GETICON 127
    WM_GETMINMAXINFO 36
    WM_GETOBJECT 61
    WM_GETTEXT 13
    WM_GETTEXTLENGTH 14
    WM_HANDHELDFIRST 856
    WM_HANDHELDLAST 863
    WM_HELP 83
    WM_HOTKEY 786
    WM_HSCROLL 276
    WM_HSCROLLCLIPBOARD 782
    WM_ICONERASEBKGND 39
    WM_IME_CHAR 646
    WM_IME_COMPOSITION 271
    WM_IME_COMPOSITIONFULL 644
    WM_IME_CONTROL 643
    WM_IME_ENDCOMPOSITION 270
    WM_IME_KEYDOWN 656
    WM_IME_KEYLAST 271
    WM_IME_KEYUP 657
    WM_IME_NOTIFY 642
    WM_IME_REQUEST 648
    WM_IME_SELECT 645
    WM_IME_SETCONTEXT 641
    WM_IME_STARTCOMPOSITION 269
    WM_INITDIALOG 272
    WM_INITMENU 278
    WM_INITMENUPOPUP 279
    WM_INPUTLANGCHANGE 81
    WM_INPUTLANGCHANGEREQUEST 80
    WM_KEYDOWN 256
    WM_KEYFIRST 256
    WM_KEYLAST 264
    WM_KEYUP 257
    WM_KILLFOCUS 8
    WM_LBUTTONDBLCLK 515
    WM_LBUTTONDOWN 513
    WM_LBUTTONUP 514
    WM_MBUTTONDBLCLK 521
    WM_MBUTTONDOWN 519
    WM_MBUTTONUP 520
    WM_MDIACTIVATE 546
    WM_MDICASCADE 551
    WM_MDICREATE 544
    WM_MDIDESTROY 545
    WM_MDIGETACTIVE 553
    WM_MDIICONARRANGE 552
    WM_MDIMAXIMIZE 549
    WM_MDINEXT 548
    WM_MDIREFRESHMENU 564
    WM_MDIRESTORE 547
    WM_MDISETMENU 560
    WM_MDITILE 550
    WM_MEASUREITEM 44
    WM_MENUCHAR 288
    WM_MENUCOMMAND 294
    WM_MENUDRAG 291
    WM_MENUGETOBJECT 292
    WM_MENURBUTTONUP 290
    WM_MENUSELECT 287
    WM_MOUSEACTIVATE 33
    WM_MOUSEFIRST 512
    WM_MOUSEHOVER 673
    WM_MOUSELEAVE 675
    WM_MOUSEMOVE 512
    WM_MOUSEWHEEL 522
    WM_MOVE 3
    WM_MOVING 534
    WM_NCACTIVATE 134
    WM_NCCALCSIZE 131
    WM_NCCREATE 129
    WM_NCDESTROY 130
    WM_NCHITTEST 132
    WM_NCLBUTTONDBLCLK 163
    WM_NCLBUTTONDOWN 161
    WM_NCLBUTTONUP 162
    WM_NCMBUTTONDBLCLK 169
    WM_NCMBUTTONDOWN 167
    WM_NCMBUTTONUP 168
    WM_NCMOUSEMOVE 160
    WM_NCPAINT 133
    WM_NCRBUTTONDBLCLK 166
    WM_NCRBUTTONDOWN 164
    WM_NCRBUTTONUP 165
    WM_NEXTDLGCTL 40
    WM_NEXTMENU 531
    WM_NOTIFY 78
    WM_NOTIFYFORMAT 85
    WM_NULL 0
    WM_PAINT 15
    WM_PAINTCLIPBOARD 777
    WM_PAINTICON 38
    WM_PALETTECHANGED 785
    WM_PALETTEISCHANGING 784
    WM_PARENTNOTIFY 528
    WM_PASTE 770
    WM_PENWINFIRST 896
    WM_PENWINLAST 911
    WM_POWER 72
    WM_POWERBROADCAST 536
    WM_PRINT 791
    WM_PRINTCLIENT 792
    WM_QUERYDRAGICON 55
    WM_QUERYENDSESSION 17
    WM_QUERYNEWPALETTE 783
    WM_QUERYOPEN 19
    WM_QUEUESYNC 35
    WM_QUIT 18
    WM_RBUTTONDBLCLK 518
    WM_RBUTTONDOWN 516
    WM_RBUTTONUP 517
    WM_RENDERALLFORMATS 774
    WM_RENDERFORMAT 773
    WM_SETCURSOR 32
    WM_SETFOCUS 7
    WM_SETFONT 48
    WM_SETHOTKEY 50
    WM_SETICON 128
    WM_SETREDRAW 11
    WM_SETTEXT 12
    WM_SETTINGCHANGE 26
    WM_SHOWWINDOW 24
    WM_SIZE 5
    WM_SIZECLIPBOARD 779
    WM_SIZING 532
    WM_SPOOLERSTATUS 42
    WM_STYLECHANGED 125
    WM_STYLECHANGING 124
    WM_SYNCPAINT 136
    WM_SYSCHAR 262
    WM_SYSCOLORCHANGE 21
    WM_SYSCOMMAND 274
    WM_SYSDEADCHAR 263
    WM_SYSKEYDOWN 260
    WM_SYSKEYUP 261
    WM_TCARD 82
    WM_TIMECHANGE 30
    WM_TIMER 275
    WM_UNDO 772
    WM_UNINITMENUPOPUP 293
    WM_USER 1024
    WM_USERCHANGED 84
    WM_VKEYTOITEM 46
    WM_VSCROLL 277
    WM_VSCROLLCLIPBOARD 778
    WM_WINDOWPOSCHANGED 71
    WM_WINDOWPOSCHANGING 70
    WM_WININICHANGE 26
     
    Posted by 나비:D
    :
     q 메서드의 대리자
     
    q 메서드를 보다 효율적으로 사용하기 위하여 특정 메서드 자체를 캡슐화할 있게 만들어 주는 방법

     

    Delegate 주는 장점은 메서드 자체가 캡슐화 되어있기 때문에 메서드를 보다 효율적으로 사용할 있게 줍니다. 다음은 Delegate 간단한 구현입니다.

     

    using System;

    delegate void SimpleDelegate1();

    delegate void SimpleDelegate2(int i);

    class AType{

         public void F1() {

              System.Console.WriteLine("AType.F1");

         }

         public void F2(int x){

              System.Console.WriteLine("AType.F2 x=" + x);

         }

    }

    class DeleTest {

           public static void Main(){

              AType atype = new AType();

            SimpleDelegate1 s1 = new SimpleDelegate1(atype.F1);

            SimpleDelegate2 s2 = new SimpleDelegate2(atype.F2);

            s1();

            s2(1000);

        }//main

    }//class

     

    메서드를 캡슐화하여 사용할 있다는 것은 아주 단순한 기능입니다. 단순한 기능만큼이나 Delegate 파워는 굉장합니다. 다음과 같은 경우를 예를 들어보죠. 만약 하나의 클래스에서 다른 것은 필요 없고 단지 특정객체의 메서드에만 관심이 있다고 가정해보죠. 특정객체의 메서드는 객체의 멤버로 소속되어 있기 때문에 객체의 모든 기능을 사용할 있을 것입니다. 그런데 어떻게 메서드만을 빼올까라는 생각을 하게 것입니다.

     

    C#에서 스레드를 실행한다는 것은 이와 비슷합니다. C#에서 사용되는 모든 스레드는 하나의 표준 스레드에 메서드만 추가 시켜주고 스레드를 시작하면 작업을 수행합니다. 만약 메서드 10개가 있다면 표준 스레드 10개를 만들고, 메서드를 표준 스레드에 하나씩 넣어주고 실행하라고 명령을 내리면 10개의 스레드가 동시에 작업을 수행하게 됩니다.

     

    스레드와 메서드의 관계는 아주 단순합니다. Main() 메서드도 알고 보면 스레드입니다. 표준 스레드에 Main() 넣어주고 실행해 달라는 것이니까요. , 10개의 Main 동시에 돌린다고 가정해 보죠. 이럴 때는 10개의 표준 스레드가 필요하고 10개의 Main() 메서드를 각각 넣어준 실행을 하면 10개의 스레드는 CPU Time 분할해서 사용하게 되는 것입니다. 너한번 다른 너한번...... 그리고 마지막으로 나한번! , 표준 스레드 입장에서는 항상 스레드가 수행되어지기 전에 어떤 메서드가 들어올지 궁금해 것입니다. 이런 면에서 스레드는 다른 객체의 메서드만을 빼와서 수행하고자 것입니다. 스레드는 메서드를 Delegate 포장해서 메서드만을 달라고 요청하는 것입니다. 실제 스레드를 실행하기 위한 예는 다음과 같습니다.

     

    n                  Top t = new Top();

    n                  Thread  t = new Thread(new ThreadStart(t.메서드));

    n                  thread.Start();

     

    C#에서 등장하는 Delegate 스레드, 이벤트에서 아주 중요한 역할을 담당하고 있습니다. 메서드를 캡슐화하여 이용하고자 한다면 어디든 등장하는 놈이 바로 Delegate입니다. 특정 객체에서 메서드를 직접 호출하는 것보다 메서드의 표준틀을 이용하여 사용하는 것이 휠씬 쉬우니까요. 그리고 사실 Delegate C++에서 메서드의 주소호출에 해당합니다. 메서드의 특정 주소를 이용하여 메서드를 더욱 안전하고 쉽게 호출하겠다는 의미를 담고 있습니다. 그대로 Delegate 메서드의 대리자가 되는 것입니다.

     

     

    출처 : 소설 같은 C#

    Posted by 나비:D
    :

    delegate string GetTextCallback();
    public string GetText()
    {
        if (this.cb_DataSelectTime.InvokeRequired)
        {
            GetTextCallback callback = new GetTextCallback(GetText);
            return (string) this.Invoke(callback, new object[] { });
        }
        else
        {
            return this.cb_DataSelectTime.Text;
        }
    }

    delegate void SetTextCallback();
    public string SetText()
    {
        if (this.cb_DataSelectTime.InvokeRequired)
        {
            SetTextCallback callback = new GetTextCallback(SetText);
            return (string) this.Invoke(callback, new object[] { });
        }
        else
        {
            return this.cb_DataSelectTime.Text;
        }
    }


    일단 Set 과 Get형식의 델리게이트..

    UI의 값을 참조시에는 Delegate와 INvokeRequired를 사용하여 호출 해주어야 한다.....

    왜?? 아직 잘모르겠따 ㅡㅡ;;;;
    생각보다 delegate가 먼말인지 모르겠돠 ㅡㅡ;;; 쟁장..

    Posted by 나비:D
    :

    출처 : http://msdn2.microsoft.com/ko-kr/library/ms171728(VS.80).aspx

    방법: 스레드로부터 안전한 방식으로 Windows Forms 컨트롤 호출

    Windows Forms 응용 프로그램의 성능 향상을 위해 다중 스레딩을 사용할 경우 스레드로부터 안전한 방식으로 컨트롤을 호출하도록 주의해야 합니다.

    예제

    Windows Forms 컨트롤에 대한 액세스는 기본적으로 스레드로부터 안전하지 않습니다. 컨트롤 상태를 조작하는 스레드가 두 개 이상 있는 경우 컨트롤이 일관성 없는 상태가 될 수 있습니다. 경합 상태, 교착 상태 등의 다른 스레드 관련 버그가 발생할 수 있습니다. 따라서 컨트롤에 대한 액세스가 스레드로부터 안전한 방식으로 수행되는지 확인해야 합니다.

    .NET Framework에서는 사용자가 스레드로부터 안전하지 않은 방식으로 컨트롤에 액세스할 경우 이를 감지할 수 있습니다. 디버거에서 응용 프로그램을 실행할 때 컨트롤을 만든 스레드가 아닌 스레드에서 해당 컨트롤을 호출하려고 하면 디버거에서 InvalidOperationException을 발생시키고 "control name 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다."라는 메시지를 표시합니다.

    이 예외는 일부 환경에서 런타임에 디버깅하는 동안 안정적으로 발생합니다. 이 예외가 발생할 경우 문제를 수정하는 것이 좋습니다. 이 예외는 .NET Framework 2.0 이전 버전에서 작성한 응용 프로그램을 디버깅할 때 발생할 수 있습니다.

    Note참고

    CheckForIllegalCrossThreadCalls 속성 값을 false로 설정하여 이 예외를 비활성화할 수 있습니다. 그러면 컨트롤이 Visual Studio 2003에서와 같은 방식으로 실행됩니다.

    다음 코드 예제에서는 작업자 스레드에서 스레드로부터 안전한 방식과 스레드로부터 안전하지 않은 방식으로 Windows Forms 컨트롤을 호출하는 방법을 보여 줍니다. 또한 스레드로부터 안전하지 않은 방식으로 TextBox 컨트롤의 Text 속성을 설정하는 방법과 스레드로부터 안전한 방식으로 Text 속성을 설정하는 두 가지 방법을 보여 줍니다.

    Visual Basic
    Imports System
    Imports System.ComponentModel
    Imports System.Threading
    Imports System.Windows.Forms
    
    Public Class Form1
       Inherits Form
       
       ' This delegate enables asynchronous calls for setting
       ' the text property on a TextBox control.
       Delegate Sub SetTextCallback([text] As String)
    
       ' This thread is used to demonstrate both thread-safe and
       ' unsafe ways to call a Windows Forms control.
       Private demoThread As Thread = Nothing
    
       ' This BackgroundWorker is used to demonstrate the 
       ' preferred way of performing asynchronous operations.
       Private WithEvents backgroundWorker1 As BackgroundWorker
    
       Private textBox1 As TextBox
       Private WithEvents setTextUnsafeBtn As Button
       Private WithEvents setTextSafeBtn As Button
       Private WithEvents setTextBackgroundWorkerBtn As Button
       
       Private components As System.ComponentModel.IContainer = Nothing
       
       
       Public Sub New()
          InitializeComponent()
        End Sub
       
       
       Protected Overrides Sub Dispose(disposing As Boolean)
          If disposing AndAlso Not (components Is Nothing) Then
             components.Dispose()
          End If
          MyBase.Dispose(disposing)
        End Sub
       
       
       ' This event handler creates a thread that calls a 
       ' Windows Forms control in an unsafe way.
        Private Sub setTextUnsafeBtn_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs) Handles setTextUnsafeBtn.Click
    
            Me.demoThread = New Thread( _
            New ThreadStart(AddressOf Me.ThreadProcUnsafe))
    
            Me.demoThread.Start()
        End Sub
       
       
       ' This method is executed on the worker thread and makes
       ' an unsafe call on the TextBox control.
       Private Sub ThreadProcUnsafe()
          Me.textBox1.Text = "This text was set unsafely."
       End Sub 
    
       ' This event handler creates a thread that calls a 
       ' Windows Forms control in a thread-safe way.
        Private Sub setTextSafeBtn_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs) Handles setTextSafeBtn.Click
    
            Me.demoThread = New Thread( _
            New ThreadStart(AddressOf Me.ThreadProcSafe))
    
            Me.demoThread.Start()
        End Sub
       
       
       ' This method is executed on the worker thread and makes
       ' a thread-safe call on the TextBox control.
       Private Sub ThreadProcSafe()
          Me.SetText("This text was set safely.")
        End Sub
    
       ' This method demonstrates a pattern for making thread-safe
       ' calls on a Windows Forms control. 
       '
       ' If the calling thread is different from the thread that
       ' created the TextBox control, this method creates a
       ' SetTextCallback and calls itself asynchronously using the
       ' Invoke method.
       '
       ' If the calling thread is the same as the thread that created
        ' the TextBox control, the Text property is set directly. 
    
        Private Sub SetText(ByVal [text] As String)
    
            ' InvokeRequired required compares the thread ID of the
            ' calling thread to the thread ID of the creating thread.
            ' If these threads are different, it returns true.
            If Me.textBox1.InvokeRequired Then
                Dim d As New SetTextCallback(AddressOf SetText)
                Me.Invoke(d, New Object() {[text]})
            Else
                Me.textBox1.Text = [text]
            End If
        End Sub
    
       ' This event handler starts the form's 
       ' BackgroundWorker by calling RunWorkerAsync.
       '
       ' The Text property of the TextBox control is set
       ' when the BackgroundWorker raises the RunWorkerCompleted
       ' event.
        Private Sub setTextBackgroundWorkerBtn_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs) Handles setTextBackgroundWorkerBtn.Click
            Me.backgroundWorker1.RunWorkerAsync()
        End Sub
       
       
       ' This event handler sets the Text property of the TextBox
       ' control. It is called on the thread that created the 
       ' TextBox control, so the call is thread-safe.
       '
       ' BackgroundWorker is the preferred way to perform asynchronous
       ' operations.
        Private Sub backgroundWorker1_RunWorkerCompleted( _
        ByVal sender As Object, _
        ByVal e As RunWorkerCompletedEventArgs) _
        Handles backgroundWorker1.RunWorkerCompleted
            Me.textBox1.Text = _
            "This text was set safely by BackgroundWorker."
        End Sub
    
       #Region "Windows Form Designer generated code"
       
       
       Private Sub InitializeComponent()
          Me.textBox1 = New System.Windows.Forms.TextBox()
          Me.setTextUnsafeBtn = New System.Windows.Forms.Button()
          Me.setTextSafeBtn = New System.Windows.Forms.Button()
          Me.setTextBackgroundWorkerBtn = New System.Windows.Forms.Button()
          Me.backgroundWorker1 = New System.ComponentModel.BackgroundWorker()
          Me.SuspendLayout()
          ' 
          ' textBox1
          ' 
          Me.textBox1.Location = New System.Drawing.Point(12, 12)
          Me.textBox1.Name = "textBox1"
          Me.textBox1.Size = New System.Drawing.Size(240, 20)
          Me.textBox1.TabIndex = 0
          ' 
          ' setTextUnsafeBtn
          ' 
          Me.setTextUnsafeBtn.Location = New System.Drawing.Point(15, 55)
          Me.setTextUnsafeBtn.Name = "setTextUnsafeBtn"
          Me.setTextUnsafeBtn.TabIndex = 1
          Me.setTextUnsafeBtn.Text = "Unsafe Call"
          ' 
          ' setTextSafeBtn
          ' 
          Me.setTextSafeBtn.Location = New System.Drawing.Point(96, 55)
          Me.setTextSafeBtn.Name = "setTextSafeBtn"
          Me.setTextSafeBtn.TabIndex = 2
          Me.setTextSafeBtn.Text = "Safe Call"
          ' 
          ' setTextBackgroundWorkerBtn
          ' 
          Me.setTextBackgroundWorkerBtn.Location = New System.Drawing.Point(177, 55)
          Me.setTextBackgroundWorkerBtn.Name = "setTextBackgroundWorkerBtn"
          Me.setTextBackgroundWorkerBtn.TabIndex = 3
          Me.setTextBackgroundWorkerBtn.Text = "Safe BW Call"
          ' 
          ' backgroundWorker1
          ' 
          ' 
          ' Form1
          ' 
          Me.ClientSize = New System.Drawing.Size(268, 96)
          Me.Controls.Add(setTextBackgroundWorkerBtn)
          Me.Controls.Add(setTextSafeBtn)
          Me.Controls.Add(setTextUnsafeBtn)
          Me.Controls.Add(textBox1)
          Me.Name = "Form1"
          Me.Text = "Form1"
          Me.ResumeLayout(False)
          Me.PerformLayout()
       End Sub 'InitializeComponent 
       
       #End Region
       
       <STAThread()>  _
       Shared Sub Main()
          Application.EnableVisualStyles()
          Application.Run(New Form1())
        End Sub
    End Class
    
    using System;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace CrossThreadDemo
    {
        public class Form1 : Form
        {
            // This delegate enables asynchronous calls for setting
            // the text property on a TextBox control.
            delegate void SetTextCallback(string text);
    
            // This thread is used to demonstrate both thread-safe and
            // unsafe ways to call a Windows Forms control.
            private Thread demoThread = null;
    
            // This BackgroundWorker is used to demonstrate the 
            // preferred way of performing asynchronous operations.
            private BackgroundWorker backgroundWorker1;
    
            private TextBox textBox1;
            private Button setTextUnsafeBtn;
            private Button setTextSafeBtn;
            private Button setTextBackgroundWorkerBtn;
    
            private System.ComponentModel.IContainer components = null;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            // This event handler creates a thread that calls a 
            // Windows Forms control in an unsafe way.
            private void setTextUnsafeBtn_Click(
                object sender, 
                EventArgs e)
            {
                this.demoThread = 
                    new Thread(new ThreadStart(this.ThreadProcUnsafe));
    
                this.demoThread.Start();
            }
    
            // This method is executed on the worker thread and makes
            // an unsafe call on the TextBox control.
            private void ThreadProcUnsafe()
            {
                this.textBox1.Text = "This text was set unsafely.";
            }
    
            // This event handler creates a thread that calls a 
            // Windows Forms control in a thread-safe way.
            private void setTextSafeBtn_Click(
                object sender, 
                EventArgs e)
            {
                this.demoThread = 
                    new Thread(new ThreadStart(this.ThreadProcSafe));
    
                this.demoThread.Start();
            }
    
            // This method is executed on the worker thread and makes
            // a thread-safe call on the TextBox control.
            private void ThreadProcSafe()
            {
                this.SetText("This text was set safely.");
            }
    
            // This method demonstrates a pattern for making thread-safe
            // calls on a Windows Forms control. 
            //
            // If the calling thread is different from the thread that
            // created the TextBox control, this method creates a
            // SetTextCallback and calls itself asynchronously using the
            // Invoke method.
            //
            // If the calling thread is the same as the thread that created
            // the TextBox control, the Text property is set directly. 
    
            private void SetText(string text)
            {
                // InvokeRequired required compares the thread ID of the
                // calling thread to the thread ID of the creating thread.
                // If these threads are different, it returns true.
                if (this.textBox1.InvokeRequired)
                {    
                    SetTextCallback d = new SetTextCallback(SetText);
                    this.Invoke(d, new object[] { text });
                }
                else
                {
                    this.textBox1.Text = text;
                }
            }
    
            // This event handler starts the form's 
            // BackgroundWorker by calling RunWorkerAsync.
            //
            // The Text property of the TextBox control is set
            // when the BackgroundWorker raises the RunWorkerCompleted
            // event.
            private void setTextBackgroundWorkerBtn_Click(
                object sender, 
                EventArgs e)
            {
                this.backgroundWorker1.RunWorkerAsync();
            }
            
            // This event handler sets the Text property of the TextBox
            // control. It is called on the thread that created the 
            // TextBox control, so the call is thread-safe.
            //
            // BackgroundWorker is the preferred way to perform asynchronous
            // operations.
    
            private void backgroundWorker1_RunWorkerCompleted(
                object sender, 
                RunWorkerCompletedEventArgs e)
            {
                this.textBox1.Text = 
                    "This text was set safely by BackgroundWorker.";
            }
    
            #region Windows Form Designer generated code
    
            private void InitializeComponent()
            {
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.setTextUnsafeBtn = new System.Windows.Forms.Button();
                this.setTextSafeBtn = new System.Windows.Forms.Button();
                this.setTextBackgroundWorkerBtn = new System.Windows.Forms.Button();
                this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
                this.SuspendLayout();
                // 
                // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(12, 12);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(240, 20);
                this.textBox1.TabIndex = 0;
                // 
                // setTextUnsafeBtn
                // 
                this.setTextUnsafeBtn.Location = new System.Drawing.Point(15, 55);
                this.setTextUnsafeBtn.Name = "setTextUnsafeBtn";
                this.setTextUnsafeBtn.TabIndex = 1;
                this.setTextUnsafeBtn.Text = "Unsafe Call";
                this.setTextUnsafeBtn.Click += new System.EventHandler(this.setTextUnsafeBtn_Click);
                // 
                // setTextSafeBtn
                // 
                this.setTextSafeBtn.Location = new System.Drawing.Point(96, 55);
                this.setTextSafeBtn.Name = "setTextSafeBtn";
                this.setTextSafeBtn.TabIndex = 2;
                this.setTextSafeBtn.Text = "Safe Call";
                this.setTextSafeBtn.Click += new System.EventHandler(this.setTextSafeBtn_Click);
                // 
                // setTextBackgroundWorkerBtn
                // 
                this.setTextBackgroundWorkerBtn.Location = new System.Drawing.Point(177, 55);
                this.setTextBackgroundWorkerBtn.Name = "setTextBackgroundWorkerBtn";
                this.setTextBackgroundWorkerBtn.TabIndex = 3;
                this.setTextBackgroundWorkerBtn.Text = "Safe BW Call";
                this.setTextBackgroundWorkerBtn.Click += new System.EventHandler(this.setTextBackgroundWorkerBtn_Click);
                // 
                // backgroundWorker1
                // 
                this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
                // 
                // Form1
                // 
                this.ClientSize = new System.Drawing.Size(268, 96);
                this.Controls.Add(this.setTextBackgroundWorkerBtn);
                this.Controls.Add(this.setTextSafeBtn);
                this.Controls.Add(this.setTextUnsafeBtn);
                this.Controls.Add(this.textBox1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
    
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.Run(new Form1());
            }
    
        }
    }
    

    스레드로부터 안전하지 않은 Windows Forms 컨트롤 호출

    스레드로부터 안전하지 않은 Windows Forms 컨트롤을 호출하는 방법은 작업자 스레드에서 직접 호출하는 것입니다. 응용 프로그램을 디버깅할 때 디버거에서는 InvalidOperationException을 발생시키고 컨트롤 호출이 스레드로부터 안전하지 않다는 경고를 표시합니다.

    Visual Basic
    ' This event handler creates a thread that calls a 
    ' Windows Forms control in an unsafe way.
     Private Sub setTextUnsafeBtn_Click( _
     ByVal sender As Object, _
     ByVal e As EventArgs) Handles setTextUnsafeBtn.Click
    
         Me.demoThread = New Thread( _
         New ThreadStart(AddressOf Me.ThreadProcUnsafe))
    
         Me.demoThread.Start()
     End Sub
    
    
    ' This method is executed on the worker thread and makes
    ' an unsafe call on the TextBox control.
    Private Sub ThreadProcUnsafe()
       Me.textBox1.Text = "This text was set unsafely."
    End Sub 
    
    // This event handler creates a thread that calls a 
    // Windows Forms control in an unsafe way.
    private void setTextUnsafeBtn_Click(
        object sender, 
        EventArgs e)
    {
        this.demoThread = 
            new Thread(new ThreadStart(this.ThreadProcUnsafe));
    
        this.demoThread.Start();
    }
    
    // This method is executed on the worker thread and makes
    // an unsafe call on the TextBox control.
    private void ThreadProcUnsafe()
    {
        this.textBox1.Text = "This text was set unsafely.";
    }
    

    스레드로부터 안전한 방식으로 Windows Forms 컨트롤 호출

    스레드로부터 안전한 방식으로 Windows Forms 컨트롤을 호출하려면

    1. 컨트롤의 InvokeRequired 속성을 쿼리합니다.

    2. InvokeRequiredtrue를 반환하는 경우에는 컨트롤을 실제로 호출하는 대리자를 사용하여 Invoke를 호출합니다.

    3. InvokeRequiredfalse를 반환하는 경우에는 컨트롤을 직접 호출합니다.

    다음 코드 예제에서는 SetText라는 유틸리티 메서드에서 이 논리를 구현합니다. SetTextDelegate 대리자 형식은 SetText 메서드를 캡슐화합니다. TextBox 컨트롤의 InvokeRequiredtrue를 반환하면 SetText 메서드는 SetTextDelegate 인스턴스를 만들고 폼의 Invoke 메서드를 호출합니다. 그러면 TextBox 컨트롤을 만든 스레드에서 SetText 메서드가 호출되고 이 스레드 컨텍스트에서 Text 속성이 직접 설정됩니다.

    Visual Basic
    ' This event handler creates a thread that calls a 
    ' Windows Forms control in a thread-safe way.
     Private Sub setTextSafeBtn_Click( _
     ByVal sender As Object, _
     ByVal e As EventArgs) Handles setTextSafeBtn.Click
    
         Me.demoThread = New Thread( _
         New ThreadStart(AddressOf Me.ThreadProcSafe))
    
         Me.demoThread.Start()
     End Sub
    
    
    ' This method is executed on the worker thread and makes
    ' a thread-safe call on the TextBox control.
    Private Sub ThreadProcSafe()
       Me.SetText("This text was set safely.")
     End Sub
    
    // This event handler creates a thread that calls a 
    // Windows Forms control in a thread-safe way.
    private void setTextSafeBtn_Click(
        object sender, 
        EventArgs e)
    {
        this.demoThread = 
            new Thread(new ThreadStart(this.ThreadProcSafe));
    
        this.demoThread.Start();
    }
    
    // This method is executed on the worker thread and makes
    // a thread-safe call on the TextBox control.
    private void ThreadProcSafe()
    {
        this.SetText("This text was set safely.");
    }
    
    Visual Basic
    ' This method demonstrates a pattern for making thread-safe
    ' calls on a Windows Forms control. 
    '
    ' If the calling thread is different from the thread that
    ' created the TextBox control, this method creates a
    ' SetTextCallback and calls itself asynchronously using the
    ' Invoke method.
    '
    ' If the calling thread is the same as the thread that created
     ' the TextBox control, the Text property is set directly. 
    
     Private Sub SetText(ByVal [text] As String)
    
         ' InvokeRequired required compares the thread ID of the
         ' calling thread to the thread ID of the creating thread.
         ' If these threads are different, it returns true.
         If Me.textBox1.InvokeRequired Then
             Dim d As New SetTextCallback(AddressOf SetText)
             Me.Invoke(d, New Object() {[text]})
         Else
             Me.textBox1.Text = [text]
         End If
     End Sub
    
    // This method demonstrates a pattern for making thread-safe
    // calls on a Windows Forms control. 
    //
    // If the calling thread is different from the thread that
    // created the TextBox control, this method creates a
    // SetTextCallback and calls itself asynchronously using the
    // Invoke method.
    //
    // If the calling thread is the same as the thread that created
    // the TextBox control, the Text property is set directly. 
    
    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.textBox1.InvokeRequired)
        {    
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox1.Text = text;
        }
    }
    

    BackgroundWorker를 사용하여 스레드로부터 안전한 방식으로 호출

    응용 프로그램에서 다중 스레딩을 구현하는 기본 방법은 BackgroundWorker 구성 요소를 사용하는 것입니다. BackgroundWorker 구성 요소는 다중 스레딩의 이벤트 구동 모델을 사용합니다. 작업자 스레드는 DoWork 이벤트 처리기를 실행하고 컨트롤을 만드는 스레드는 ProgressChangedRunWorkerCompleted 이벤트 처리기를 실행합니다. DoWork 이벤트 처리기에서 컨트롤을 호출하지 마십시오.

    다음 코드 예제에는 비동기적으로 수행되는 작업이 없으므로 DoWork 이벤트 처리기 구현이 없습니다. TextBox 컨트롤의 Text 속성은 RunWorkerCompleted 이벤트 처리기에서 직접 설정됩니다.

    Visual Basic
    ' This event handler starts the form's 
    ' BackgroundWorker by calling RunWorkerAsync.
    '
    ' The Text property of the TextBox control is set
    ' when the BackgroundWorker raises the RunWorkerCompleted
    ' event.
     Private Sub setTextBackgroundWorkerBtn_Click( _
     ByVal sender As Object, _
     ByVal e As EventArgs) Handles setTextBackgroundWorkerBtn.Click
         Me.backgroundWorker1.RunWorkerAsync()
     End Sub
    
    
    ' This event handler sets the Text property of the TextBox
    ' control. It is called on the thread that created the 
    ' TextBox control, so the call is thread-safe.
    '
    ' BackgroundWorker is the preferred way to perform asynchronous
    ' operations.
     Private Sub backgroundWorker1_RunWorkerCompleted( _
     ByVal sender As Object, _
     ByVal e As RunWorkerCompletedEventArgs) _
     Handles backgroundWorker1.RunWorkerCompleted
         Me.textBox1.Text = _
         "This text was set safely by BackgroundWorker."
     End Sub
    
    // This event handler starts the form's 
    // BackgroundWorker by calling RunWorkerAsync.
    //
    // The Text property of the TextBox control is set
    // when the BackgroundWorker raises the RunWorkerCompleted
    // event.
    private void setTextBackgroundWorkerBtn_Click(
        object sender, 
        EventArgs e)
    {
        this.backgroundWorker1.RunWorkerAsync();
    }
    
    // This event handler sets the Text property of the TextBox
    // control. It is called on the thread that created the 
    // TextBox control, so the call is thread-safe.
    //
    // BackgroundWorker is the preferred way to perform asynchronous
    // operations.
    
    private void backgroundWorker1_RunWorkerCompleted(
        object sender, 
        RunWorkerCompletedEventArgs e)
    {
        this.textBox1.Text = 
            "This text was set safely by BackgroundWorker.";
    }
    

    Windows Forms의 ActiveX 컨트롤

    폼에서 ActiveX 컨트롤을 사용하는 경우 디버거에서 실행할 때 크로스 스레드 InvalidOperationException이 발생할 수 있습니다. 이런 경우에는 ActiveX 컨트롤에서 다중 스레딩을 지원하지 않습니다. Windows Forms에서의 ActiveX 컨트롤 사용에 대한 자세한 내용은 Windows Forms 및 관리되지 않는 응용 프로그램을 참조하십시오.

    Visual Studio를 사용하는 경우에는 Visual Studio 호스팅 프로세스를 비활성화하여 이 예외가 발생하지 않도록 만들 수 있습니다.

    자세한 내용은 다음을 참조하십시오. 방법: 호스팅 프로세스 비활성화.

    강력한 프로그래밍

    Caution note주의

    어떤 종류의 다중 스레딩을 사용하든지 코드가 매우 심각하고 복잡한 버그에 노출될 수 있습니다. 다중 스레딩을 사용하는 솔루션을 구현하기 전에 관리되는 스레딩을 구현하는 최선의 방법에서 자세한 내용을 참조하십시오.

    참고 항목

    Posted by 나비:D
    :

    소켓통신으로 객체를 마샬링하여 통째로 전달하여 보자.

    우리가 소켓통신을 사용하다 보면 배열이나 구조체를 통째로

    날리면 편하겠다 라는 생각을 많이 하게 된다.

    먼저 우리가 알아두어야 할 개념이 있다.

    MarshalAsAttribute의 설명

    이 특성은 매개 변수, 필드 또는 반환 값에 적용될 수 있습니다.

    각 데이터 형식에 기본 마샬링 동작이 있으므로 이 특성은 선택적입니다. 이 특성은 주어진 형식을 여러 형식으로 마샬링할 수 있는 경우에만 필요합니다. 예를 들어, 문자열은 LPStr, LPWStr, LPTStr 또는 BStr로 관리되지 않는 코드로 마샬링할 수 있습니다. 기본적으로 공용 언어 런타임에서는 문자열 매개 변수를 BStr로 COM 메서드로 마샬링합니다. MarshalAsAttribute 속성을 개별 필드나 매개 변수에 적용하여 특정 문자열이 BStr 대신 LPStr로 마샬링되도록 할 수 있습니다. 형식 라이브러리 내보내기(Tlbexp.exe)는 사용자의 마샬링 기본 설정을 공용 언어 런타임에 전달합니다.

    일부 매개 변수 및 반환 값은 COM interop 또는 플랫폼 호출과 함께 사용할 경우 기본 마샬링 동작이 다릅니다. 기본적으로 런타임에서는 문자열 매개 변수 및 값 형식의 필드를 LPStr로 플랫폼 호출 메서드 또는 함수로 마샬링합니다. 자세한 내용은 기본 마샬링 동작을 참조하십시오.

    대부분의 경우 이 특성은 다음 C# 시그니처와 같이 UnmanagedType 열거형을 사용하는 관리되지 않는 데이터의 형식을 쉽게 식별합니다.

    void MyMethod([MarshalAs(LPStr)] String s);

    일부 UnmanagedType 열거형 멤버에는 추가 정보가 필요합니다. 예를 들어, UnmanagedTypeLPArray 일 때에는 추가 정보가 필요합니다. 이 특성을 배열에 사용하는 방법에 대한 자세한 내용은배열에 대한 기본 마샬링을 참조하십시오.

    형식 라이브러리 가져오기(Tlbimp.exe)는 이 특성을 매개 변수, 필드 및 반환 값에도 적용하여 입력 형식 라이브러리의 데이터 형식이 해당 관리되는 데이터 형식의 기본 형식이 아님을 나타냅니다. Tlbimp.exe는 입력 형식 라이브러리에 지정된 형식에 상관없이 명확함을 기하기 위해 StringObject 형식에 항상 MarshalAsAttribute를 적용합니다.


    예제를 보자.


    [C#]

    //Applied to a parameter.

      public void M1 ([MarshalAs(UnmanagedType.LPWStr)]String msg);

    //Applied to a field within a class.

      class MsgText {

        [MarshalAs(UnmanagedType.LPWStr)] Public String msg;

      }

    //Applied to a return value.

    [return: MarshalAs(UnmanagedType.LPWStr)]

    public String GetMessage();

     

    이 마샬링의 개념이 정리가 되었으면 이제  관리되지 않는 메모리 블록의 데이터를

    관리되는 개체로 마샬링하는 메서드를 정리 해보도록 하자.


    Marshal.PtrToStructure 메서드사용 예제

    UCOMITypeInfo typeInfo = ...;

    IntPtr ptr = IntPtr.Zero;

    typeInfo.GetTypeAttr(ref ptr);

    TYPEATTR attr = (TYPEATTR)Marshal.PtrToStructure(ptr,

        typeof(TYPEATTR));





    실전 객체 전달 프로그래밍


    using System.Runtime.InteropServices; //관리되지않는 코드 (포인터 사용및 구조체를 시퀜셜하게 만들기위해)

    using System.Text;

    using System.Net.Sockets;

    using System.Diagnostics;  


    // 클래스(구조체) 샘플.

    [StructLayout(LayoutKind.Sequential)]

    public class TempPacket

    {

        public byte Command;

        public byte Version;

        public ushort Length;        

        [MarshalAs(UnmanagedType.ByValArray, SizeConst=10)] public byte[] Data;  //바이트 배열....

    }


    public class Sample

    {

        public void Text()

        {

            TempPacket tmpPacket = new TempPacket();


            tmpPacket.Command = 0x10;

            tmpPacket.Version = 0x01;

            tmpPacket.Length = 10;

            tmpPacket.Data = Encoding.ASCII.GetBytes("0123456789");


            //객체를 보내보자.                    

            byte[] buffer = new byte[Marshal.SizeOf(tmpPacket)];

            unsafe

            {

                fixed(byte* fixed_buffer = buffer)

                {

                    Marshal.StructureToPtr(tmpPacket, (IntPtr)fixed_buffer, false);

                }

            }

       

            //소켓열고        

            TcpClient tcpClient = new TcpClient();

            tcpClient.Connect("localhost", 8296);

       

            NetworkStream networkStream = tcpClient.GetStream();

       

            networkStream.Write(buffer, 0, Marshal.SizeOf(tmpPacket));

                   

            //객체받고

            TempPacket tmpPacket2 = new TempPacket();

            networkStream.Read(buffer, 0, Marshal.SizeOf(tmpPacket));

            unsafe

            {

                fixed(byte* fixed_buffer = buffer)

                {

                    Marshal.PtrToStructure((IntPtr)fixed_buffer, tmpPacket2);

                }

            }    

            string data;

       

            data = Encoding.ASCII.GetString(tmpPacket2.Data, 0, 10);

            Debug.WriteLine(data);

            networkStream.Close();

            tcpClient.Close();

        }

    }


     


      작성자 : HOONS(박경훈)
      이메일 : tajopkh@hanmail.net
      홈페이지 : http://www.hoonsbara.com 

    Posted by 나비:D
    :

    BLOG main image
    by 나비:D

    공지사항

    카테고리

    분류 전체보기 (278)
    Programming? (0)
    ---------------------------.. (0)
    나비의삽질 (5)
    Application (177)
    SQL (51)
    Web (27)
    etc. (14)
    Omnia (0)
    ---------------------------.. (0)

    최근에 올라온 글

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함

    달력

    «   2024/12   »
    1 2 3 4 5 6 7
    8 9 10 11 12 13 14
    15 16 17 18 19 20 21
    22 23 24 25 26 27 28
    29 30 31
    Total :
    Today : Yesterday :