다음을 통해 공유


서식 있는 편집 컨트롤에서 OLE를 사용하는 방법

이 섹션에는 서식 있는 편집 컨트롤에 OLE(개체 연결 및 포함)를 사용하는 방법에 대한 정보가 포함되어 있습니다.

알아야 할 사항

기술

  • 윈도우 제어

필수 구성 요소

  • C/C++
  • Windows 사용자 인터페이스 프로그래밍

지시

서식 있는 편집 인터페이스 사용

다양한 편집 컨트롤은 COM(구성 요소 개체 모델) 인터페이스를 통해 일부 기능을 노출합니다. 컨트롤에서 인터페이스를 가져오면 컨트롤 내의 다른 개체로 작업할 수 있습니다. EM_GETOLEINTERFACE 메시지를 보내 이 인터페이스를 가져올 수 있습니다. IRichEditOle 인터페이스에서 텍스트 객체 모델에 사용되는 인터페이스를 얻을 수 있습니다.

IRichEditOleCallback또 다른 인터페이스는 개체와 상호 작용할 때 컨트롤의 동작을 정의하기 위해 애플리케이션에 의해 구현됩니다.

개체를 서식 있는 편집 컨트롤에 삽입하기

다음 코드 예제에서는 서식 있는 편집 컨트롤에 파일 개체를 삽입 합니다. 프로그램이 사용자 컴퓨터의 파일 형식과 연결된 경우(예: .xls 파일의 경우 Microsoft Excel), 컨트롤에 파일 내용이 표시됩니다. 그렇지 않으면 아이콘이 나타납니다.

  1. IRichEditOle 인터페이스를 가져옵니다.

    BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
    {
        HRESULT hr;
    
        LPRICHEDITOLE pRichEditOle;
        SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
    
        ...
    
  2. 구조화된 스토리지를 만듭니다.

        LPLOCKBYTES pLockBytes = NULL;
        hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
    
        LPSTORAGE pStorage;
        hr = StgCreateDocfileOnILockBytes(pLockBytes, 
                                          STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
                                          0, &pStorage);
        ...
    
  3. 데이터 형식을 설정합니다.

        FORMATETC formatEtc;
    
        formatEtc.cfFormat = 0;
        formatEtc.ptd      = NULL;
        formatEtc.dwAspect = DVASPECT_CONTENT;
        formatEtc.lindex   = -1;
        formatEtc.tymed    = TYMED_NULL;
    
        ...
    
  4. 표시 사이트에 대한 포인터를 가져옵니다.

        LPOLECLIENTSITE pClientSite;
        hr = pRichEditOle->GetClientSite(&pClientSite);
    
        ...
    
  5. 개체를 만들고 해당 IUnknown 인터페이스를 검색합니다.

        LPUNKNOWN pUnk;
        CLSID clsid = CLSID_NULL;
    
        hr = OleCreateFromFile(clsid, 
                               pszFileName, 
                               IID_IUnknown, 
                               OLERENDER_DRAW, 
                               &formatEtc, 
                               pClientSite, 
                               pStorage, 
                               (void**)&pUnk);
    
        pClientSite->Release();
    
        ...
    
  6. 개체에 대한 IOleObject 인터페이스를 가져옵니다.

        LPOLEOBJECT pObject;
    
        hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
    
        pUnk->Release();
    
        ...
    
  7. 참조가 올바르게 계산되도록 하려면 개체에 포함되었음을 알립니다.

        OleSetContainedObject(pObject, TRUE);
    
        ...
    
  8. 개체 정보를 설정합니다.

        REOBJECT reobject = { sizeof(REOBJECT)};
    
        hr = pObject->GetUserClassID(&clsid);
    
        reobject.clsid    = clsid;
        reobject.cp       = REO_CP_SELECTION;
        reobject.dvaspect = DVASPECT_CONTENT;
        reobject.dwFlags  = REO_RESIZABLE | REO_BELOWBASELINE;
        reobject.dwUser   = 0;
        reobject.poleobj  = pObject;
        reobject.polesite = pClientSite;
        reobject.pstg     = pStorage;
    
        SIZEL sizel       = { 0 };
        reobject.sizel    = sizel;
    
        ...
    
  9. 텍스트의 끝으로 캐리트를 이동하고 캐리지 리턴을 추가합니다.

        SendMessage(hRichEdit, EM_SETSEL, 0, -1);
    
        DWORD dwStart, dwEnd;
    
        SendMessage(hRichEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
        SendMessage(hRichEdit, EM_SETSEL, dwEnd+1, dwEnd+1);
        SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (WPARAM)L"\n"); 
    
        ...
    
  10. 개체를 삽입합니다.

        hr = pRichEditOle->InsertObject(&reobject);
    
        ...
    
  11. 정리해요.

        pObject->Release();
    
        pRichEditOle->Release();
    
        return TRUE;
    
    }
    

IRichEditOleCallback의 사용

애플리케이션은 IRichEditOleCallback 인터페이스를 구현하여 풍부한 편집 컨트롤에서 수행하는 OLE 관련 쿼리 또는 작업에 응답합니다. EM_SETOLECALLBACK 메시지를 전송하여 인터페이스 구현을 컨트롤과 연결합니다. 그런 다음 컨트롤은 인터페이스 구현에 대한 메서드를 적절하게 호출합니다.

예를 들어 사용자가 개체를 컨트롤에 끌어서 붙여넣으려고 할 때 queryAcceptData호출됩니다. 애플리케이션이 데이터를 수락할 수 있는 경우 메서드 구현은 S_OK 반환합니다. 그렇지 않으면 오류 코드를 반환합니다. 메서드는 해당 형식의 파일을 컨트롤에 배치할 수 없다는 경고와 같은 다른 작업을 수행할 수도 있습니다.

InsertObject 예제 함수 완료

다음 코드 예제에서는 오류 처리를 포함하는 하나의 전체 함수로 결합된 이전 코드 조각을 보여 줍니다.

BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
{
    HRESULT hr;

    LPRICHEDITOLE pRichEditOle;
    SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);

    if (pRichEditOle == NULL)
    {
        return FALSE;
    }

    LPLOCKBYTES pLockBytes = NULL;
    hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);

    if (FAILED(hr))
    {
        return FALSE;
    }

    LPSTORAGE pStorage;
    hr = StgCreateDocfileOnILockBytes(pLockBytes, 
           STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
           0, &pStorage);

    if (FAILED(hr))
    {
        return FALSE;
    }

    FORMATETC formatEtc;
    formatEtc.cfFormat = 0;
    formatEtc.ptd = NULL;
    formatEtc.dwAspect = DVASPECT_CONTENT;
    formatEtc.lindex = -1;
    formatEtc.tymed = TYMED_NULL;

    LPOLECLIENTSITE pClientSite;
    hr = pRichEditOle->GetClientSite(&pClientSite);

    if (FAILED(hr))
    {
        return FALSE;
    }

    LPUNKNOWN pUnk;
    CLSID clsid = CLSID_NULL;

    hr = OleCreateFromFile(clsid, pszFileName, IID_IUnknown, OLERENDER_DRAW, 
           &formatEtc, pClientSite, pStorage, (void**)&pUnk);

    pClientSite->Release();

    if (FAILED(hr))
    {
        return FALSE;
    }

    LPOLEOBJECT pObject;
    hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
    pUnk->Release();

    if (FAILED(hr))
    {
        return FALSE;
    }

    OleSetContainedObject(pObject, TRUE);
    REOBJECT reobject = { sizeof(REOBJECT)};
    hr = pObject->GetUserClassID(&clsid);

    if (FAILED(hr))
    {
        pObject->Release();
        return FALSE;
    }

    reobject.clsid = clsid;
    reobject.cp = REO_CP_SELECTION;
    reobject.dvaspect = DVASPECT_CONTENT;
    reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
    reobject.dwUser = 0;
    reobject.poleobj = pObject;
    reobject.polesite = pClientSite;
    reobject.pstg = pStorage;
    SIZEL sizel = { 0 };
    reobject.sizel = sizel;

    SendMessage(hRichEdit, EM_SETSEL, 0, -1);
    DWORD dwStart, dwEnd;
    SendMessage(hRichEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
    SendMessage(hRichEdit, EM_SETSEL, dwEnd+1, dwEnd+1);
    SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (WPARAM)L"\n"); 

    hr = pRichEditOle->InsertObject(&reobject);
    pObject->Release();
    pRichEditOle->Release();

    if (FAILED(hr))
    {
        return FALSE;
    }
    
    return TRUE;
}

서식 있는 편집 컨트롤 사용하기

Windows 공용 컨트롤 데모(CppWindowsCommonControls)