リッチ エディット コントロールで OLE を使用する方法
このセクションでは、リッチ エディット コントロールでオブジェクトのリンクと埋め込み (OLE) を使用する方法について説明します。
知っておくべきこと
テクノロジ
前提条件
- C/C++
- Windows ユーザー インターフェイス プログラミング
手順
リッチ エディット インターフェイスの使用
リッチ エディット コントロールは、コンポーネント オブジェクト モデル (COM) インターフェイスを通じて機能の一部を公開します。 コントロールからインターフェイスを取得することにより、コントロール内の他のオブジェクトを操作可能になります。 このインターフェイスは、EM_GETOLEINTERFACE メッセージを送信することにより取得できます。 IRichEditOle インターフェイスから、テキスト オブジェクト モデルで使用されているインターフェイスを取得できます。
もう 1 つのインターフェイス IRichEditOleCallback は、オブジェクトと対話するときのコントロールの動作を定義するため、アプリケーションによって実装されます。
リッチ エディット コントロールへのオブジェクトの挿入
次のコード例では、ファイル オブジェクトをリッチ エディット コントロールに挿入します。 プログラムがユーザーのコンピューター上のファイルの種類に関連付けられている場合 (たとえば、.xls ファイルの場合は Microsoft Excel)、ファイルの内容がコントロールに表示されます。それ以外の場合、アイコンが表示されます。
IRichEditOle インターフェイスを取得します。
BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName) { HRESULT hr; LPRICHEDITOLE pRichEditOle; SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle); ...
構造化ストレージを作成します。
LPLOCKBYTES pLockBytes = NULL; hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes); LPSTORAGE pStorage; hr = StgCreateDocfileOnILockBytes(pLockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); ...
データ形式を設定します。
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); ...
オブジェクトを作成し、その IUnknown インターフェイスを取得します。
LPUNKNOWN pUnk; CLSID clsid = CLSID_NULL; hr = OleCreateFromFile(clsid, pszFileName, IID_IUnknown, OLERENDER_DRAW, &formatEtc, pClientSite, pStorage, (void**)&pUnk); pClientSite->Release(); ...
オブジェクトへの IOleObject インターフェイスを取得します。
LPOLEOBJECT pObject; hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject); pUnk->Release(); ...
参照が正しくカウントされるようにするため、参照が含まれていることをオブジェクトに通知します。
OleSetContainedObject(pObject, TRUE); ...
オブジェクト情報を設定します。
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; ...
キャレットをテキストの末尾に移動し、キャリッジ リターンを追加します。
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(); return TRUE; }
IRichEditOleCallback の使用
アプリケーションは、OLE 関連のクエリ、またはリッチ エディット コントロールによって実行されるアクションに応答する IRichEditOleCallback インターフェイスを実装します。 インターフェイスの実装をコントロールに関連付けるには、EM_SETOLECALLBACK メッセージを送信します。 コントロールは、必要に応じてインターフェイスの実装でメソッドを呼び出します。
たとえば、ユーザーがオブジェクトをコントロールにドラッグまたは貼り付けようとすると、QueryAcceptData が呼び出されます。 アプリケーションがデータを受け入れる場合、メソッドの実装によって S_OK が返されます。それ以外の場合はエラー コードが返されます。 メソッドは、その種類のファイルをコントロールに配置できないことをユーザーに警告するなど、他のアクションを実行することもあります。
完全な InsertObject サンプル関数
次のコード例は、エラー処理を含む、1 つの完全な関数に結合された前のコード スニペットを示しています。
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;
}
関連トピック