'OLE'에 해당되는 글 1건

  1. 2008.01.16 OLE Drag And Drop

OLE Drag And Drop

Program/C | C++ 2008. 1. 16. 22:50

# MFC 기반 OLE DnD

Dnd 를 구현하기 위한 최소한의 코드를 설명하고자 한다.
우선 Ole Dnd 를 구현하기 위해 순차적인 순서를 확인해보자.

1. 이동할 Source의 선택
2. 마우스 클릭한 상태에서 마우스 이동
3. Drop 할 대상 윈도우에 마우스를 이동시킨후 Drop 실행(클릭을 풀어준다)

이과정에서 필요한 MFC 라이브러리는
 CSharedFile, COleDataSource, COleDropTarget, COleDataObject 클래스와 DROPEFFECT 구조체이다.

텍스트 에디터상에서 블록화된 텍스트를 Dnd 할 경우 1. 번 과정 이전에 Drag 할 데이터를 선택하는 작업이 필요할 것이다.
( 블록화된 데이터 렉트 안에서 마우스 클릭을 유지하는가.)
작성자가 작업했던 곳을 ListCtrl 이였으므로 이에 대한 설명을 생략하고.
앞으로의 설명은  ListCtrl에서 ListCtrl, ListBox 및 기타 다른 윈도우. 컨트롤로의 드롭이다.

# Drag가 일어나는 컨트롤 / 윈도우..
드래그가 일어나는 리스트컨트롤을 서브 클래싱 해야 한다.
서브 클래싱을 하는 이유는 OnMouseMove 이벤트를 사용하기 위함이다.
이를 서브 클래싱 하였다면 OnMouseMove 이벤트 핸들러에서부터 작업을 시작한다.

1. 마우스 버튼이 클릭된 상태인지 확인한다.
      if ( (nFlags & MK_LBUTTON) )

2. 선택된 데이터의 이동인지 복사인지 확인한다. ( 컨트롤 키보드를 통해 )
  if ( nFlags & MK_CONTROL )
   DropEffect = DROPEFFECT_COPY;
  else
   DropEffect = DROPEFFECT_MOVE;

3. Drag 임이 확인되었다면 이동시킬 데이터를 꾸려야 한다.
이단계에서 데이터를 이동시킬 타겟을 알 수 없다.

 - 데이터를 보관할 저장소 생성
   CSharedFile sf(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT);

 - 저장소에 데이터 복사( 문자열을 넘겨 보겠다)
   CString DataString = "나 데이터~";
   sf.Write(DataString, DataString.GetLength() );
  ( 클립보드를 이용하여 데이터를 임시 보관 할 수 도 있겠지만.. 꽁수? )

 - 실제적으로 보내지는 데이터
   HGLOBAL hData;
   hData = sf.Detach();

4. 데이터를 보내기...
   COleDataSource Source;
   Source.CacheGlobalData(CF_TEXT, hData);
   문자열을 보내기 때문에 CF_TEXT가 된다..

5. Drag의 시작
   Source.DoDragDrop(DropEffect);
  DropEffect 는 DROPEFFECT 형 변수로써 타겟에서 이 값을 확인하여 복사인지 이동인지를 판단 할 수 있다.

# Drop Target ( 윈도우, 컨트롤 )
Drop 이벤트는 COleDropTarget::OnDrop( 생략 ~ ) 에서 핸들링 하는데..
타겟 윈도우에서 이 이벤트를 받기위해선 COleDropTarget 형 변수를 선언하고 핸들러를 재정의 하거나 DropTarget 클래스를 상속받은 클래스를 생성하여 함수를 재정의 할 수도 있다..
작성자는 CDropTarget 을 상속받는 클래스를 생성한후
OnDrop(CWnd * pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)  
함수를 재정의 할 것이며 이외에도 기타 다른 함수들을 구현함으로서 좀 더 테크니컬하게 만들 수 있을 것이다.

1. COleDropTarget 상속
   class MyDropTarget : public COleDropTarget

2. OnDrop 함수 재정의
이부분은 대상 타겟에서 마우스를 끌어다 놓았을 때 발생 하는 메세지를 처리한다.
메세지 맵에 메세지를 등록하지 않아도 될 것이다.
인자로 넘어오는 값을 살펴 보면
 pWnd : Drop 이벤트를 받은 윈도우
 pDataObject : 넘어온 데이터
 dropEffect : 드랍 효과
 point : 마우스 포인터

넘어온 데이터는 데이터를 꾸릴때와 반대의 방법으로 하면 원래 데이터를 구할 수 있다
  HGLOBAL hData = hData = pDataObject->GetGlobalData(CF_TEXT);
  CMemFile sf( (BYTE*) ::GlobalLock(hData), ::GlobalSize(hData) );
  CString DataString;
  LPSTR str = DataString.GetBufferSetLength(::GlobalSize(hData) );
  sf.Read(str, ::GlobalSize(hData) );
  ::GlobalUnlock(hData);

  이렇게 작업을 해주면 DataString 에 "나 데이터~ " 값을 확인 할 수 있을 것이다.

# 레지스트리 등록.. DropTarget 등록..
Drop의 대상이 되는 윈도우나 컨트롤(서브클래싱이 필요할 것이다)에 MyDropTarget형 변수를 선언한후.. 타겟윈도우의 생성자나 Init 부분에서
Register() 함수를 통해 Ole 를 사용함을 등록하여야 한다.
등록이 있다면 반드시 소멸또한... Revoke() 있을 것이다.
Drop 이벤트를 받는 클래스는 반드시 MyDropTarget 형 변수가 있어야 이벤트를 받을 수 있을것이다.

주절 주절 적어봤지만, 역시나 검증되진 않았다는것!!
여러가지 상황에 대한 고려와... 테크니컬한 기술들이 빠져있는 Ole Drag And Drop에 대한 맛보기 정도로 생각하면 될 것이다.

'Program > C | C++' 카테고리의 다른 글

팝업 메뉴..  (0) 2008.01.16
마우스 포인터를 이용한 윈도우 핸들  (0) 2008.01.16
WaitForSingleObject 관련 스레드 다루기  (1) 2008.01.16
: