[태그:] c++

  • C# Extensions Method

    C# 3.0부터 추가된 기능이다. 이 기능을 사용하게 되면 기존 형식을 확장, 수정하지 않고도 메소드를 추가할 수 있다. Microsoft .NET 문서 에선 확장메서드를 호출하나 Extensions Method 나 차이가 없다고 서술하고 있다.

    확장명 메서드를 호출하는 것과 형식에 실제로 정의된 메서드를 호출하는 데는 명백한 차이가 없습니다.
    

    사용용도

    이 기능은 어느 클래스에나 사용할 수 있기 때문에 특정한 범위에서 사용하는 것이 좋다. 일반적으로 봉인된(sealed) 클래스에 필요한 기능을 추가할 수 없을 때가 가장 적합한 사용용도 인 거 같다.

    사용방법

    사용방법은 생각보다 간단하다. String 클래스를 예로 들어보겠다.

    namespace ExtensionMethods
    {
        public static class MyExtensions
        {
            public static int WordCount(this String str)
            {
                return str.Split(new char[] { ' ', '.', '?' }, 
                                 StringSplitOptions.RemoveEmptyEntries).Length;
            }
        }   
    }
    

    Extensions Method의 생성 조건이 몇 가지 있다.

    • 클래스는 static으로 선언해준다. ( 자동으로 함수도 static )
    • 매개변수의 첫 번째는 this와 해당 메소드가 들어갈 타입을 적어준다.

    예제에 맞게 적고 string 변수를 확인해보면 WorldCount 라는 함수가 보일 것이다.

    기타 설명

    더 자세한건 Microsoft .NET 문서 를 참고하길 바란다.


    Unity + Extensions Method

    이 기능을 유니티에 가져와 적용해본다면 기존에 불필요하게 했던 작업을 함수 하나로 보기 좋게 정리할 수 있게 된다.

    기존에 유니티 기능으로만 사용했을 때 불편한 작업이 있었다.

    • transform.position의 x값만 바꾸고 싶을 때
    • Sprite의 Color중 Alpha 값만 바꾸고 싶을 때
    • 배열에서 랜덤을 뽑고 싶을 때 ( 물론 이건 C#이지만..ㅋ )

    등등 상황에 따라 더 있겠지만 저런 상황에 Extensions Method 기능을 사용하면 매우 편리하다.

    첫 번째 경우를 가지고 설명하자면 Unity의 Transform 클래스에 Extensions Method를 추가하면 좀 더 코드가 깔끔해지고 보기 편해진다.

    TransformExtensions.cs

    using UnityEngine;
    
    public static class TransformExtensions
    {
        public static void SetPositionX(this Transform transform, float x)
        {
            var newPosition = new Vector3(x, transform.position.y, transform.position.z);
            transform.position = newPosition;
        }
    }
    

    Test.cs

    using UnityEngine;
    
    public class Test : MonoBehaviour
    {
        private void Start()
        {
            // 이전의 X값 변경 방법
            transform.position = Vector3.zero;
            Debug.Log("[Basic] Prev: " + transform.position);
            transform.position = new Vector3(20, transform.position.y, transform.position.z);
            Debug.Log("[Basic] Curr: " + transform.position);
    
            // Extensions Method
            transform.position = Vector3.zero;
            Debug.Log("[Extensions] Prev: " + transform.position);
            transform.SetPositionX(20);
            Debug.Log("[Extensions] Curr: " + transform.position);
        }
    }
    

    마무리

    Extensions Method는 클래스의 수정이 불가능한 부분들에 의한 반복적인 일들을 줄여줄 수 있는 좋은 기능인 것 같다. 유니티로 개발을 하면서 어쩔 수 없이 반복적이고 불필요한 코드들이 늘어난다면 이 기능을 이용해 리팩토링하는 것도 좋을 것 같다.

  • CDockablePane에 Dialog 등록

    http://cafe.naver.com/ssua/517

    CDockablePanel에 Dialog를 등록하여 사용할경우 컨트롤러를 직접 생성하는것보다 편리하다.

    처리해야할 부분

    기본적으로 CDockablePanel를 상속받아 Panel을 만들고 OnCreate 에서 다이얼로그를 생성하여 등록 하면

    되지만 부가적으로 해야할 처리들이 몇가지 존재한다.

    1. 페널의 사이즈가 변경될시 다이얼로그의 사이즈도 변경해 줘야 한다.

    2. 페널이 포커스되면 다이얼로그에  포커스를 설정해 줘야 한다.

    3. 페널위 다이얼로그에서 마우스 오른쪽 클릭시에도 DockablePane Context menu (도킹관련 팝업메뉴)가 떠버려

    다이얼로그를 가리게 되며 다이얼로그 위에서 마우스 왼쪽 클릭을 해도 사라지지 않는 문제점이 발생한다

    이를 위해 Context Menu를 차단 해줘야 한다.

    세부 작업 설명

    1. 다이얼로그 생성한후 아래와 같이 셋팅하자.

    Dialog.Properties.Border = None

    Dialog.Properties.Style = Child

    2. 페널 생성.

    클래스 위자드->MFC클래스-> Base Class(상속받을 클래스)에 CDockablePane 설정후 페널 생성.

    3. 페널에 다이얼로그 등록.

    페널에 WM_CREATE 메시지 핸들러 등록.

    int DockingPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CDockablePane::OnCreate(lpCreateStruct) == -1)
    return -1;

    // TODO:  Add your specialized creation code here
    BOOL bRet = m_Dialog.Create(IDD_TEST_DOCKING, this);
    ASSERT( bRet );
    m_Dialog.ShowWindow(SW_SHOW);

    return 0;
    }

    4. 사이즈 변화에 대한 다이얼로그 적용.

    페널에  WM_SIZE 메시지 핸들러 등록.

    void DockingPane::OnSize(UINT nType, int cx, int cy)
    {
    CDockablePane::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    m_Dialog.MoveWindow( 0, 0, cx, cy );
     //m_Dialog.SetWindowPos (NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
    }

    5. 페널이 포커스시 다이얼로그포커스 설정.

    페널에 WM_SETFOCUS 메시지 핸들러 등록.

    void DockingPane::OnSetFocus(CWnd* pOldWnd)
    {
    CDockablePane::OnSetFocus(pOldWnd);

    // TODO: Add your message handler code here
     m_Dialog.SetFocus();
    }

    6. DockablePane Context menu 차단.

    OnShowControlBarMenu 함수를 오버라이딩하여 Base클래스에서의 처리를 막아버린다.

    //: h

    virtual BOOL OnShowControlBarMenu(CPoint point);

    //: cpp

    BOOL DockingPane::OnShowControlBarMenu( CPoint point )
    {
    return FALSE;
    }

    기타

    ! vs2010 에서는 다이얼로그 페널(CPaneDialog)을 자체적으로 지원하는 걸로 알고 있다.

  • Drag & Drop기능

    [참조사이트]http://blog.naver.com/iperfume/100048381739

    1. 파일 드래그앤 드롭했을때 파일명과 경로를 입력하는방법

    http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=278&MAEULNo=20&no=21664&ref=21664

    2. codeproject 자료

    http://www.codeproject.com/clipboard/ddmgr.asp

    3. Devpia 자료

    3-1. http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=494120&ref=494120

    3-2. http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=466864&ref=466864

    4. 탐색기에서 응용프로그램으로 드래그 앤 드롭

    http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=469642&ref=469609

    Drag & Drop은 주로 두개의 서로 다른 프로그램 사이에서 일어나는 과정이므로 COM 인터페이스를 이용해 표준화 되어있다.

    IDropSource, IDropTarger, IDataObject 인터페이스를 통해 구현하도록 되어 있으며 RegisterDragDrop, DoDragDrop이라는 API함수를 호출하여 Drap&Drop을 시작한다.

    DoDragDrop함수가 호출된 이후의 나머지 과정(DragEnter, DragOver, Drop, DragLeave)은 운영체제가 맡아서 처리해준다.

    MFC에서는 Drag&Drop을 쉽게 구현할 수 있도록 COleDropSource, COleDropTarget, COleDataObject클래스를 제공하고 있다.

    5. Drag&Drop 으로 URL얻어오기(소스포함)

      – 인터넷 익스플로우에서 응용프로그램으로 Drag&Drop을 했을때 URL얻어오는 방법

    http://www.codeguru.com/Cpp/I-N/internet/article.php/c3363

    6. ListCtrl간 드래그앤 드롭

    http://blog.naver.com/sjhghj/140104051130