다음을 통해 공유


MFC/ole 2 TN041: MFC/OLE1 마이그레이션

[!참고]

온라인 설명서의을 처음 포함 되었습니다 때문 다음 기술 참고 업데이트 되지 않았습니다.따라서 일부 절차 및 항목 오래 되었거나 잘못 된 수 있습니다.최신 정보는 온라인 설명서 색인에서 관심 있는 주제에 대해 검색 하는 것이 좋습니다.

마이그레이션에 관련 된 일반적인 문제

OLE 1.0 지원에 대 한 MFC 2.0에서 위치 배치 같은 아키텍처의 많은 유지 하려면 OLE 2 클래스 (및 높은)에서 MFC 2.5의 디자인 목표 중 하나입니다.결과적으로 많은 같은 OLE 클래스가 MFC 2.0에서이 버전의 MFC에서는 아직 (COleDocument, COleServerDoc, COleClientItem, COleServerItem).또한 Api에서 이러한 클래스의 대부분은 동일합니다.그러나, 몇 가지 세부 사항을 변경한 예상할 수 있도록 OLE 2 OLE 1.0에서 상당히 다른입니다.MFC 2.0 OLE1 지원을 사용 하는 데 익숙한 경우 MFC의 2.0 지원으로 집에서 생각 하겠습니다.

기존 MFC/OLE1 신청서를 가져오고 OLE 2 기능을 추가 하는 경우 먼저이 글을 읽어야 합니다.이 참고가 OLE1 기능 OLE MFC/2로 이식 하는 동안 발생할 수 및 다음 MFC 2.0에 포함 된 두 개의 응용 프로그램을 이식 하는 동안 처리 되지 않는 문제에 설명 하는 몇 가지 일반적인 문제를 다룹니다: MFC OLE 샘플 OCLIENTHIERSVR.

MFC 문서/뷰 아키텍처 중요

이제 응용 프로그램 MFC의 문서/뷰 아키텍처를 사용 하지 않고 OLE 2 지원 응용 프로그램에 추가 하려는 경우 문서/뷰를 이동 하는 시간을입니다.기본 아키텍처 및 구성 요소 mfc 응용 프로그램을 사용 하면 여러 가지 MFC의 OLE 2 클래스의 장점을 얻을 수 있습니다.

MFC 아키텍처를 사용 하지 않고 서버 또는 컨테이너 구현 가능 하지만 권장 하지 않음입니다.

대신 자신의 MFC 구현 사용

같은 클래스를 "MFC 구현 고정" CToolBar, CStatusBar, 및 CScrollView OLE 2 지원에 대 한 특별 한 사례 코드를 기본 제공 합니다.따라서 이러한 클래스를 응용 프로그램에서 사용할 수 있는 경우 해당 OLE 인식 하 게 노력에서 이점이 하겠습니다.다시는 이러한 목적을 위해 "롤 자신만" 클래스에 수 있지만 않는 것이 좋습니다.비슷한 기능을 구현 하는 경우 (특히이 현재 위치에서 활성화 하면) MFC 소스 코드는 OLE의 미세한 점 중 일부를 처리 하기 위한 탁월한 참조입니다.

MFC 샘플 코드를 검사 합니다.

OLE 기능을 포함 하는 MFC 샘플의 숫자가입니다.이 응용 프로그램은 서로 다른 각도에서 OLE를 구현합니다.

  • HIERSVR 주로 사용 하는 서버 응용 프로그램 위한 것입니다.이 MFC 2.0 응용 프로그램과 MFC/o l e 1에에서 포함 된 및 MFC/OLE 2로 이식 되어 OLE 2에서 사용할 수 있는 여러 가지 OLE 기능을 구현 하도록 다음 확장 합니다.

  • OCLIENT 이 독립 실행형 컨테이너 응용 프로그램 컨테이너 관점에서 많은 OLE 기능을 보여 주는 것입니다.MFC 2.0에서을 너무 이식 된 대부분의 사용자 지정 된 클립보드 형식 및 포함 된 항목에 대 한 링크와 같은 고급 OLE 기능을 지원 하 고 확장 합니다.

  • DRAWCLI OCLIENT 처럼 기존 개체 지향 그리기 프로그램의 프레임 워크 내에서 제어권을 제외 하 고이 응용 프로그램이 OLE 컨테이너 지원을 훨씬 구현 합니다.이 그림에서는 OLE 컨테이너 지원을 구현 하 고 기존 응용 프로그램에 통합할 하는 것을 보여 줍니다.

  • SUPERPAD 하 여 훌륭한 독립 실행형 응용 프로그램 뿐 아니라이 응용 프로그램에는 또한 OLE 서버.구현 하는 서버 지원 자동 원칙은입니다.특히 어떻게 OLE 클립보드 서비스 데이터를 클립보드에 복사 하려면 사용 하지만 "Windows"편집 컨트롤에 적용 되는 기능을 사용 하 여 클립보드 붙여넣기 기능을 구현 합니다.이 새 OLE Api와의 통합은 물론 전통적인 Windows API 사용은 흥미로운 조합을 보여 줍니다.

샘플 응용 프로그램에 대 한 자세한 내용은 "MFC 샘플 도움말"을 참조 하십시오.

사례 연구: OCLIENT MFC 2.0에서

위에서 설명한 것 처럼 OCLIENT OLE MFC/o l e 1을 구현 하 고 MFC 2.0에 포함 되었습니다.가이 응용 프로그램 초기에 변환 되었습니다 OLE MFC/2 클래스를 사용 하는 단계는 다음과 같습니다.초기 포트 MFC/OLE 클래스를 잘 설명 하기 위해 완료 된 많은 기능이 추가 되었습니다.이러한 기능은 여기서 다루지 않습니다. 샘플 자체는 고급 기능에 대 한 자세한 내용은 참조 하십시오.

[!참고]

컴파일러 오류 및 단계별 프로세스는 Visual C++ 2.0으로 만들었습니다.Visual C++ 4.0에 특정 오류 메시지 및 위치가 변경 되었을 수 있지만 개념적 정보 유효 합니다.

이 시작

OCLIENT 샘플 ole MFC/포트에 적용 되는 방법을 일어나지 확실 한 컴파일러 오류를 수정 하 고 빌드를 시작 하는 것.MFC 2.0에서 OCLIENT 샘플을 가져와서이 버전의 MFC에서 컴파일해야 하는 경우에 많은 오류를 해결할 수 없는 찾을 수 있습니다.오류에서 발생 하는 순서에 대 한 설명은 다음과 같습니다.

컴파일 및 오류 수정

\oclient\mainview.cpp(104) : error C2660: 'Draw' : function does not take 4 parameters

첫 번째 오류 문제 COleClientItem::Draw.MFC/ole1에 걸리는 MFC/OLE 버전에 걸리는 시간 보다 더 많은 매개 변수입니다.다른 매개 변수는 필요 하 고 일반적으로 NULL (이 예에서 같이) 경우가 있었습니다.자동으로이 버전의 MFC 때 메타 파일 DC에 그리고 CDC는 Lpwbounds의 값을 결정할 수 있습니다.프레임 워크에서 "DC"의 특성은 Pdc에 전달 구성 됩니다 때문 뿐만 아니라, pFormatDC 매개 변수는 더 이상 필요.이 문제를 해결 하려면 단순히 두 제거 되므로 추가 그리기 호출에 매개 변수는 NULL입니다.

\oclient\mainview.cpp(273) : error C2065: 'OLE_MAXNAMESIZE' : undeclared identifier
\oclient\mainview.cpp(273) : error C2057: expected constant expression
\oclient\mainview.cpp(280) : error C2664: 'CreateLinkFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '
\oclient\mainview.cpp(286) : error C2664: 'CreateFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '
\oclient\mainview.cpp(288) : error C2664: 'CreateStaticFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '

결과 사실에서 위의 오류는 모두의 COleClientItem::CreateXXXX 함수가 MFC/o l e 1에 필요한 고유 이름을 전달 될 항목을 나타냅니다.이 기본 OLE API의 요구 사항입니다.OLE 2 DDE (이름을 DDE 대화에서 사용한)의 기본 통신 메커니즘으로 사용 하지 않으므로 MFC/OLE 2에 필요한 수 없습니다.이 문제를 해결 하려면 제거 수는 CreateNewName 함수에 대 한 모든 참조는 물론.어떤 각 MFC/OLE 함수가이 버전에서는 커서 호출을 배치 하 고 F1 키를 누르면 하 여 예상 아웃 찾기 쉽습니다.

또 다른 영역은 크게 달라 지는 OLE 2 클립보드 처리 됩니다.O l e 1을 Windows 클립보드에 클립보드 Api와 상호 작용을 사용 합니다.OLE 2 다른 메커니즘으로 이루어집니다.MFC/OLE1 Api 클립보드 복사 하기 전에 열려 있던 가정은 COleClientItem 개체는 클립보드에.이 작업이 필요 하지 않습니다 및 모든 MFC/OLE 클립보드 작업이 실패할 수 발생 합니다.종속성을 제거 하는 코드를 편집 하는 동안 CreateNewName를 열고 닫으면 Windows 클립보드 코드를 또한 제거 해야 합니다.

\oclient\mainview.cpp(332) : error C2065: 'AfxOleInsertDialog' : undeclared identifier
\oclient\mainview.cpp(332) : error C2064: term does not evaluate to a function
\oclient\mainview.cpp(344) : error C2057: expected constant expression
\oclient\mainview.cpp(347) : error C2039: 'CreateNewObject' : is not a member of 'CRectItem'

이러한 오류에서 결과 CMainView::OnInsertObject 처리기입니다."새 개체 삽입" 명령 처리 내용이 상당히 변경 어디 다른 영역입니다.이 경우 단순히 원본 구현을 새 OLE 컨테이너 응용 프로그램을 제공 하는 응용 프로그램 마법사에서 병합 하는 것이 더 쉽습니다.사실,이 적용할 수 있는 다른 응용 프로그램을 이식 하는 기술입니다.OLE1/MFC에서 "삽입 개체" 대화 상자를 호출 하 여 표시 AfxOleInsertDialog 함수.이 버전에서는 구성 된 COleInsertObject dialog 개체와 호출 DoModal.또한 OLE 항목을 새로 만든 된 CLSID classname 문자열 대신 합니다.결국이 비슷합니다.

COleInsertDialog dlg;
if (dlg.DoModal() != IDOK)
    return;

BeginWaitCursor();

CRectItem* pItem = NULL;
TRY
{
    // First create the C++ object
    pItem = GetDocument()->CreateItem();
    ASSERT_VALID(pItem);

    // Initialize the item from the dialog data.
    if (!dlg.CreateItem(pItem))
        AfxThrowMemoryException();
           // any exception will do
    ASSERT_VALID(pItem);
        
    // run the object if appropriate
    if (dlg.GetSelectionType() == 
            COleInsertDialog::createNewItem)
        pItem->DoVerb(OLEIVERB_SHOW, this);
        
    // update right away
    pItem->UpdateLink();
    pItem->UpdateItemRectFromServer();
        
    // set selection to newly inserted item
    SetSelection(pItem);
    pItem->Invalidate();
}
CATCH (CException, e)
{  
    // clean up item
    if (pItem != NULL)
        GetDocument()->DeleteItem(pItem);
            
    AfxMessageBox(IDP_FAILED_TO_CREATE);
}
END_CATCH
    
EndWaitCursor();

[!참고]

새 개체 삽입 응용 프로그램에 다를 수 있습니다):

또한 선언에 포함 된 <afxodlgs.h>를 포함 하는 데 필요한 것은 COleInsertObject 대화 상자 클래스 뿐 아니라 MFC에서 제공 되는 표준 대화 상자입니다.

\oclient\mainview.cpp(367) : error C2065: 'OLEVERB_PRIMARY' : undeclared identifier
\oclient\mainview.cpp(367) : error C2660: 'DoVerb' : function does not take 1 parameters

개념에는 경우에 일부 OLE1 상수 OLE 2에서 변경 된 사실을 이러한 오류가 발생 합니다.이 경우 OLEVERB_PRIMARY 위해 변경 되었습니다 OLEIVERB_PRIMARY.항목을 클릭할 때 기본 동사 OLE1 및 OLE 2의 컨테이너에서 일반적으로 실행 됩니다.

또한 DoVerb 추가 매개 변수가 더 길어진 — 보기에 대 한 포인터 (CView*).이 매개 변수는 "비주얼 편집" (또는 현재 위치에서 활성화) 구현에 사용 됩니다.이 지금은이 기능을 구현 하지 않는 있으므로 이제 해당 매개 변수가 NULL로 설정 합니다.

프레임 워크는 원위치 하는 시도 활성화 했는지 확인 하려면 재정의 해야 COleClientItem::CanActivate 는 다음과 같이 하십시오.

BOOL CRectItem::CanActivate()
{
    return FALSE;
}

\oclient\rectitem.cpp(53) : error C2065: 'GetBounds' : undeclared identifier
\oclient\rectitem.cpp(53) : error C2064: term does not evaluate to a function
\oclient\rectitem.cpp(84) : error C2065: 'SetBounds' : undeclared identifier
\oclient\rectitem.cpp(84) : error C2064: term does not evaluate to a function

MFC/ole1에서 COleClientItem::GetBoundsSetBounds 쿼리 및 항목의 범위를 조작 하는 데 사용 된 (의 왼쪽 구성원 이었던 항상 0).OLE MFC/2이 직접 지 COleClientItem::GetExtentSetExtent, 어떤 처리로 크기 또는 CSize 대신.

코드를 새로운 SetItemRectToServer 및 UpdateItemRectFromServer 호출 모양은:

BOOL CRectItem::UpdateItemRectFromServer()
{
   ASSERT(m_bTrackServerSize);
   CSize size;
   if (!GetExtent(&size))
      return FALSE;    // blank

   // map from HIMETRIC to screen coordinates
   {
      CClientDC screenDC(NULL);
      screenDC.SetMapMode(MM_HIMETRIC);
      screenDC.LPtoDP(&size);
   }
   // just set the item size
   if (m_rect.Size() != size)
   {
      // invalidate the old size/position
      Invalidate();
      m_rect.right = m_rect.left + size.cx;
      m_rect.bottom = m_rect.top + size.cy;
      // as well as the new size/position
      Invalidate();
   }
   return TRUE;
}

BOOL CRectItem::SetItemRectToServer()
{
   // set the official bounds for the embedded item
   CSize size = m_rect.Size();
   {
      CClientDC screenDC(NULL);
      screenDC.SetMapMode(MM_HIMETRIC);
      screenDC.DPtoLP(&size);
   }
   TRY
   {
      SetExtent(size);  // may do a wait
   }
   CATCH(CException, e)
   {
      return FALSE;  // links will not allow SetBounds
   }
   END_CATCH
   return TRUE;
}

\oclient\frame.cpp(50) : error C2039: 'InWaitForRelease' : is not a member of 'COleClientItem'
\oclient\frame.cpp(50) : error C2065: 'InWaitForRelease' : undeclared identifier
\oclient\frame.cpp(50) : error C2064: term does not evaluate to a function

MFC/OLE1 동기식 API의 서버 컨테이너에서 호출 된 시뮬레이트된, OLE1 본질적으로 대부분의 비동기 때문입니다.처리 중인 비동기 호출 중에서에 사용자 로부터 명령을 처리 하기 전에 확인 해야 했습니다.MFC/OLE1 제공 되는 COleClientItem::InWaitForRelease 함수를 수행 하기 위해.Cmainframe에 oncommand 재정의 모두 함께 제거할 수 있도록 OLE MFC/2이 필요 하지 않습니다.

이때 OCLIENT 컴파일하고 링크 합니다.

기타 필요한 사항

그러나 OCLIENT 실행, 유지 됩니다 수행 되지 않는 몇 가지 있습니다.이제 대신 나중에 이러한 문제를 해결 하는 것이 좋습니다.

첫째, OLE 라이브러리를 초기화 하는 것이 필요 합니다.이 호출 하 여 수행 됩니다 AfxOleInit 에서 InitInstance:

if (!AfxOleInit())
{
  AfxMessageBox("Failed to initialize OLE libraries");
  return FALSE;
}

매개 변수 목록 변경 내용에 대 한 가상 함수를 확인 하는 좋은 방법 이기도 합니다.이러한 함수는 COleClientItem::OnChange, 재정의 된 모든 MFC/OLE 컨테이너 응용 프로그램에서.온라인 도움말에 보면은 여분의 'DWORD dwParam'이 추가 되었습니다 표시 됩니다.새로운 Crectitem::onchange는 다음과 같습니다.

void 
CRectItem::OnChange(OLE_NOTIFICATION wNotification, DWORD dwParam)
{
  if (m_bTrackServerSize &&
        !UpdateItemRectFromServer())
  {
    // Blank object
    if (wNotification == OLE_CLOSED)
    {
      // no data received for the object - destroy it
      ASSERT(!IsVisible());
      GetDocument()->DeleteItem(this);
      return;   // no update (item is gone now)
    }
  }
  if (wNotification != OLE_CLOSED)
      Dirty();
  Invalidate();  // any change will cause a redraw
}

OLE1/MFC, 컨테이너 응용 프로그램에서 문서 클래스를 파생 된 COleClientDoc.OLE MFC/2이이 클래스 제거 되었으며 대체 COleDocument (이 새 조직 컨테이너/서버 응용 프로그램을 구축 하기 쉽습니다).되는 #define 는 매핑합니다 COleClientDocCOleDocument MFC/OLE1 OCLIENT 같은 OLE MFC/2 응용 프로그램의 이식 단순화할 수.제공 하지의 기능 중 하나 COleDocument 에서 제공 된 COleClientDoc 표준 명령 메시지 맵 항목입니다.지금 것이 또한 사용 하는 서버 응용 프로그램을 COleDocument 컨테이너/서버 응용 프로그램이 아닌 경우 (간접)에 이러한 명령 처리기의 오버 헤드가 전송 하지 않기.CMainDoc 메시지 맵에 다음 항목을 추가 해야 합니다.

ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdatePasteMenu)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_LINK, OnUpdatePasteLinkMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, OnUpdateEditLinksMenu)
ON_COMMAND(ID_OLE_EDIT_LINKS, COleDocument::OnEditLinks)
ON_UPDATE_COMMAND_UI(ID_OLE_VERB_FIRST, OnUpdateObjectVerbMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_CONVERT, OnUpdateObjectVerbMenu)
ON_COMMAND(ID_OLE_EDIT_CONVERT, OnEditConvert)

구현이 이러한 명령의 모든 COleDocument, 문서에 대 한 기본 클래스입니다.

이 시점에서 OCLIENT 기능 OLE 컨테이너 응용 프로그램입니다.(OLE1 또는 OLE 2) 모든 종류의 항목을 삽입 하는 것이 가능 합니다.현재 위치에서 활성화를 사용 하는 데 필요한 코드를 구현 되지 않았습니다. 하므로 항목 ole1와 거의 같은 별도 창에서 편집할 수 있습니다.다음 섹션 ("비주얼 편집"이 라고도 함) 현재 위치에서 편집할 수 있도록 필요한 사항을 설명 합니다.

"비주얼 편집"를 추가합니다.

OLE의 가장 흥미로운 기능 중 하나는 현재 위치에서 활성화 (또는 "비주얼 편집")입니다.이 기능은 서버 응용 프로그램이 컨테이너의 사용자 인터페이스 부분을 통해 제공 되는 보다 원활한 편집 인터페이스 사용자에 게 수행할 수 있습니다.OCLIENT 현재 위치에서 활성화를 구현 하려면 몇 가지 특수 리소스 같은 일부 추가 코드 추가 할.응용 프로그램 마법사에서 이러한 리소스와 코드를 정상적으로 제공-사실 대부분 여기에 코드의 "컨테이너"를 지 원하는 새 응용 프로그램 마법사 응용 프로그램에서 직접 차용한 되었습니다.

첫째, 있을 때 현재 위치에서 활성화 된 항목을 사용 하는 메뉴 리소스를 추가 하는 것이 필요 합니다.IDR_OCLITYPE 리소스를 복사 하 고 파일 및 창 팝업 제외한 모든 제거 하 여 Visual C++에서이 추가 메뉴 리소스를 만들 수 있습니다.구분 막대를 두 그룹의 분리를 나타내려면 파일 및 창 팝업 사이의 삽입 (모양을 합니다: 파일 | | 창)입니다.이 구분 기호는 무엇을 의미 하 고 서버 및 컨테이너 메뉴를 병합 하는 방법을 대 한 자세한 내용은 "메뉴 및 리소스:: 메뉴 병합"을 참조 하십시오 OLE 2 클래스.

이러한 메뉴를 만든 후, 프레임 워크에서는를 알아낼 수 있도록 해야 합니다.이 호출 하 여 수행 됩니다 CDocTemplate::SetContainerInfo 문서 템플릿 목록에 해당 Initinstance에 추가 하기 전에 문서 템플릿.문서 서식 파일을 등록 하려면 새 코드는 다음과 같습니다.

CDocTemplate* pTemplate = new CMultiDocTemplate(
    IDR_OLECLITYPE,
    RUNTIME_CLASS(CMainDoc),
    RUNTIME_CLASS(CMDIChildWnd),    // standard MDI child frame
    RUNTIME_CLASS(CMainView));
pTemplate->SetContainerInfo(IDR_OLECLITYPE_INPLACE);
AddDocTemplate(pTemplate);

IDR_OLECLITYPE_INPLACE 리소스를 Visual C++에서 만든 특수 한 내부 리소스가입니다.

현재 위치에서 활성화를 사용 하려면 모두 변경 해야 할 몇 가지는 CView (CMainView) 파생 클래스 및 COleClientItem 파생 클래스 (CRectItem).응용 프로그램 마법사에서 제공 되는 모든 이러한 재정의 및 대부분의 구현은 기본 응용 프로그램 마법사에서는 애플리케이션에서 직접 표시 됩니다.

이 포트의 첫 번째 단계에서 전체적으로 재정의 하 여 내부 활성화 비활성화 되었습니다 COleClientItem::CanActivate.이 재정의 제거 하 여 현재 위치에서 활성화를 허용 되어야 합니다.또한 NULL 모든 호출에 전달 된 DoVerb (가지 두 가지) 보기 제공만 현재 위치에서 활성화에 필요한 때문입니다.현재 위치에서 활성화를 완벽 하 게 구현 하려면 올바른 보기에서 전달 하는 데 필요한 것은 DoVerb 를 호출 합니다.이러한 호출 중 하나입니다의 CMainView::OnInsertObject:

pItem->DoVerb(OLEIVERB_SHOW, this);

다른입니다 CMainView::OnLButtonDblClk:

m_pSelection->DoVerb(OLEIVERB_PRIMARY, this);

재정의 해야 하는 COleClientItem::OnGetItemPosition.이 서버 항목이 내부에서 활성화 되 면 해당 창을 기준으로 컨테이너 창의 넣을 위치를 알려줍니다.OCLIENT에 대 한 구현은 매우 간단합니다.

void CRectItem::OnGetItemPosition(CRect& rPosition)
{
    rPosition = m_rect;
}

어떤 "크기 조정 원위치." 라고 대부분의 서버를 구현할 수도 이 서버 창을 크기 및 사용자가 항목을 편집 하는 동안 이동할 수 있습니다.위치와 크기는 컨테이너 문서 내에서 이동 하거나 창 크기를 보통를 영향을 주므로 컨테이너는이 작업에 참여 해야 합니다.OCLIENT의 구현은 m_rect의 새 위치와 크기에 의해 유지 관리 되는 내부 사각형을 동기화 합니다.

BOOL CRectItem::OnChangeItemPosition(const CRect& rectPos)
{
    ASSERT_VALID(this);

    if (!COleClientItem::OnChangeItemPosition(rectPos))
        return FALSE;

    Invalidate();
    m_rect = rectPos;
    Invalidate();
    GetDocument()->SetModifiedFlag();

    return TRUE;
}

이 시점에서 항목이 활성화 되 면 항목 이동 및 크기 조정으로 처리 하 고 내부에서 활성화 될 수 있도록 충분 한 코드 있지만 코드가 편집 세션을 끝내려면 사용자가 있습니다.일부 서버가이 기능 자체가 esc 키를 처리 하 여 제공할 수 있지만, 컨테이너 항목을 비활성화 하려면 두 가지 방법으로 제공 하는 제안입니다: (1) 외부에서 항목을 클릭 하 고 (2) ESC 키를 누르면 됩니다.

이스케이프 키 액셀러레이터 키 명령에는 VK_ESCAPE 키 맵 한 Visual C++ 추가, ID_CANCEL_EDIT 리소스에 추가 됩니다.이 명령에 대 한 처리기는 다음과 같습니다.

// The following command handler provides the standard
// keyboard user interface to cancel an in-place
// editing session.void CMainView::OnCancelEdit()
{
    // Close any in-place active item on this view.
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL)
        pActiveItem->Close();
    ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}

사용자가 항목을 클릭할 경우가를 처리 하려면 다음 코드의 시작 부분으로 추가 CMainView::SetSelection:

if (pNewSel != m_pSelection || pNewSel == NULL)
{
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL && pActiveItem != pNewSel)
        pActiveItem->Close();
}
    

항목이 현재 위치에서 활성화 될 때 포커스가 있어야 합니다.이런 있는지 보기 포커스를 받았을 때 포커스는 항상 활성 항목으로 전송 되는 OnSetFocus 처리:

// Special handling of OnSetFocus and OnSize are required 
// when an object is being edited in-place.
void CMainView::OnSetFocus(CWnd* pOldWnd)
{
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL &&
    pActiveItem->GetItemState() == COleClientItem::activeUIState)
    {
        // need to set focus to this item if it is same view
        CWnd* pWnd = pActiveItem->GetInPlaceWindow();
        if (pWnd != NULL)
        {
            pWnd->SetFocus();  // don't call the base class
            return;
        }
    }

    CView::OnSetFocus(pOldWnd);
}

보기의 크기를 조정할 때 클리핑 사각형에 변경 된 현재 항목에 알리기 위해 필요 합니다.이 대 한 처리기를 제공 OnSize:

void CMainView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL)
        pActiveItem->SetItemRects();
}

사례 연구: HIERSVR에서 MFC 2.0

HIERSVR OLE MFC/o l e 1을 구현 하 고 MFC 2.0에도 포함 되었습니다.이 참고는이 응용 프로그램 처음 변환 되었습니다 OLE MFC/2 클래스를 사용 하는 단계를 간략하게 설명 합니다.초기 포트 더 MFC/OLE 2 클래스를 설명 하기 위해 완료 된 많은 기능이 추가 되었습니다.이러한 기능은 여기서 다루지 않습니다. 샘플 자체는 고급 기능에 대 한 자세한 내용은 참조 하십시오.

[!참고]

컴파일러 오류 및 단계별 프로세스는 Visual C++ 2.0으로 만들었습니다.Visual C++ 4.0에 특정 오류 메시지 및 위치가 변경 되었을 수 있지만 개념적 정보 유효 합니다.

이 시작

HIERSVR 샘플 ole MFC/포트에 적용 되는 방법을 일어나지 확실 한 컴파일러 오류를 수정 하 고 빌드를 시작 하는 것.MFC 2.0에서 HIERSVR 샘플을 가져와서이 버전의 MFC에서 컴파일해야 하는 경우 (OCLIENT 샘플을 두 개 이상 있지만) 해결에 많은 오류가 없는 것을 알 수 있습니다.오류에는 일반적으로 나타나는 순서 대로 다음과 같습니다.

컴파일 및 오류 수정

\hiersvr\hiersvr.cpp(83) : error C2039: 'RunEmbedded' : is not a member of 'COleTemplateServer'

이 첫 번째 오류를 훨씬 더 큰 문제를 가리키는 있는 InitInstance 서버에 대 한 함수.OLE 서버에 대해 필요한 초기화 OLE1 MFC/응용 프로그램을 실행할 수 있도록 해야 가장 큰 변화 중 하나가 것 같습니다.응용 프로그램 마법사에서 OLE 서버를 만듭니다를 살펴보고 적절 한 코드를 수정 하는 것이 가장을입니다.유의 사항은 다음과 같습니다.

호출 하 여 OLE 라이브러리를 초기화 하는 데 필요한 됩니다 AfxOleInit

Setserverinfo를 호출 하 여 서버 리소스 핸들을 설정할 수 없는 런타임 클래스 정보를 설정 하 여 문서 템플릿 개체에는 CDocTemplate 생성자입니다.

명령줄에 /Embedding 있으면 응용 프로그램의 주 창을 표시 하지 마십시오.

필요한 것은 GUID 문서에 대 한.이 문서의 형식 (128 비트)에 대 한 고유 식별자입니다.응용 프로그램 마법사가 생성 됩니다-따라서 여기 설명 된 방법을 사용 하는 경우 새로 생성 하는 응용 프로그램 마법사에서 서버 응용 프로그램에서 새 코드를 복사를 하면 단순히 "해당 응용 프로그램에서 GUID를 훔칠 수".그렇지 않으면 GUIDGEN을 사용할 수 있습니다.BIN 디렉터리에 EXE 유틸리티입니다.

"연결" 할 필요를 COleTemplateServer 개체를 호출 하 여 문서 서식 파일 COleTemplateServer::ConnectTemplate.

응용 프로그램이 독립 실행형으로 실행 될 때 시스템 레지스트리를 업데이트 합니다.사용자를 이동 하는이 경우에.EXE 응용 프로그램을 실행 하는 새 위치에서 Windows 시스템 등록 데이터베이스의 새 위치를 가리키도록 업데이트 됩니다.

어떤 응용 프로그램 마법사에 대 한 작성에 따라 이러한 변경 내용을 모두 적용 한 후 InitInstance, InitInstance (및 관련 GUID) HIERSVR 같이 읽어야 합니다:

// this is the GUID for HIERSVR documents
static const GUID BASED_CODE clsid =
    { 0xA0A16360L, 0xC19B, 0x101A, { 0x8C, 0xE5, 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x12 } };
    
/////////////////////////////////////////////////////////////////////////////
// COLEServerApp initialization

BOOL COLEServerApp::InitInstance()
{
    // OLE 2 initialization
    if (!AfxOleInit())
    {
        AfxMessageBox("Initialization of the OLE failed!");
        return FALSE;
    }

    // Standard initialization
    LoadStdProfileSettings(); // Load standard INI file options 

    // Register document templates
    CDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(IDR_HIERSVRTYPE,
        RUNTIME_CLASS(CServerDoc),   
        RUNTIME_CLASS(CMDIChildWnd),
        RUNTIME_CLASS(CServerView));
    pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB);
    AddDocTemplate(pDocTemplate);

    // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
        return FALSE;
    m_pMainWnd = pMainFrame;

    SetDialogBkColor();   // gray look

    // enable file manager drag/drop and DDE Execute open
    m_pMainWnd->DragAcceptFiles();
    EnableShellOpen();
    
    m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
    COleTemplateServer::RegisterAll();

    // try to launch as an OLE server
    if (RunEmbedded())
    {
        // "short-circuit" initialization -- run as server!
        return TRUE;
    }
    m_server.UpdateRegistry();
    RegisterShellFileTypes();

    // not run as OLE server, so show the main window
    if (m_lpCmdLine[0] == '\0')
    {
        // create a new (empty) document
        OnFileNew();
    }
    else
    {
        // open an existing document
        OpenDocumentFile(m_lpCmdLine);
    }

    pMainFrame->ShowWindow(m_nCmdShow);
    pMainFrame->UpdateWindow();
    
    return TRUE;
}

IDR_HIERSVRTYPE_SRVR_EMB는 새 리소스 ID를 위의 코드 참조를 확인할 수 있습니다.다른 컨테이너에 포함 되어 있는 문서를 편집할 때 사용 하는 메뉴 리소스입니다.MFC/ole1에 포함 된 항목을 편집 하려면 특정 메뉴 항목을 즉석에서 수정 되었습니다.파일을 기반으로 문서를 편집 하는 대신 포함 된 항목을 편집 하는 경우는 완전히 다른 메뉴 구조를 사용 하 여 훨씬 이러한 두 가지 별도 모드에 대 한 다양 한 사용자 인터페이스를 제공 하기 쉽습니다.나중에 살펴보겠지만는 완전히 별도 메뉴 리소스는 제자리에서 포함 된 개체를 편집할 때 사용 됩니다.

이 리소스를 만들려면 리소스 스크립트에 Visual C++를 로드 하 고 기존 IDR_HIERSVRTYPE 메뉴 리소스를 복사 합니다.새 리소스를 (응용 프로그램 마법사를 사용 하는 동일한 명명 규칙은) IDR_HIERSVRTYPE_SRVR_EMB를 이름을 바꿉니다.그런 다음 "파일 업데이트"; "파일 저장"을 변경 명령 ID를 제공 합니다. ID_FILE_UPDATE."파일 저장" "파일 복사본으로 저장 하려면"; 변경할 수도 명령 ID를 제공 합니다. ID_FILE_SAVE_COPY_AS.이러한 명령은 모두 구현 프레임 워크를 제공합니다.

\hiersvr\svritem.h(60) : error C2433: 'OLESTATUS' : 'virtual' not permitted on data declarations
\hiersvr\svritem.h(60) : error C2501: 'OLESTATUS' : missing decl-specifiers
\hiersvr\svritem.h(60) : error C2146: syntax error : missing ';' before identifier 'OnSetData'
\hiersvr\svritem.h(60) : error C2061: syntax error : identifier 'OLECLIPFORMAT'
\hiersvr\svritem.h(60) : error C2501: 'OnSetData' : missing decl-specifiers

재정의에서 발생 하는 오류는 여러 가지 OnSetData, 참조할 수 있기 때문에 OLESTATUS 형식.OLESTATUS OLE1 오류를 반환 했습니다.이 변경 되었습니다 HRESULT OLE 2에서 일반적으로 MFC 변환 되지만 HRESULT 에 있는 COleException 오류가 있는.이 특별 한 경우, 재정의 된 OnSetData 제거 하는 가장 쉬운 것 이므로 더 이상 필요 없습니다.

\hiersvr\svritem.cpp(30) : error C2660: 'COleServerItem::COleServerItem' : function does not take 1 parameters

COleServerItem 생성자는 추가 'BOOL' 매개 변수를 사용 합니다.이 플래그에서 메모리 관리 방식을 이루어집니다 결정은 COleServerItem 개체입니다.TRUE로 설정 프레임 워크를 이러한 개체의 메모리 관리를 처리-더 이상 필요 없는 경우이 삭제 합니다.HIERSVR를 사용 하 여 CServerItem (파생 COleServerItem)은이 플래그를 FALSE로 설정 합니다 있도록 원시 데이터, 일부 개체입니다.이렇게 HIERSVR을 각 서버 항목이 삭제 되는 시기를 결정할 수 있습니다.

\hiersvr\svritem.cpp(44) : error C2259: 'CServerItem' : illegal attempt to instantiate abstract class
\hiersvr\svritem.cpp(44) : error C2259: 'CServerItem' : illegal attempt to instantiate abstract class

이러한 오류를 알 수 있듯이 Cserveritem에서 오버라이드되지 않았기 일부 ' 순수 가상 ' 함수입니다.대부분의 경우이 사실은 여 Ondraw의 매개 변수 목록에서 변경 된 때문입니다.이 오류를 해결 하려면 변경 CServerItem::OnDraw 같이 (물론 선언 svritem.h에서):

BOOL CServerItem::OnDraw(CDC* pDC, CSize& rSize)
{
    // request from OLE to draw node
    pDC->SetMapMode(MM_TEXT); // always in pixels
    return DoDraw(pDC, CPoint(0,0), FALSE);
}

새 매개 변수를 'rSize'입니다.이렇게 하면 드로잉의 크기를 채우기 위해 편리한 경우 있습니다.이 크기에 있어야 HIMETRIC.프레임 워크를 호출 하므로 경우이이 값을 채우는 데 편리 하지 OnGetExtent 범위를 검색 합니다.해당 작업을 구현 해야 합니다 OnGetExtent:

BOOL CServerItem::OnGetExtent(DVASPECT dwDrawAspect, CSize& rSize)
{
    if (dwDrawAspect != DVASPECT_CONTENT)
        return COleServerItem::OnGetExtent(dwDrawAspect, rSize);
        
    rSize = CalcNodeSize();
    return TRUE;
}

\hiersvr\svritem.cpp(104) : error C2065: 'm_rectBounds' : undeclared identifier
\hiersvr\svritem.cpp(104) : error C2228: left of '.SetRect' must have class/struct/union type
\hiersvr\svritem.cpp(106) : error C2664: 'void __pascal __far DPtoLP(struct ::tagPOINT __far *,int )__far const ' : cannot convert parameter 1 from 'int __far *' to 'struct ::tagPOINT __far *'

항목 크기 변환 CServerItem::CalcNodeSize 함수에서 HIMETRIC 저장 m_rectBounds.문서화 되지 않은 'm_rectBounds' 소속 COleServerItem 존재 하지 않습니다 (이 부분적으로 바뀌었습니다 m_sizeExtent, 하지만 보다는 약간 다르게 사용 했습니다.이 @ OLE 2 m_rectBounds ole1에서 되지 않았습니다).설정 대신에 HIMETRIC 크기 멤버 변수에 반환 됩니다.반환 값이 사용 됩니다 OnGetExtent, 이전에 구현 된.

CSize CServerItem::CalcNodeSize()
{
    CClientDC dcScreen(NULL);

    m_sizeNode = dcScreen.GetTextExtent(m_strDescription,
      m_strDescription.GetLength());
    m_sizeNode += CSize(CX_INSET * 2, CY_INSET * 2);

    // set suggested HIMETRIC size
    CSize size(m_sizeNode.cx, m_sizeNode.cy);
    dcScreen.SetMapMode(MM_HIMETRIC);
    dcScreen.DPtoLP(&size);
    return size;
}

CServerItem 또한 재정의 COleServerItem::OnGetTextData.이 함수는 MFC/OLE에서 사용 되지 않습니다 및 다른 메커니즘으로 대체 됩니다.MFC OLE 샘플의 MFC 3.0 버전 HIERSVR 를 재정의 하 여이 기능을 구현 합니다. COleServerItem::OnRenderFileData.OnGetTextData 재정의 제거할 수 있도록이 기능을이 기본 포트에 대 한 중요 한 아닙니다.

해결 하지 svritem.cpp의 많은 자세한 오류입니다."실제" 오류 되지 않습니다-단지 오류 이전 오류로 인해.

\hiersvr\svrview.cpp(325) : error C2660: 'CopyToClipboard' : function does not take 2 parameters

COleServerItem::CopyToClipboard더 이상 'bIncludeNative' 플래그를 지원합니다.네이티브 데이터 (데이터 서버 항목의 Serialize 함수에 의해 기록 된) 첫 번째 매개 변수를 제거 하므로 항상 복사 됩니다.또한, CopyToClipboard FALSE를 반환 하는 대신 오류가 발생 하면 예외가 throw 됩니다.코드 Cserverview::oneditcopy를 다음과 같이 변경 합니다.

void CServerView::OnEditCopy()
{
    if (m_pSelectedNode == NULL)
        AfxThrowNotSupportedException();
        
    TRY
    {
        m_pSelectedNode->CopyToClipboard(TRUE);
    }
    CATCH_ALL(e)
    {
        AfxMessageBox("Copy to clipboard failed");
    }
    END_CATCH_ALL   
}

OCLIENT의 동일한 버전에 비해 컴파일에서 HIERSVR MFC 2.0 버전의 결과 더 이상 오류가 발생 하지만 있었고 실제로 적게 변경 됩니다.

이 시점에서 HIERSVR 컴파일 및 링크 및 다음 구현 될 내부 편집 기능을 하지 않고 OLE 서버로 작동 합니다.

"비주얼 편집"를 추가합니다.

"비주얼 편집" (또는 현재 위치에서 활성화)이 서버 응용 프로그램에 추가 하는 몇 가지만의 주의 해야

  • 항목의 현재 위치에서 활성화 될 때 사용 될 특수 메뉴 리소스가 필요한.

  • 이 응용 프로그램 도구 모음이 있으므로 일치 (위에서 언급 한 메뉴 리소스와 일치) 메뉴 명령을 서버에서 사용할 수 있는 표준 도구 모음의 하위 집합만 포함 된 도구 모음을 해야 합니다.

  • 파생 된 새 클래스를 해야 COleIPFrameWnd 전체 사용자 인터페이스를 제공 하는 (처럼 파생 CMainFrame, CMDIFrameWnd, MDI 사용자 인터페이스 제공).

  • 이러한 특수 리소스 및 클래스에 대 한 프레임 워크를 설명 해야 합니다.

메뉴 리소스를 쉽게 만들 수 있습니다.Visual C++ 실행, 메뉴 리소스 IDR_HIERSVRTYPE IDR_HIERSVRTYPE_SRVR_IP 라는 메뉴 리소스를 복사 합니다.메뉴를 수정 하도록 편집 및 도움말 메뉴 팝업만 남아 있습니다.두 개의 구분 기호 메뉴 편집 및 도움말 메뉴 사이 추가 (모양을 합니다: 편집 | | 도움말)입니다.이 구분 기호는 무엇을 의미 하 고 서버 및 컨테이너 메뉴를 병합 하는 방법을 대 한 자세한 내용은 "메뉴 및 리소스:: 메뉴 병합"을 참조 하십시오 OLE 2 클래스.

쉽게 체크 "서버" 옵션과 새로 생성 하는 응용 프로그램 마법사 응용 프로그램을 복사 하 여 일부 도구 모음 비트맵을 만들 수 있습니다.Visual C++에 다음이 비트맵을 가져올 수 있습니다.ID IDR_HIERSVRTYPE_SRVR_IP의 비트맵을 제공 해야 합니다.

파생 클래스는 COleIPFrameWnd 를 생성 하는 응용 프로그램 마법사 응용 프로그램 서버 지원에 복사할 수 있습니다.IPFRAME 파일을 모두 복사 합니다.CPP 및 IPFRAME입니다.H 및 프로젝트에 추가 합니다.있는지 확인은 LoadBitmap IDR_HIERSVRTYPE_SRVR_IP, 이전 단계에서 만든 비트맵 전화를 말합니다.

이제 만든 모든 새 리소스 및 클래스는 프레임 워크에 대 한 이러한 알고 (지금이 응용 프로그램에서 내부 편집을 지원 하는지 알 수 있도록) 필요한 코드를 추가 합니다.몇 가지 더 많은 매개 변수를 추가 하 여 이렇게는 SetServerInfo 호출 InitInstance 함수:

pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB,
    IDR_HIERSVRTYPE_SRVR_IP, RUNTIME_CLASS(CInPlaceFrame));

지금 현재 위치에서 실행할 준비가 되어 또한 현재 위치에서 활성화를 지 원하는 모든 컨테이너에서.하지만, 여전히 코드에 묻혀 사소한 버그 하나입니다.HIERSVR는 상황에 맞는 메뉴, 마우스 오른쪽 단추를 누를 때 표시를 지원 합니다.이 메뉴는 HIERSVR 완전히 열려 있지만 포함 내부 편집 하면 작동 하지 않습니다 때 작동 합니다.이유는이 한 줄의 코드에서 CServerView::OnRButtonDown 고정할 수 있습니다:

pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
    point.x, point.y, AfxGetApp()->m_pMainWnd);

참조를 확인할 수 AfxGetApp()-> m_pMainWnd.서버가 원위치 활성화 되 면가 주 창 하 고 m_pMainWnd 설정 했지만 일반적으로 표시 되지 않습니다.게다가이 창을 참조 하는 창 응용 프로그램의 서버를 완벽 하 게 되 면 나타나는 MDI 프레임 창 열기 또는 독립 실행형 실행 합니다.활성 프레임 창을 참조 하지 않습니다-때 현재 위치에서 활성화는 프레임 창에서 파생 COleIPFrameWnd.올바른 활성 창을도 편집, 제자리에서이 버전의 MFC의 새로운 기능을 추가 하는 경우 AfxGetMainWnd.일반적으로이 함수를 대신 사용 해야 AfxGetApp()-> m_pMainWnd.이 코드는 다음과 같이 변경 해야 합니다.

pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
    point.x, point.y, AfxGetMainWnd());

이제 OLE 서버를 최소한으로 작동 현재 위치에서 활성화에 있습니다.있지만 아직도 많은 기능 사용할 수 있는 MFC/ole1에서 사용할 수 없는 OLE MFC/2.HIERSVR 샘플 더 많은 아이디어를 구현 하려는 기능을 참조 하십시오.HIERSVR를 구현 하는 기능 중 일부는 다음과 같습니다.

  • True WYSISYG 동작의 컨테이너를 기준으로 확대/축소 합니다.

  • 드래그 / 드롭 및 사용자 지정 된 클립보드 형식입니다.

  • 스크롤이 컨테이너 창의 선택 영역으로 변경 됩니다.

HIERSVR 샘플에서는 MFC 3.0도 해당 서버 항목에 대 한 약간 다른 디자인을 사용합니다.이 메모리를 절약 하는 데 도움이 됩니다 및 링크 보다 융통성이 있습니다.HIERSVR의 2.0 버전과 트리의 각 노드에 되는COleServerItem.COleServerItem각이 노드와 여기에 반드시 필요한 것 보다 조금 더 많은 오버 헤드를 전달 하지만 COleServerItem 각에 대 한 활성 링크입니다.하지만 대부분의 활성 링크를 거의 언제 든 지 있습니다.HIERSVR이 버전의 MFC의 노드 구분이 보다 효율적으로 COleServerItem.가 두는 Cservernode와 CServerItem 클래스입니다.CServerItem (파생 COleServerItem)은 필요에 따라 만들어집니다.Cservernode와 연관 된 CServerItem 개체 컨테이너 (또는 컨테이너)에 해당 특정 노드에 특정 링크를 사용을 중지 한 후에 삭제 됩니다.이 디자인은 더 효율적이 고 유연한입니다.유연성의 여러 선택 링크를 다룰 때 활용할 수 있습니다.HIERSVR의 두 가지 버전 중 어느 것도 다중 선택을 지원 하지만 추가 (및 링크와 같은 선택 항목을 지원 하도록) 훨씬 더 쉽 겠지요 HIERSVR에서 MFC 3.0 버전 이후는 COleServerItem 에서 원시 데이터를 구분 합니다.

참고 항목

기타 리소스

번호 기술 정보

범주별 기술 노트