EternalWindows
OLE埋め込み / コンテナサンプル

OLE埋め込みのコンテナ側のサンプルを示します。 埋め込むオブジェクトはWordやExcelのような既存のオブジェクトでも構いませんし、 次節以降で作成する独自のオブジェクトでも構いません。 まず、sample.hを示します。

class CSite;

class CContainer : public IUnknown
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();

	CContainer();
	~CContainer();
	int Run(HINSTANCE hinst, int nCmdShow);
	LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	BOOL CreateRootStorage(LPWSTR lpszFileName);
	BOOL InsertObject();
	BOOL SaveObject();
	BOOL LoadObject();
	void Destroy();
	void ChangeSelectObject(CSite *pNew);
	BOOL GetSiteFormPos(LPARAM lParam, CSite **pp);
	void GetWindow(HWND *phwnd);
	void InitializeMenuItem(HMENU hmenu, LPTSTR lpszItemName, int nId, HMENU hmenuSub);
	BOOL FileDialog(BOOL bOpen, LPWSTR lpszFilePath, DWORD dwLength);

private:
	LONG     m_cRef;
	HWND     m_hwnd;
	HMENU    m_hmenu;
	int      m_nObjectCount;
	IStorage *m_pRootStorage;
	IStream  *m_pStream;
	CSite    *m_pSite;
	CSite    *m_pSiteMoving;
	WCHAR    m_szFilePath[MAX_PATH];
};

extern CContainer *g_pContainer;

次に、site.hを示します。

class CSite : public IOleClientSite, public IAdviseSink
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
	
	STDMETHODIMP SaveObject();
	STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
	STDMETHODIMP GetContainer(IOleContainer **ppContainer);
	STDMETHODIMP ShowObject();
	STDMETHODIMP OnShowWindow(BOOL fShow);
	STDMETHODIMP RequestNewObjectLayout();

	STDMETHODIMP_(void) OnDataChange(FORMATETC *pFormatetc, STGMEDIUM *pStgmed);
	STDMETHODIMP_(void) OnViewChange(DWORD dwAspect, LONG lindex);
	STDMETHODIMP_(void) OnRename(IMoniker *pmk);
	STDMETHODIMP_(void) OnSave();
	STDMETHODIMP_(void) OnClose();

	CSite();
	~CSite();
	void Initialize(IOleObject *pOlebject, IStorage *pStorage, LPWSTR lpszObjectName, LPRECT lprc);
	void Save();
	void RunObject(LONG lVerb);
	void Close();
	void Draw(HDC hdc);
	void AddVerbMenu(HMENU hmenu, UINT uIdVerbMin, UINT uIdVerbMax);
	void ChangeSelect(BOOL bSelect);
	void GetRect(LPRECT lprc);
	void UpdateRect();
	void MoveRect(LPARAM lParam);
	void SetClickPos(LPARAM lParam);
	void HIMETRICtoDP(LPSIZEL lpSizel);
	
	CSite *m_pNext;

private:
	LONG       m_cRef;
	RECT       m_rc;
	POINT      m_ptClick;
	DWORD      m_dwConnection;
	BOOL       m_bSelect;
	BOOL       m_bShowWindow;
	IOleObject *m_pOleObject;
	IStorage   *m_pStorage;
};

次に、sample.cppを示します。

#include <windows.h>
#include <oledlg.h>
#include "sample.h"
#include "site.h"

#define ID_FILE 100
#define ID_OPEN 200
#define ID_SAVE 300
#define ID_INSERT 400
#define ID_VERBMIN 0
#define ID_VERBMAX 5

#pragma comment (lib, "oledlg.lib")

const CLSID CLSID_SampleFile = {0x8f05f2d2, 0x9ec2, 0x43ac, {0xb6, 0x69, 0x0, 0x7e, 0x3f, 0x80, 0x7, 0xfc}};

CContainer *g_pContainer = NULL;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	int nResult = 0;

	OleInitialize(NULL);
	
	g_pContainer = new CContainer;
	if (g_pContainer != NULL) {
		nResult = g_pContainer->Run(hinst, nCmdShow);
		g_pContainer->Release();
	}

	OleUninitialize();

	return nResult;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return g_pContainer->WindowProc(hwnd, uMsg, wParam, lParam);
}


// CContainer


CContainer::CContainer()
{
	m_cRef = 1;
	m_hwnd = NULL;
	m_hmenu = NULL;
	m_nObjectCount = 0;
	m_pRootStorage = NULL;
	m_pStream = NULL;
	m_pSite = NULL;
	m_pSiteMoving = NULL;
	m_szFilePath[0] = '\0';
}

CContainer::~CContainer()
{
}

STDMETHODIMP CContainer::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;	

	if (IsEqualIID(riid, IID_IUnknown))
		*ppvObject = static_cast<IUnknown *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CContainer::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CContainer::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {
		delete this;
		return 0;
	}

	return m_cRef;
}

int CContainer::Run(HINSTANCE hinst, int nCmdShow)
{
	TCHAR      szAppName[] = TEXT("sample");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = CS_DBLCLKS;
	wc.lpfnWndProc   = ::WindowProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hinst;
	wc.hIcon         = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	wc.hCursor       = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = szAppName;
	wc.hIconSm       = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	
	if (RegisterClassEx(&wc) == 0)
		return 0;

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

LRESULT CContainer::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {

	case WM_CREATE: {
		HMENU hmenu;
		HMENU hmenuPopupFile;
		HMENU hmenuPopupHelp;

		hmenu  = CreateMenu();
		hmenuPopupFile = CreatePopupMenu();
		hmenuPopupHelp = CreatePopupMenu();

		InitializeMenuItem(hmenuPopupFile, TEXT("開く(&O)"), ID_OPEN, NULL);
		InitializeMenuItem(hmenuPopupFile, TEXT("保存(&S)"), ID_SAVE, NULL);

		InitializeMenuItem(hmenu, TEXT("ファイル(&F)"), ID_FILE, hmenuPopupFile);
		InitializeMenuItem(hmenu, TEXT("オブジェクトの挿入(&I)"), ID_INSERT, NULL);
		
		m_hwnd = hwnd;
		m_hmenu = hmenu;
		SetMenu(m_hwnd, m_hmenu);

		if (!CreateRootStorage(NULL))
			return -1;

		return 0;
	}
	
	case WM_COMMAND: {
		int nId = LOWORD(wParam);

		if (nId == ID_OPEN)
			LoadObject();
		else if (nId == ID_SAVE)
			SaveObject();
		else if (nId == ID_INSERT)
			InsertObject();
		else if (nId >= ID_VERBMIN || nId <= ID_VERBMAX)
			m_pSiteMoving->RunObject(nId);
		else
			;
		InvalidateRect(m_hwnd, NULL, TRUE);
		
		return 0;
	}

	case WM_LBUTTONDOWN: {
		CSite *p = NULL;
		BOOL  bChangeSelect = TRUE;

		if (GetSiteFormPos(lParam, &p)) {
			if (p == m_pSiteMoving)
				bChangeSelect = FALSE;
			SetCapture(hwnd);
			m_pSiteMoving = p;
			m_pSiteMoving->SetClickPos(lParam);
		}

		if (bChangeSelect) {
			ChangeSelectObject(p);
			InvalidateRect(m_hwnd, NULL, TRUE);
		}

		return 0;
	}

	case WM_LBUTTONUP:
		ReleaseCapture();
		m_pSiteMoving = NULL;
		return 0;
	
	case WM_LBUTTONDBLCLK: {
		CSite *p;

		if (GetSiteFormPos(lParam, &p))
			p->RunObject(OLEIVERB_PRIMARY);

		return 0;
	}
	
	case WM_RBUTTONDOWN: {
		CSite *p = NULL;
		POINT pt;
		HMENU hmenu;

		if (GetSiteFormPos(lParam, &p)) {
			if (p != m_pSiteMoving) {
				m_pSiteMoving = p;
				ChangeSelectObject(p);
				InvalidateRect(m_hwnd, NULL, TRUE);
			}

			hmenu = CreatePopupMenu();
			p->AddVerbMenu(hmenu, ID_VERBMIN, ID_VERBMAX);
			GetCursorPos(&pt);
			TrackPopupMenu(hmenu, 0, pt.x, pt.y, 0, hwnd, NULL);
			DestroyMenu(hmenu);
		}
		else {
			ChangeSelectObject(p);
			InvalidateRect(m_hwnd, NULL, TRUE);
		}
		
		return 0;
	}

	case WM_MOUSEMOVE:
		if (GetCapture() != NULL) {
			m_pSiteMoving->MoveRect(lParam);
			InvalidateRect(m_hwnd, NULL, TRUE);
		}
		return 0;
	
	case WM_PAINT: {
		HDC         hdc;
		PAINTSTRUCT ps;
		CSite       *p = m_pSite;

		hdc = BeginPaint(hwnd, &ps);

		while (p != NULL) {
			p->Draw(hdc);
			p = p->m_pNext;
		}

		EndPaint(hwnd, &ps);

		return 0;
	}

	case WM_DESTROY:
		Destroy();
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

BOOL CContainer::CreateRootStorage(LPWSTR lpszFileName)
{
	CLSID clsid;
	WCHAR szStreamName[] = L"stream";

	if (lpszFileName == NULL) {
		StgCreateDocfile(NULL, STGM_READWRITE | STGM_TRANSACTED, 0, &m_pRootStorage);
		if (m_pRootStorage == NULL)
			return FALSE;

		WriteClassStg(m_pRootStorage, CLSID_SampleFile);
		
		m_pRootStorage->CreateStream(szStreamName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStream);
		if (m_pStream == NULL)
			return FALSE;
	}
	else {
		IStorage *pStorage;
		IStream  *pStream;

		StgOpenStorage(lpszFileName, NULL, STGM_READWRITE | STGM_TRANSACTED, NULL, 0, &pStorage);
		if (pStorage == NULL)
			return FALSE;

		ReadClassStg(pStorage, &clsid);
		if (!IsEqualCLSID(clsid, CLSID_SampleFile)) {
			pStorage->Release();
			return FALSE;
		}

		pStorage->OpenStream(szStreamName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStream);
		if (pStream == NULL) {
			pStorage->Release();
			return FALSE;
		}

		Destroy();
	
		m_pRootStorage = pStorage;
		m_pStream = pStream;
	}

	return TRUE;
}

BOOL CContainer::InsertObject()
{
	UINT              uResult;
	WCHAR             szFilePath[MAX_PATH];
	WCHAR             szObjectName[256];
	IStorage          *pStorage;
	IOleObject        *pOleObject;
	CSite             *p;
	OLEUIINSERTOBJECT insertObject;

	wsprintfW(szObjectName, L"オブジェクト %d", m_nObjectCount + 1);
	m_pRootStorage->CreateStorage(szObjectName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStorage);
	if (pStorage == NULL)
		return FALSE;

	szFilePath[0] = '\0';

	ZeroMemory(&insertObject, sizeof(OLEUIINSERTOBJECT));
	insertObject.cbStruct   = sizeof(OLEUIINSERTOBJECT);
	insertObject.dwFlags    = IOF_DISABLEDISPLAYASICON | IOF_SELECTCREATENEW | IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_DISABLELINK;
	insertObject.hWndOwner  = m_hwnd;
	insertObject.lpszFile   = szFilePath;
	insertObject.cchFile    = MAX_PATH;
	insertObject.iid        = IID_IOleObject;
	insertObject.oleRender  = OLERENDER_DRAW;
	insertObject.lpIStorage = pStorage;
	insertObject.ppvObj     =  (void **)&pOleObject;
	
	uResult = OleUIInsertObject(&insertObject);
	if (uResult != OLEUI_OK) {
		m_pRootStorage->DestroyElement(szObjectName);
		return FALSE;
	}

	m_nObjectCount++;

	if (m_pSite == NULL) {
		m_pSite = new CSite;
		p = m_pSite;
	}
	else {
		p = m_pSite;
		while (p->m_pNext != NULL)
			p = p->m_pNext;

		p->m_pNext = new CSite;
		p = p->m_pNext;
	}
	
	p->Initialize(pOleObject, pStorage, szObjectName, NULL);

	return TRUE;
}

BOOL CContainer::SaveObject()
{
	int           i;
	ULONG         uResult;
	RECT          rc;
	CSite         *p = m_pSite;
	WCHAR         szFilePath[MAX_PATH];
	LARGE_INTEGER li = {0};

	if (m_nObjectCount == 0) {
		MessageBox(NULL, TEXT("オブジェクトが作成されていません。"), NULL, MB_ICONWARNING);
		return FALSE;
	}

	if (!FileDialog(FALSE, szFilePath, MAX_PATH))
		return FALSE;

	m_pStream->Seek(li, STREAM_SEEK_SET, NULL);
	m_pStream->Write(&m_nObjectCount, sizeof(int), &uResult);

	for (i = 0; i < m_nObjectCount; i++) {
		p->GetRect(&rc);
		m_pStream->Write(&rc, sizeof(RECT), &uResult);

		p->Save();
		p = p->m_pNext;
	}

	if (lstrcmpW(szFilePath, m_szFilePath) != 0) {
		HRESULT      hr;
		IRootStorage *pRootStorage;

		m_pRootStorage->QueryInterface(IID_PPV_ARGS(&pRootStorage));
		hr = pRootStorage->SwitchToFile(szFilePath);
		pRootStorage->Release();
		if (FAILED(hr)) {
			m_pRootStorage->Revert();
			return FALSE;
		}

		lstrcpyW(m_szFilePath, szFilePath);
	}

	m_pRootStorage->Commit(STGC_DEFAULT);

	return TRUE;
}

BOOL CContainer::LoadObject()
{
	int        i;
	ULONG      uResult;
	RECT       rc;
	WCHAR      szObjectName[256];
	WCHAR      szFilePath[MAX_PATH];
	CSite      *p = NULL;
	IOleObject *pOleObject;
	IStorage   *pStorage;

	if (!FileDialog(TRUE, szFilePath, MAX_PATH))
		return FALSE;

	if (!CreateRootStorage(szFilePath))
		return FALSE;

	lstrcpyW(m_szFilePath, szFilePath);

	m_pStream->Read(&m_nObjectCount, sizeof(int), &uResult);
	for (i = 0; i < m_nObjectCount; i++) {
		wsprintf(szObjectName, L"オブジェクト %d", i + 1); 
		m_pRootStorage->OpenStorage(szObjectName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
		OleLoad(pStorage, IID_IOleObject, NULL, (void **)&pOleObject);

		m_pStream->Read(&rc, sizeof(RECT), &uResult);

		if (i == 0) {
			m_pSite = new CSite;
			p = m_pSite;
		}
		else {
			p->m_pNext = new CSite;
			p = p->m_pNext;
		}

		p->Initialize(pOleObject, pStorage, szObjectName, &rc);
	}

	return TRUE;
}

void CContainer::Destroy()
{
	CSite *p = m_pSite;
	CSite *p2;
	
	while (p != NULL) {
		p2 = p->m_pNext;
		
		p->Close();
		p->Release();
		p = p2;
	}
	
	if (m_pStream != NULL)
		m_pStream->Release();

	if (m_pRootStorage != NULL)
		m_pRootStorage->Release();
}

void CContainer::ChangeSelectObject(CSite *pNew)
{
	CSite *p = m_pSite;

	while (p != NULL) {
		p->ChangeSelect(FALSE);
		p = p->m_pNext;
	}

	if (pNew != NULL)
		pNew->ChangeSelect(TRUE);
}

BOOL CContainer::GetSiteFormPos(LPARAM lParam, CSite **pp)
{
	POINT pt;
	RECT  rc;
	CSite *p = m_pSite;
	
	pt.x = LOWORD(lParam);
	pt.y = HIWORD(lParam);
	
	while (p != NULL) {
		p->GetRect(&rc);
		if (PtInRect(&rc, pt)) {
			*pp = p;
			return TRUE;
		}
		p = p->m_pNext;
	}
	
	*pp = NULL;

	return FALSE;
}

void CContainer::GetWindow(HWND *phwnd)
{
	*phwnd = m_hwnd;
}

void CContainer::InitializeMenuItem(HMENU hmenu, LPTSTR lpszItemName, int nId, HMENU hmenuSub)
{
	MENUITEMINFO mii;
	
	mii.cbSize = sizeof(MENUITEMINFO);
	mii.fMask  = MIIM_ID | MIIM_TYPE;
	mii.wID    = nId;

	if (lpszItemName != NULL) {
		mii.fType      = MFT_STRING;
		mii.dwTypeData = lpszItemName;
	}
	else
		mii.fType = MFT_SEPARATOR;

	if (hmenuSub != NULL) {
		mii.fMask   |= MIIM_SUBMENU;
		mii.hSubMenu = hmenuSub;
	}

	InsertMenuItem(hmenu, nId, FALSE, &mii);
}

BOOL CContainer::FileDialog(BOOL bOpen, LPWSTR lpszFilePath, DWORD dwLength)
{
	OPENFILENAMEW ofn;
	LPWSTR        lpszFilter = L"ols File (*.ols)\0*.ols\0\0";

	lpszFilePath[0] = '\0';

	if (bOpen) {
		ZeroMemory(&ofn, sizeof(OPENFILENAME));
		ofn.lStructSize = sizeof(OPENFILENAME);
		ofn.hwndOwner   = m_hwnd;
		ofn.lpstrFilter = lpszFilter;
		ofn.lpstrFile   = lpszFilePath;
		ofn.nMaxFile    = dwLength;
		ofn.lpstrTitle  = L"ファイルの読み込み";
		ofn.Flags       = OFN_FILEMUSTEXIST;

		if (!GetOpenFileNameW(&ofn))
			return FALSE;
	}
	else {
		ZeroMemory(&ofn, sizeof(OPENFILENAME));
		ofn.lStructSize = sizeof(OPENFILENAME);
		ofn.hwndOwner   = m_hwnd;
		ofn.lpstrFilter = lpszFilter;
		ofn.lpstrFile   = lpszFilePath;
		ofn.nMaxFile    = dwLength;
		ofn.lpstrTitle  = L"ファイルの保存";
		ofn.Flags       = OFN_FILEMUSTEXIST;
		ofn.lpstrDefExt = L"ols";

		if (!GetSaveFileNameW(&ofn))
			return FALSE;
	}

	return TRUE;
}

最後に、site.cppを示します。

#include <windows.h>
#include <oledlg.h>
#include "sample.h"
#include "site.h"

CSite::CSite()
{
	m_cRef = 1;
	m_dwConnection = 0;
	m_bSelect = FALSE;
	m_bShowWindow = FALSE;
	m_pOleObject = NULL;
	m_pStorage = NULL;
	m_pNext = NULL;
	SetRectEmpty(&m_rc);
}

CSite::~CSite()
{
	if (m_pOleObject != NULL)
		m_pOleObject->Release();

	if (m_pStorage != NULL)
		m_pStorage->Release();
}

STDMETHODIMP CSite::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;	

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IOleClientSite))
		*ppvObject = static_cast<IOleClientSite *>(this);
	else if (IsEqualIID(riid, IID_IAdviseSink))
		*ppvObject = static_cast<IAdviseSink *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CSite::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CSite::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {
		delete this;
		return 0;
	}

	return m_cRef;
}

STDMETHODIMP CSite::SaveObject()
{
	HWND hwnd;

	Save();

	UpdateRect();
	g_pContainer->GetWindow(&hwnd);
	InvalidateRect(hwnd, NULL, TRUE);

	return S_OK;
}

STDMETHODIMP CSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
{
	return E_NOTIMPL;
}

STDMETHODIMP CSite::GetContainer(IOleContainer **ppContainer)
{
	*ppContainer = NULL;

	return E_NOINTERFACE;
}

STDMETHODIMP CSite::ShowObject()
{
	return S_OK;
}

STDMETHODIMP CSite::OnShowWindow(BOOL fShow)
{
	HWND hwnd;
	
	m_bShowWindow = fShow;

	g_pContainer->GetWindow(&hwnd);
	InvalidateRect(hwnd, NULL, TRUE);

	return S_OK;
}

STDMETHODIMP CSite::RequestNewObjectLayout()
{
	return E_NOTIMPL;
}

STDMETHODIMP_(void) CSite::OnDataChange(FORMATETC *pFormatetc, STGMEDIUM *pStgmed)
{
}

STDMETHODIMP_(void) CSite::OnViewChange(DWORD dwAspect, LONG lindex)
{
	HWND hwnd;

	UpdateRect();

	g_pContainer->GetWindow(&hwnd);
	InvalidateRect(hwnd, NULL, TRUE);
}

STDMETHODIMP_(void) CSite::OnRename(IMoniker *pmk)
{
}

STDMETHODIMP_(void) CSite::OnSave()
{	
}

STDMETHODIMP_(void) CSite::OnClose()
{
}

void CSite::Initialize(IOleObject *pOlebject, IStorage *pStorage, LPWSTR lpszObjectName, LPRECT lprc)
{
	m_pStorage = pStorage;

	m_pOleObject = pOlebject;
	m_pOleObject->SetClientSite(static_cast<IOleClientSite *>(this));
	m_pOleObject->SetHostNames(L"sample", lpszObjectName);

	if (lprc != NULL)
		m_rc = *lprc;
	else
		UpdateRect();
}

void CSite::Save()
{
	IPersistStorage *pPersistStorage;

	m_pOleObject->QueryInterface(IID_PPV_ARGS(&pPersistStorage));

	OleSave(pPersistStorage, m_pStorage, TRUE);

	pPersistStorage->SaveCompleted(NULL);
	pPersistStorage->Release();
}

void CSite::RunObject(LONG lVerb)
{
	HWND        hwnd;
	IViewObject *pViewObject;
	
	m_pOleObject->Advise(static_cast<IAdviseSink *>(this), &m_dwConnection);

	m_pOleObject->QueryInterface(IID_PPV_ARGS(&pViewObject));
	pViewObject->SetAdvise(DVASPECT_CONTENT, 0, static_cast<IAdviseSink *>(this));
	pViewObject->Release();

	g_pContainer->GetWindow(&hwnd);
	m_pOleObject->DoVerb(lVerb, NULL, static_cast<IOleClientSite *>(this), 0, hwnd, &m_rc);
}

void CSite::Close()
{
	if (OleIsRunning(m_pOleObject)) {
		m_pOleObject->Close(OLECLOSE_NOSAVE);
		m_pOleObject->Unadvise(m_dwConnection);
	}
}

void CSite::Draw(HDC hdc)
{
	OleDraw(m_pOleObject, DVASPECT_CONTENT, hdc, &m_rc);

	if (m_bShowWindow) {
		HBRUSH hbr;
		hbr = CreateHatchBrush(HS_BDIAGONAL, RGB(128, 128, 128));
		SelectObject(hdc, hbr);
		SetBkMode(hdc, TRANSPARENT);
		Rectangle(hdc, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom);
		DeleteObject(hbr);
	}
	
	if (m_bSelect)
		DrawFocusRect(hdc, &m_rc);
	else
		FrameRect(hdc, &m_rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
}

void CSite::AddVerbMenu(HMENU hmenu, UINT uIdVerbMin, UINT uIdVerbMax)
{
	HMENU hmenuTmp;
	
	OleUIAddVerbMenu(m_pOleObject, NULL, hmenu, 0, uIdVerbMin, uIdVerbMax, FALSE, 0, &hmenuTmp);
}

void CSite::ChangeSelect(BOOL bSelect)
{
	m_bSelect = bSelect;
}

void CSite::GetRect(LPRECT lprc)
{
	*lprc = m_rc;
}

void CSite::UpdateRect()
{
	SIZEL sizel;
	
	m_pOleObject->GetExtent(DVASPECT_CONTENT, &sizel);

	HIMETRICtoDP(&sizel);
	m_rc.right = m_rc.left + sizel.cx;
	m_rc.bottom = m_rc.top + sizel.cy;
}

void CSite::MoveRect(LPARAM lParam)
{
	int x, y;

	x = LOWORD(lParam) - m_ptClick.x;
	y = HIWORD(lParam) - m_ptClick.y;

	m_ptClick.x = LOWORD(lParam);
	m_ptClick.y = HIWORD(lParam);

	OffsetRect(&m_rc, x, y);
}

void CSite::SetClickPos(LPARAM lParam)
{
	m_ptClick.x = LOWORD(lParam);
	m_ptClick.y = HIWORD(lParam);
}

void CSite::HIMETRICtoDP(LPSIZEL lpSizel)
{
	HDC hdc;
	const int HIMETRIC_INCH = 2540;

	hdc = GetDC(NULL);
	lpSizel->cx = lpSizel->cx * GetDeviceCaps(hdc, LOGPIXELSX) / HIMETRIC_INCH;
	lpSizel->cy = lpSizel->cy * GetDeviceCaps(hdc, LOGPIXELSY) / HIMETRIC_INCH;
	ReleaseDC(NULL, hdc);
}

戻る