EternalWindows
インプレースアクティベーション / オブジェクトサンプル

インプレースアクティベーションのオブジェクト側のサンプルを示します。 まず、object.hを示します。

struct SHAPE {
	RECT rc;
	BOOL bRectangle;
};
typedef struct SHAPE SHAPE;
typedef struct SHAPE *LPSHAPE;

class CObject : public IOleObject, public IDataObject, public IPersistStorage, public IOleInPlaceObject, public IOleInPlaceActiveObject
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();

	STDMETHODIMP SetClientSite(IOleClientSite *pClientSite);
	STDMETHODIMP GetClientSite(IOleClientSite **ppClientSite);
	STDMETHODIMP SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
	STDMETHODIMP Close(DWORD dwSaveOption);
	STDMETHODIMP SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk);
	STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
	STDMETHODIMP InitFromData(IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved);
	STDMETHODIMP GetClipboardData(DWORD dwReserved, IDataObject **ppDataObject);
	STDMETHODIMP DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect);
	STDMETHODIMP EnumVerbs(IEnumOLEVERB **ppEnumOleVerb);
	STDMETHODIMP Update();
	STDMETHODIMP IsUpToDate();
	STDMETHODIMP GetUserClassID(CLSID *pClsid);
	STDMETHODIMP GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType);
	STDMETHODIMP SetExtent(DWORD dwDrawAspect, SIZEL *psizel);
	STDMETHODIMP GetExtent(DWORD dwDrawAspect, SIZEL *psizel);
	STDMETHODIMP Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection);
	STDMETHODIMP Unadvise(DWORD dwConnection);
	STDMETHODIMP EnumAdvise(IEnumSTATDATA **ppenumAdvise);
	STDMETHODIMP GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus);
	STDMETHODIMP SetColorScheme(LOGPALETTE *pLogpal);

	STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
	STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
	STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
	STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut);
	STDMETHODIMP SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease);
	STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc);
	STDMETHODIMP DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
	STDMETHODIMP DUnadvise(DWORD dwConnection);
	STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);

	STDMETHODIMP GetClassID(CLSID *pClassID);
	STDMETHODIMP IsDirty();
	STDMETHODIMP InitNew(IStorage *pStg);
	STDMETHODIMP Load(IStorage *pStg);
	STDMETHODIMP Save(IStorage *pStgSave, BOOL fSameAsLoad);
	STDMETHODIMP SaveCompleted(IStorage *pStgNew);
	STDMETHODIMP HandsOffStorage();

	STDMETHODIMP GetWindow(HWND *phwnd);
	STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
	STDMETHODIMP InPlaceDeactivate();
	STDMETHODIMP ReactivateAndUndo();
	STDMETHODIMP SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
	STDMETHODIMP UIDeactivate();
	
	STDMETHODIMP TranslateAccelerator(LPMSG lpmsg);
	STDMETHODIMP OnFrameWindowActivate(BOOL fActivate);
	STDMETHODIMP OnDocWindowActivate(BOOL fActivate);
	STDMETHODIMP ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow);
	STDMETHODIMP EnableModeless(BOOL fEnable);
	
	CObject();
	~CObject();
	int Run(HINSTANCE hinst, int nCmdShow, BOOL bEmbedding);
	LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	LRESULT WindowProcInplace(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	void OnLButtonDown(HWND hwnd, int x, int y);
	BOOL InPlaceActivate(HWND hwndParent, LPRECT lprc, BOOL bUIActivate);
	BOOL UIActivate();
	void DrawShape(HDC hdc);
	void GetSize(int *pnWidth, int *pnHeight);
	HGLOBAL GetMetaFileData(BOOL bEnhance);
	void DPtoHIMETRIC(LPSIZEL lpSizel);
	void SaveObject();
	void InitializeMenuItem(HMENU hmenu, LPTSTR lpszItemName, int nId, HMENU hmenuSub);
	void InitializeMenuItemByPos(HMENU hmenu, LPTSTR lpszItemName, int nId, int nPos, HMENU hmenuSub);

private:
	LONG                m_cRef;
	HWND                m_hwnd;
	HMENU               m_hmenu;
	BOOL                m_bEmbedding;
	BOOL                m_bDirty;
	BOOL                m_bDrawRectangle;
	WCHAR               m_szStreamName[256];
	SHAPE               m_shape[10];
	int                 m_nShapeCount;
	int                 m_nShapeMaxCount;
	IStorage            *m_pStorage;
	IStream             *m_pStream;
	IOleClientSite      *m_pClientSite;
	IOleAdviseHolder    *m_pAdviseHolder;
	IDataAdviseHolder   *m_pDataAdviseHolder;
	IOleInPlaceFrame    *m_pInPlaceFrame;
	IOleInPlaceUIWindow *m_pInPlaceUIWindow;
	IOleInPlaceSite     *m_pInPlaceSite;
	OLEINPLACEFRAMEINFO m_frameInfo;
	HMENU               m_hmenuShared;
	HOLEMENU            m_holemenu;
	HWND                m_hwndInplace;
	HWND                m_hwndToolbar;
	int                 m_nToolbarHeight;
	TCHAR               m_szInplaceClassName[256];
};

extern CObject *g_pObject;

const CLSID CLSID_SampleObject = {0x9d22dc48, 0x655, 0x4c36, {0x93, 0xad, 0xdf, 0xd8, 0xf0, 0x53, 0xab, 0xe0}};
const TCHAR g_szClsid[] = TEXT("{9D22DC48-0655-4c36-93AD-DFD8F053ABE0}");
const TCHAR g_szProgid[] = TEXT("Sample.OleServer");

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

#include <windows.h>
#include <shlwapi.h>
#include "object.h"

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

class CClassFactory : public IClassFactory
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
	
	STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
	STDMETHODIMP LockServer(BOOL fLock);
};

BOOL RegisterServer();
BOOL UnregisterServer();
BOOL CreateVerbKey();
BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	int           nResult;
	DWORD         dwRegister = 0;
	BOOL          bEmbedding;
	CClassFactory classFactory;

	OleInitialize(NULL);
	
	g_pObject = new CObject;
	if (g_pObject == NULL) {
		OleUninitialize();
		return 0;
	}

	if ((lstrcmpA(lpszCmdLine, "-RegServer") == 0) || (lstrcmpA(lpszCmdLine, "/RegServer") == 0)) {
		if (RegisterServer())
			MessageBox(NULL, TEXT("登録に成功しました。"), TEXT("OK"), MB_OK);
		else
			MessageBox(NULL, TEXT("登録に失敗しました。"), NULL, MB_ICONWARNING);
		OleUninitialize();
		return 0;
	}
	else if ((lstrcmpA(lpszCmdLine, "-UnregServer") == 0) || (lstrcmpA(lpszCmdLine, "/UnregServer") == 0)) {
		UnregisterServer();
		MessageBox(NULL, TEXT("登録を解除しました。"), TEXT("OK"), MB_OK);
		OleUninitialize();
		return 0;
	}
	else if (lstrcmpA(lpszCmdLine, "-Embedding") == 0 || (lstrcmpA(lpszCmdLine, "/Embedding") == 0)) {
		CoRegisterClassObject(CLSID_SampleObject, static_cast<IClassFactory *>(&classFactory), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegister);
		nCmdShow = SW_HIDE;
		bEmbedding = TRUE;
	}
	else
		bEmbedding = FALSE;

	nResult = g_pObject->Run(hinst, nCmdShow, bEmbedding);
	g_pObject->Release();

	if (bEmbedding)
		CoRevokeClassObject(dwRegister);

	OleUninitialize();

	return nResult;
}


// CClassFactory


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

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

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
	return 2;
}

STDMETHODIMP_(ULONG) CClassFactory::Release()
{
	return 1;
}

STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{
	HRESULT hr;

	*ppvObject = NULL;

	if (pUnkOuter != NULL)
		return CLASS_E_NOAGGREGATION;

	hr = g_pObject->QueryInterface(riid, ppvObject);

	return hr;
}

STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
	return S_OK;
}


// Function


BOOL RegisterServer()
{
	TCHAR szObjectName[] = TEXT("Sample Object");
	TCHAR szModulePath[MAX_PATH];
	TCHAR szKey[256];

	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szObjectName))
		return FALSE;

	GetModuleFileName(NULL, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
	wsprintf(szKey, TEXT("CLSID\\%s\\LocalServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szModulePath))
		return FALSE;
	
	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("ole32.dll")))
		return FALSE;

	wsprintf(szKey, TEXT("CLSID\\%s\\ProgID"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, (LPTSTR)g_szProgid))
		return FALSE;

	wsprintf(szKey, TEXT("%s"), g_szProgid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szObjectName))
		return FALSE;

	wsprintf(szKey, TEXT("%s\\Insertable"), g_szProgid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, NULL))
		return FALSE;
  
	wsprintf(szKey, TEXT("%s\\CLSID"), g_szProgid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, (LPTSTR)g_szClsid))
		return FALSE;
	
	if (!CreateVerbKey())
		return FALSE;

	return TRUE;
}

BOOL UnregisterServer()
{
	TCHAR szKey[256];

	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	SHDeleteKey(HKEY_CLASSES_ROOT, szKey);
	
	wsprintf(szKey, TEXT("%s"), g_szProgid);
	SHDeleteKey(HKEY_CLASSES_ROOT, szKey);

	return TRUE;
}

BOOL CreateVerbKey()
{
	TCHAR szKey[256];

	wsprintf(szKey, TEXT("CLSID\\%s\\Verb"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, NULL))
		return FALSE;

	wsprintf(szKey, TEXT("CLSID\\%s\\Verb\\0"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("&編集,0,2")))
		return FALSE;

	wsprintf(szKey, TEXT("CLSID\\%s\\Verb\\1"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("&開く,0,2")))
		return FALSE;

	return TRUE;
}

BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData)
{
	HKEY  hKey;
	LONG  lResult;
	DWORD dwSize;

	lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
	if (lResult != ERROR_SUCCESS)
		return FALSE;

	if (lpszData != NULL)
		dwSize = (lstrlen(lpszData) + 1) * sizeof(TCHAR);
	else
		dwSize = 0;

	RegSetValueEx(hKey, lpszValue, 0, REG_SZ, (LPBYTE)lpszData, dwSize);
	RegCloseKey(hKey);
	
	return TRUE;
}

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

#include <windows.h>
#include <commctrl.h>
#include "object.h"

#define ID_FILE 100
#define ID_EXIT 200
#define ID_UPDATE 300
#define ID_EDIT 400
#define ID_RECTANGLE 500
#define ID_ELLIPSE 600
#define ID_TOOLBAR 1000
#define ID_INPLACEWINDOW 2000

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

CObject *g_pObject = NULL;

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

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


// CObject


CObject::CObject()
{
	m_cRef = 1;
	m_hwnd = NULL;
	m_hmenu = NULL;
	m_bEmbedding = FALSE;
	m_bDirty = FALSE;
	m_bDrawRectangle = TRUE;
	m_nShapeCount = 0;
	m_nShapeMaxCount = sizeof(m_shape) / sizeof(m_shape[0]);
	m_pStorage = NULL;
	m_pStream = NULL;
	m_pClientSite = NULL;
	m_pAdviseHolder = NULL;
	m_pDataAdviseHolder = NULL;
	m_pInPlaceFrame = NULL;
	m_pInPlaceUIWindow = NULL;
	m_pInPlaceSite = NULL;
	m_holemenu = NULL;
	m_hmenuShared = NULL;
	m_hwndInplace = NULL;
	m_hwndToolbar = NULL;
	m_nToolbarHeight = 30;
	lstrcpyW(m_szStreamName, L"stream");
}

CObject::~CObject()
{
	HandsOffStorage();
	
	if (m_pAdviseHolder != NULL)
		m_pAdviseHolder->Release();

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

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

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IOleObject))
		*ppvObject = static_cast<IOleObject *>(this);
	else if (IsEqualIID(riid, IID_IDataObject))
		*ppvObject = static_cast<IDataObject *>(this);
	else if (IsEqualIID(riid, IID_IPersist) || IsEqualIID(riid, IID_IPersistStorage))
		*ppvObject = static_cast<IPersistStorage *>(this);
	else if (IsEqualIID(riid, IID_IOleWindow) || IsEqualIID(riid, IID_IOleInPlaceObject))
		*ppvObject = static_cast<IOleInPlaceObject *>(this);
	else if (IsEqualIID(riid, IID_IOleInPlaceActiveObject))
		*ppvObject = static_cast<IOleInPlaceActiveObject *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

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

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

	return m_cRef;
}

STDMETHODIMP CObject::SetClientSite(IOleClientSite *pClientSite)
{
	if (m_pClientSite != NULL)
		m_pClientSite->Release();

	m_pClientSite = pClientSite;

	if (m_pClientSite != NULL)
		m_pClientSite->AddRef();

	return S_OK;
}

STDMETHODIMP CObject::GetClientSite(IOleClientSite **ppClientSite)
{
	*ppClientSite = m_pClientSite;
	m_pClientSite->AddRef();

	return S_OK;
}

STDMETHODIMP CObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
{
	int   i, nCount;
	HMENU hmenuPopupFile;
	WCHAR szBuf[256];

	hmenuPopupFile = GetSubMenu(m_hmenu, 0);
	nCount = GetMenuItemCount(hmenuPopupFile);

	for (i = 0; i < nCount; i++)
		RemoveMenu(hmenuPopupFile, 0, MF_BYPOSITION);

	wsprintf(szBuf, L"%sの更新", szContainerObj);
	InitializeMenuItem(hmenuPopupFile, szBuf, ID_UPDATE, NULL);
	InitializeMenuItem(hmenuPopupFile, TEXT("終了(&X)"), ID_EXIT, NULL);

	return S_OK;
}

STDMETHODIMP CObject::Close(DWORD dwSaveOption)
{
	BOOL bDontSave;

	if (dwSaveOption == OLECLOSE_NOSAVE)
		bDontSave = TRUE;
	else
		bDontSave = FALSE;
	
	PostMessage(m_hwnd, WM_CLOSE, (WPARAM)bDontSave, 0);
	
	return S_OK;
}

STDMETHODIMP CObject::SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk)
{
	return E_NOTIMPL;
}

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

STDMETHODIMP CObject::InitFromData(IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::GetClipboardData(DWORD dwReserved, IDataObject **ppDataObject)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
{
	BOOL bOpen = FALSE;

	if (iVerb == OLEIVERB_SHOW || iVerb == OLEIVERB_PRIMARY || iVerb == OLEIVERB_UIACTIVATE) {
		if (!InPlaceActivate(hwndParent, (LPRECT)lprcPosRect, TRUE))
			bOpen = TRUE;
	}
	else if (iVerb == OLEIVERB_INPLACEACTIVATE) {
		if (!InPlaceActivate(hwndParent, (LPRECT)lprcPosRect, FALSE))
			bOpen = TRUE;
	}
	else if (iVerb == OLEIVERB_OPEN || iVerb == 1)
		bOpen = TRUE;
	else if (iVerb == OLEIVERB_HIDE)
		InPlaceDeactivate();
	else
		return E_FAIL;

	if (bOpen) {
		m_pClientSite->ShowObject();
		if (lprcPosRect != NULL){
			RECT rc = *lprcPosRect;
			AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, TRUE, 0);
			SetWindowPos(m_hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
		}
		ShowWindow(m_hwnd, SW_SHOW);
		SetForegroundWindow(m_hwnd);
		m_pClientSite->OnShowWindow(TRUE);
	}

	return S_OK;
}

STDMETHODIMP CObject::EnumVerbs(IEnumOLEVERB **ppEnumOleVerb)
{
	return OLE_S_USEREG;
}

STDMETHODIMP CObject::Update()
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::IsUpToDate()
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::GetUserClassID(CLSID *pClsid)
{
	*pClsid = CLSID_SampleObject;

	return S_OK;
}

STDMETHODIMP CObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
	return OLE_S_USEREG;
}

STDMETHODIMP CObject::SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::GetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
	int nWidth, nHeight;

	GetSize(&nWidth, &nHeight);
	psizel->cx = nWidth;
	psizel->cy = nHeight;
	
	DPtoHIMETRIC(psizel);

	return S_OK;
}

STDMETHODIMP CObject::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
	if (m_pAdviseHolder == NULL)
		CreateOleAdviseHolder(&m_pAdviseHolder);

	return m_pAdviseHolder->Advise(pAdvSink, pdwConnection);
}

STDMETHODIMP CObject::Unadvise(DWORD dwConnection)
{
	if (m_pAdviseHolder != NULL)
		m_pAdviseHolder->Unadvise(dwConnection);

	return S_OK;
}

STDMETHODIMP CObject::EnumAdvise(IEnumSTATDATA **ppenumAdvise)
{
	if (m_pAdviseHolder != NULL)
		m_pAdviseHolder->EnumAdvise(ppenumAdvise);

	return S_OK;
}


STDMETHODIMP CObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
{
	*pdwStatus = 0;

	return S_OK;
}

STDMETHODIMP CObject::SetColorScheme(LOGPALETTE *pLogpal)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
	if (pformatetcIn->cfFormat == CF_METAFILEPICT) {
		pmedium->tymed = TYMED_MFPICT;
		pmedium->pUnkForRelease = NULL;
		pmedium->hGlobal = GetMetaFileData(FALSE);
	}
	else if (pformatetcIn->cfFormat == CF_ENHMETAFILE) {
		pmedium->tymed = TYMED_ENHMF;
		pmedium->pUnkForRelease = NULL;
		pmedium->hEnhMetaFile = (HENHMETAFILE)GetMetaFileData(TRUE);
	}
	else
		return E_FAIL;

	return S_OK;
}

STDMETHODIMP CObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::QueryGetData(FORMATETC *pformatetc)
{
	if (pformatetc->cfFormat == CF_METAFILEPICT || pformatetc->cfFormat == CF_ENHMETAFILE)
		return S_OK;

	return S_FALSE;
}

STDMETHODIMP CObject::GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut)
{
	return DATA_S_SAMEFORMATETC;
}

STDMETHODIMP CObject::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
	if (m_pDataAdviseHolder == NULL)
		CreateDataAdviseHolder(&m_pDataAdviseHolder);

	return m_pDataAdviseHolder->Advise(static_cast<IDataObject *>(this), pformatetc, advf, pAdvSink, pdwConnection);
}

STDMETHODIMP CObject::DUnadvise(DWORD dwConnection)
{
	if (m_pDataAdviseHolder != NULL)
		m_pDataAdviseHolder->Unadvise(dwConnection);

	return S_OK;
}

STDMETHODIMP CObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
{
	if (m_pDataAdviseHolder != NULL)
		m_pDataAdviseHolder->EnumAdvise(ppenumAdvise);

	return S_OK;
}

STDMETHODIMP CObject::GetClassID(CLSID *pClassID)
{
	*pClassID = CLSID_SampleObject;

	return S_OK;
}

STDMETHODIMP CObject::IsDirty()
{
	if (m_bDirty)
		return S_OK;
	else
		return S_FALSE;
}

STDMETHODIMP CObject::InitNew(IStorage *pStg)
{
	if (m_pStream != NULL)
		return E_UNEXPECTED;

	pStg->CreateStream(m_szStreamName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStream);

	m_pStorage = pStg;
	m_pStorage->AddRef();
	
	return S_OK;
}

STDMETHODIMP CObject::Load(IStorage *pStg)
{
	int     i;
	ULONG   uResult;
	IStream *pStream;

	if (SaveCompleted(pStg) != S_OK)
		return E_FAIL;

	m_pStream->Read(&m_nShapeCount, sizeof(int), &uResult);

	for (i = 0; i < m_nShapeCount; i++) {
		m_pStream->Read(&m_shape[i].rc, sizeof(RECT), &uResult);
		m_pStream->Read(&m_shape[i].bRectangle, sizeof(BOOL), &uResult);
	}
	
	m_bDirty = FALSE;

	return S_OK;
}

STDMETHODIMP CObject::Save(IStorage *pStgSave, BOOL fSameAsLoad)
{
	int           i;
	ULONG         uResult;
	IStream       *pStream;
	LARGE_INTEGER li = {0};
	
	m_pStream->Seek(li, STREAM_SEEK_SET, NULL);
	m_pStream->Write(&m_nShapeCount, sizeof(int), &uResult);

	for (i = 0; i < m_nShapeCount; i++) {
		m_pStream->Write(&m_shape[i].rc, sizeof(RECT), &uResult);
		m_pStream->Write(&m_shape[i].bRectangle, sizeof(BOOL), &uResult);
	}

	m_bDirty = FALSE;
	
	return S_OK;
}

STDMETHODIMP CObject::SaveCompleted(IStorage *pStgNew)
{
	if (pStgNew != NULL) {
		HandsOffStorage();

		pStgNew->OpenStream(m_szStreamName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &m_pStream);
		if (m_pStream == NULL)
			return E_FAIL;

		m_pStorage = pStgNew;
		m_pStorage->AddRef();
	}

	return S_OK;
}

STDMETHODIMP CObject::HandsOffStorage()
{
	if (m_pStorage != NULL) {
		m_pStorage->Release();
		m_pStorage = NULL;
	}
	
	if (m_pStream != NULL) {
		m_pStream->Release();
		m_pStream = NULL;
	}

	return S_OK;
}

STDMETHODIMP CObject::GetWindow(HWND *phwnd)
{
	if (m_hwndInplace != NULL)
		*phwnd = m_hwndInplace;
	else
		*phwnd = m_hwnd;

	return S_OK;
}

STDMETHODIMP CObject::ContextSensitiveHelp(BOOL fEnterMode)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::InPlaceDeactivate()
{
	UIDeactivate();

	if (m_pInPlaceSite != NULL) {
		m_pInPlaceSite->OnInPlaceDeactivate();
		m_pInPlaceSite->Release();
		m_pInPlaceSite = NULL;
	}

	if (m_hwndInplace != NULL) {
		DestroyWindow(m_hwndInplace);
		m_hwndInplace = NULL;
		m_pClientSite->OnShowWindow(FALSE);
	}

	return S_OK;
}

STDMETHODIMP CObject::ReactivateAndUndo()
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
{
	MoveWindow(m_hwndInplace, lprcPosRect->left, lprcPosRect->top, lprcPosRect->right - lprcPosRect->left, lprcPosRect->bottom - lprcPosRect->top, TRUE);	
	
	return S_OK;
}

STDMETHODIMP CObject::UIDeactivate()
{
	if (m_pInPlaceSite != NULL)
		m_pInPlaceSite->OnUIDeactivate(FALSE);
	
	if (m_pInPlaceUIWindow != NULL) {
		m_pInPlaceUIWindow->SetActiveObject(NULL, NULL);
		m_pInPlaceUIWindow->Release();
		m_pInPlaceUIWindow = NULL;
	}

	if (m_pInPlaceFrame != NULL) {
		m_pInPlaceFrame->SetMenu(NULL, NULL, NULL);
		OleDestroyMenuDescriptor(m_holemenu);
		m_holemenu = NULL;
		RemoveMenu(m_hmenuShared, ID_EDIT, MF_BYCOMMAND);
		m_pInPlaceFrame->RemoveMenus(m_hmenuShared);
		DestroyMenu(m_hmenuShared);
		m_hmenuShared = NULL;

		SetParent(m_hwndToolbar, m_hwnd);

		m_pInPlaceFrame->SetActiveObject(NULL, NULL);
		m_pInPlaceFrame->Release();
		m_pInPlaceFrame = NULL;
	}

	return S_OK;
}

STDMETHODIMP CObject::TranslateAccelerator(LPMSG lpmsg)
{
	return E_NOTIMPL;
}

STDMETHODIMP CObject::OnFrameWindowActivate(BOOL fActivate)
{
	return S_OK;
}

STDMETHODIMP CObject::OnDocWindowActivate(BOOL fActivate)
{
	return S_OK;
}

STDMETHODIMP CObject::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
{
	MoveWindow(m_hwndToolbar, prcBorder->left, prcBorder->top, prcBorder->right - prcBorder->top, m_nToolbarHeight, TRUE);

	return S_OK;
}

STDMETHODIMP CObject::EnableModeless(BOOL fEnable)
{
	return E_NOTIMPL;
}

int CObject::Run(HINSTANCE hinst, int nCmdShow, BOOL bEmbedding)
{
	TCHAR      szAppName[] = TEXT("object");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;
	RECT       rc;
	int        nWidth, nHeight;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	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;

	lstrcpy(m_szInplaceClassName, TEXT("inplace"));
	wc.lpfnWndProc   = ::WindowProcInplace;
	wc.lpszClassName = m_szInplaceClassName;
	if (RegisterClassEx(&wc) == 0)
		return 0;
	
	m_bEmbedding = bEmbedding;
	if (bEmbedding) {
		SetRect(&rc, 0, 0, 230, 200);
		AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, TRUE, 0);
		nWidth = rc.right - rc.left;
		nHeight = rc.bottom - rc.top;
	}
	else {
		nWidth = CW_USEDEFAULT;
		nHeight = CW_USEDEFAULT;
	}

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, nWidth, nHeight, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		if (OleTranslateAccelerator(m_pInPlaceFrame, &m_frameInfo, &msg) != S_OK) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}

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

	case WM_CREATE: {
		TBBUTTON tbButton[] = {
			{I_IMAGENONE, ID_RECTANGLE, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("Rectangle")},
			{I_IMAGENONE, ID_ELLIPSE, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("Ellipse")}
		};
		int                  nCount = nCount = sizeof(tbButton) / sizeof(tbButton[0]);
		INITCOMMONCONTROLSEX ic;
		HMENU                hmenu;
		HMENU                hmenuPopupFile;
		HMENU                hmenuPopupEdit;

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

		InitializeMenuItem(hmenuPopupFile, TEXT("終了(&X)"), ID_EXIT, NULL);
		InitializeMenuItem(hmenuPopupEdit, TEXT("Rectangle"), ID_RECTANGLE, NULL);
		InitializeMenuItem(hmenuPopupEdit, TEXT("Ellipse"), ID_ELLIPSE, NULL);

		InitializeMenuItem(hmenu, TEXT("ファイル(&F)"), ID_FILE, hmenuPopupFile);
		InitializeMenuItem(hmenu, TEXT("編集(&E)"), ID_EDIT, hmenuPopupEdit);

		m_hwnd = hwnd;
		m_hmenu = hmenu;
		SetMenu(m_hwnd, m_hmenu);

		ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
		ic.dwICC  = ICC_BAR_CLASSES;
		InitCommonControlsEx(&ic);

		m_hwndToolbar = CreateToolbarEx(hwnd, WS_CHILD | WS_VISIBLE | TBSTYLE_LIST, ID_TOOLBAR, 0, HINST_COMMCTRL, IDB_STD_SMALL_COLOR, tbButton, nCount, 0, 0, 0, 0, sizeof(TBBUTTON));

		return 0;
	}
	
	case WM_PAINT: {
		HDC         hdc;
		PAINTSTRUCT ps;

		hdc = BeginPaint(hwnd, &ps);

		DrawShape(hdc);

		EndPaint(hwnd, &ps);

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

		if (nId == ID_RECTANGLE)
			m_bDrawRectangle = TRUE;
		else if (nId == ID_ELLIPSE)
			m_bDrawRectangle = FALSE;
		else if (nId == ID_EXIT)
			PostMessage(m_hwnd, WM_CLOSE, 0, 0);
		else if (nId == ID_UPDATE)
			SaveObject();
		else
			;

		return 0;
	}
	
	case WM_LBUTTONDOWN:
		OnLButtonDown(hwnd, LOWORD(lParam), HIWORD(lParam));
		return 0;

	case WM_EXITSIZEMOVE:
		if (m_bEmbedding && m_pDataAdviseHolder != NULL)
			m_pDataAdviseHolder->SendOnDataChange(static_cast<IDataObject *>(this), 0, DVASPECT_CONTENT);
		return 0;

	case WM_CLOSE:
		if (m_bEmbedding) {
			BOOL bDontSave = (BOOL)wParam;
			if (!bDontSave)
				SaveObject();
			m_pClientSite->OnShowWindow(FALSE);
			if (m_pAdviseHolder != NULL)
				m_pAdviseHolder->SendOnClose();
		}
		break;
	
	case WM_SIZE:
		MoveWindow(m_hwndToolbar, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

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

LRESULT CObject::WindowProcInplace(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
	
	case WM_PAINT: {
		HDC         hdc;
		PAINTSTRUCT ps;

		hdc = BeginPaint(hwnd, &ps);

		DrawShape(hdc);

		EndPaint(hwnd, &ps);

		return 0;
	}

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

		if (nId == ID_RECTANGLE)
			m_bDrawRectangle = TRUE;
		else if (nId == ID_ELLIPSE)
			m_bDrawRectangle = FALSE;
		else
			;

		return 0;
	}
	
	case WM_LBUTTONDOWN:
		OnLButtonDown(hwnd, LOWORD(lParam), HIWORD(lParam));
		return 0;

	case WM_EXITSIZEMOVE: {
		RECT rc;

		GetWindowRect(hwnd, &rc);

		ScreenToClient(GetParent(hwnd), (LPPOINT)&rc);
		ScreenToClient(GetParent(hwnd), (LPPOINT)&rc + 1);
		m_pInPlaceSite->OnPosRectChange(&rc);

		if (m_bEmbedding && m_pDataAdviseHolder != NULL)
			m_pDataAdviseHolder->SendOnDataChange(static_cast<IDataObject *>(this), 0, DVASPECT_CONTENT);

		return 0;
	}

	default:
		break;

	}

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

void CObject::OnLButtonDown(HWND hwnd, int x, int y)
{
	RECT rc;
	
	if (m_nShapeCount >= m_nShapeMaxCount) {
		MessageBox(hwnd, TEXT("最大数に達しました。"), TEXT("OK"), MB_OK);
		return;
	}
	
	SetRect(&rc, x, y, x + 70, y + 30);
	m_shape[m_nShapeCount].rc = rc;
	m_shape[m_nShapeCount].bRectangle = m_bDrawRectangle;
	m_nShapeCount++;
	
	InvalidateRect(hwnd, &rc, FALSE);
	
	if (m_bEmbedding && m_pDataAdviseHolder != NULL)
		m_pDataAdviseHolder->SendOnDataChange(static_cast<IDataObject *>(this), 0, DVASPECT_CONTENT);
	
	m_bDirty = TRUE;
}

BOOL CObject::InPlaceActivate(HWND hwndParent, LPRECT lprc, BOOL bUIActivate)
{
	HRESULT hr;

	hr = m_pClientSite->QueryInterface(IID_PPV_ARGS(&m_pInPlaceSite));
	if (FAILED(hr))
		return FALSE;
	
	hr = m_pInPlaceSite->CanInPlaceActivate();
	if (FAILED(hr)) {
		m_pInPlaceSite->Release();
		m_pInPlaceSite = NULL;
		return FALSE;
	}

	m_pInPlaceSite->OnInPlaceActivate();

	m_hwndInplace = CreateWindowEx(WS_EX_NOPARENTNOTIFY, m_szInplaceClassName, TEXT(""), WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hwndParent, (HMENU)ID_INPLACEWINDOW, GetModuleHandle(NULL), NULL);

	m_pClientSite->ShowObject();
	ShowWindow(m_hwndInplace, SW_SHOW);
	m_pClientSite->OnShowWindow(TRUE);
	
	if (bUIActivate)
		UIActivate();

	return TRUE;
}

BOOL CObject::UIActivate()
{
	int                 i;
	HRESULT             hr;
	HWND                hwndParent;
	HMENU               hmenu;
	HOLEMENU            holemenu;
	OLEMENUGROUPWIDTHS  menuWidths;
	BORDERWIDTHS        borderWidths;
	RECT                rc, rcPos, rcClip;

	m_pInPlaceSite->OnUIActivate();

	m_frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
	hr = m_pInPlaceSite->GetWindowContext(&m_pInPlaceFrame, &m_pInPlaceUIWindow, &rcPos, &rcClip, &m_frameInfo);
	if (FAILED(hr))
		return FALSE;

	for (i = 0; i < 6; i++)
		menuWidths.width[i] = 0;
	hmenu = CreateMenu();
	m_pInPlaceFrame->InsertMenus(hmenu, &menuWidths);
	InitializeMenuItemByPos(hmenu, TEXT("編集(&E)"), ID_EDIT, menuWidths.width[0], GetSubMenu(m_hmenu, 1));
	menuWidths.width[1] = 1;
	holemenu = OleCreateMenuDescriptor(hmenu, &menuWidths);
	m_pInPlaceFrame->SetMenu(hmenu, holemenu, m_hwnd);
	m_holemenu = holemenu;
	m_hmenuShared = hmenu;
	
	SetRect((LPRECT)&borderWidths, 0, m_nToolbarHeight, 0, 0);
	hr = m_pInPlaceFrame->RequestBorderSpace(&borderWidths);
	if (hr == S_OK) {
		m_pInPlaceFrame->SetBorderSpace(&borderWidths);
		m_pInPlaceFrame->GetBorder(&rc);
		m_pInPlaceFrame->GetWindow(&hwndParent);
		SetParent(m_hwndToolbar, hwndParent);
		MoveWindow(m_hwndToolbar, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
	}

	if (m_pInPlaceUIWindow != NULL)
		m_pInPlaceUIWindow->SetActiveObject(static_cast<IOleInPlaceActiveObject *>(this), NULL);

	m_pInPlaceFrame->SetActiveObject(static_cast<IOleInPlaceActiveObject *>(this), NULL);
	
	return TRUE;
}

void CObject::DrawShape(HDC hdc)
{
	int  i;
	RECT rc;

	for (i = 0; i < m_nShapeCount; i++) {
		rc = m_shape[i].rc;
		if (m_shape[i].bRectangle)
			Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
		else
			Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
	}
}

HGLOBAL CObject::GetMetaFileData(BOOL bEnhance)
{
	HDC            hdc;
	HMETAFILE      hmf;
	HGLOBAL        hglobal;
	LPMETAFILEPICT lpmf;
	SIZEL          sizel;
	int            nWidth, nHeight;
	
	hdc = (HDC)CreateMetaFile(NULL);
	
	GetSize(&nWidth, &nHeight);

	SetMapMode(hdc, MM_ANISOTROPIC);
	SetWindowOrgEx(hdc, 0, 0, NULL);
	SetWindowExtEx(hdc, nWidth, nHeight, NULL);
	
	DrawShape(hdc);
	
	hmf = CloseMetaFile(hdc);

	sizel.cx = nWidth;
	sizel.cy = nHeight;
	DPtoHIMETRIC(&sizel);

	hglobal = GlobalAlloc(GPTR, sizeof(METAFILEPICT));
	lpmf = (LPMETAFILEPICT)GlobalLock(hglobal);
	lpmf->hMF = hmf;
	lpmf->mm = MM_ANISOTROPIC;
	lpmf->xExt = sizel.cx;
	lpmf->yExt = sizel.cy;
	GlobalUnlock(hglobal);

	if (bEnhance) {
		DWORD   dwSize;
		LPBYTE  lpData;
		HGLOBAL hglobalOld = hglobal;
		
		dwSize = GetMetaFileBitsEx(lpmf->hMF, 0, NULL);
		lpData = (LPBYTE)GlobalAlloc(GPTR, dwSize);
		GetMetaFileBitsEx(lpmf->hMF, dwSize, lpData);
		hglobal = (HGLOBAL)SetWinMetaFileBits(dwSize, lpData, NULL, lpmf);
		GlobalFree(lpData);
		GlobalFree(hglobalOld);
	}

	return hglobal;
}

void CObject::GetSize(int *pnWidth, int *pnHeight)
{
	HWND hwnd;
	RECT rc;
	
	if (m_hwndInplace != NULL)
		hwnd = m_hwndInplace;
	else
		hwnd = m_hwnd;

	GetClientRect(hwnd, &rc);
	*pnWidth = rc.right - rc.left;
	*pnHeight = rc.bottom - rc.top;
}

void CObject::DPtoHIMETRIC(LPSIZEL lpSizel)
{
	HDC hdc;
	const int HIMETRIC_INCH = 2540;
	
	hdc = GetDC(NULL);
	lpSizel->cx = lpSizel->cx * HIMETRIC_INCH / GetDeviceCaps(hdc, LOGPIXELSX);
	lpSizel->cy = lpSizel->cy * HIMETRIC_INCH / GetDeviceCaps(hdc, LOGPIXELSY);
	ReleaseDC(NULL, hdc);
}

void CObject::SaveObject()
{
	if (m_bEmbedding) {
		m_pClientSite->SaveObject();
		if (m_pAdviseHolder != NULL)
			m_pAdviseHolder->SendOnSave();
	}
}

void CObject::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);
}


void CObject::InitializeMenuItemByPos(HMENU hmenu, LPTSTR lpszItemName, int nId, int nPos, 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, nPos, TRUE, &mii);
}

戻る