📄 olemisc.cpp
字号:
sc = ((COleException*)pAnyException)->m_sc;
else if (pAnyException->IsKindOf(RUNTIME_CLASS(CMemoryException)))
sc = E_OUTOFMEMORY;
else if (pAnyException->IsKindOf(RUNTIME_CLASS(CNotSupportedException)))
sc = E_NOTIMPL;
else
sc = E_UNEXPECTED; // some other problem
return sc;
}
/////////////////////////////////////////////////////////////////////////////
// Implementation helpers
HMENU AFXAPI AfxMergeMenus(HMENU hMenuShared, HMENU hMenuSource,
LONG* lpMenuWidths, int iWidthIndex, BOOL bMergeHelpMenus /* = FALSE */)
{
ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
BOOL bHelpMergedAsSubMenu = FALSE;
HMENU hHelpSubMenu = NULL;
// copy the popups from the pMenuSource
int cMenuItems = GetMenuItemCount(hMenuSource);
int cGroupWidth = 0;
int nPosition = 0;
// insert at appropriate spot depending on iWidthIndex
ASSERT(iWidthIndex == 0 || iWidthIndex == 1);
if (iWidthIndex == 1)
nPosition = (int)lpMenuWidths[0];
for (int i = 0; i < cMenuItems; i++)
{
// get the HMENU of the popup
HMENU hMenuPopup = ::GetSubMenu(hMenuSource, i);
// separators move us to next group
UINT state = GetMenuState(hMenuSource, i, MF_BYPOSITION);
if (hMenuPopup == NULL && (state & MF_SEPARATOR) != 0)
{
ASSERT(iWidthIndex <= 5); // servers should not touch past 5
lpMenuWidths[iWidthIndex] = cGroupWidth;
cGroupWidth = 0;
if (iWidthIndex < 5)
nPosition += (int)lpMenuWidths[iWidthIndex+1];
iWidthIndex += 2;
}
else
{
HMENU hHelpMenu = NULL;
// are we processing the help menu group?
if (bMergeHelpMenus && iWidthIndex == 5)
{
// if so, see if the container has Help any menu items
if (lpMenuWidths[iWidthIndex] == 1)
{
// get the help menu from the container
hHelpMenu = GetSubMenu(hMenuShared, nPosition);
}
}
// get the menu item text
TCHAR szItemText[256];
int nLen = GetMenuString(hMenuSource, i, szItemText,
sizeof szItemText, MF_BYPOSITION);
// popups are handled differently than normal menu items
if (hMenuPopup != NULL)
{
if (hHelpMenu != NULL)
{
CString strTearOff = AfxGetAppName();
if (!strTearOff.IsEmpty())
strTearOff += ' ';
strTearOff += szItemText;
// container has help items -- add ours to its submenu
AppendMenu(hHelpMenu, MF_STRING | MF_POPUP,
(UINT)hMenuPopup, strTearOff);
// clear the count of Help group items and add
// the help menu to the window group
lpMenuWidths[iWidthIndex] = 0;
lpMenuWidths[iWidthIndex-1]++;
bHelpMergedAsSubMenu = TRUE;
hHelpSubMenu = hMenuPopup;
}
else if (::GetMenuItemCount(hMenuPopup) != 0)
{
// strip the HIBYTE because it contains a count of items
state = LOBYTE(state) | MF_POPUP; // must be popup
// non-empty popup -- add it to the shared menu bar
InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
(UINT)hMenuPopup, szItemText);
++nPosition;
++cGroupWidth;
}
}
else if (nLen > 0)
{
// only non-empty items are added
ASSERT(szItemText[0] != 0);
// here the state does not contain a count in the HIBYTE
InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
GetMenuItemID(hMenuSource, i), szItemText);
++nPosition;
++cGroupWidth;
}
}
}
// set the last group width
if (!bHelpMergedAsSubMenu)
{
ASSERT(iWidthIndex <= 5); // servers should not touch past 5
lpMenuWidths[iWidthIndex] = cGroupWidth;
}
return hHelpSubMenu;
}
void AFXAPI AfxUnmergeMenus(HMENU hMenuShared, HMENU hMenuSource,
HMENU hHelpMenuPopup /* = NULL */)
{
ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
ASSERT(hHelpMenuPopup == NULL || IsMenu(hHelpMenuPopup));
int cOurItems = GetMenuItemCount(hMenuSource);
int cMenuItems = GetMenuItemCount(hMenuShared);
for (int i = cMenuItems-1; i >= 0; i--)
{
// check out the popup menus
HMENU hMenuPopup = ::GetSubMenu(hMenuShared, i);
if (hMenuPopup != NULL)
{
// if we have a Help submenu, check to see if it appears in this
// submenu someplace... this normally happens only in
// DocObject frame windows
if (hHelpMenuPopup != NULL)
{
int cPopupItems = ::GetMenuItemCount(hMenuPopup);
for (int k = 0; k < cPopupItems; k++)
{
if (::GetSubMenu(hMenuPopup, k) == hHelpMenuPopup)
{
::RemoveMenu(hMenuPopup, k, MF_BYPOSITION);
hHelpMenuPopup = NULL; // can only have one
break;
}
}
}
else
{
// if it is one of ours, remove it from the pMenuShared
for (int j = 0; j < cOurItems; j++)
{
if (::GetSubMenu(hMenuSource, j) == hMenuPopup)
{
// remove the menu from pMenuShared
RemoveMenu(hMenuShared, i, MF_BYPOSITION);
break;
}
}
}
}
}
}
// Helper for creating default FORMATETC from cfFormat
LPFORMATETC AFXAPI _AfxFillFormatEtc(
LPFORMATETC lpFormatEtc, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtcFill)
{
ASSERT(lpFormatEtcFill != NULL);
if (lpFormatEtc == NULL && cfFormat != 0)
{
lpFormatEtc = lpFormatEtcFill;
lpFormatEtc->cfFormat = cfFormat;
lpFormatEtc->ptd = NULL;
lpFormatEtc->dwAspect = DVASPECT_CONTENT;
lpFormatEtc->lindex = -1;
lpFormatEtc->tymed = (DWORD) -1;
}
return lpFormatEtc;
}
AFX_STATIC HGLOBAL AFXAPI _AfxCopyGlobalMemory(HGLOBAL hDest, HGLOBAL hSource)
{
ASSERT(hSource != NULL);
// make sure we have suitable hDest
DWORD nSize = ::GlobalSize(hSource);
if (hDest == NULL)
{
hDest = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, nSize);
if (hDest == NULL)
return NULL;
}
else if (nSize > ::GlobalSize(hDest))
{
// hDest is not large enough
return NULL;
}
// copy the bits
LPVOID lpSource = ::GlobalLock(hSource);
LPVOID lpDest = ::GlobalLock(hDest);
ASSERT(lpDest != NULL);
ASSERT(lpSource != NULL);
memcpy(lpDest, lpSource, nSize);
::GlobalUnlock(hDest);
::GlobalUnlock(hSource);
// success -- return hDest
return hDest;
}
BOOL AFXAPI _AfxCopyStgMedium(
CLIPFORMAT cfFormat, LPSTGMEDIUM lpDest, LPSTGMEDIUM lpSource)
{
if (lpDest->tymed == TYMED_NULL)
{
ASSERT(lpSource->tymed != TYMED_NULL);
switch (lpSource->tymed)
{
case TYMED_ENHMF:
case TYMED_HGLOBAL:
ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
lpDest->tymed = lpSource->tymed;
lpDest->hGlobal = NULL;
break; // fall through to CopyGlobalMemory case
case TYMED_ISTREAM:
lpDest->pstm = lpSource->pstm;
lpDest->pstm->AddRef();
lpDest->tymed = TYMED_ISTREAM;
return TRUE;
case TYMED_ISTORAGE:
lpDest->pstg = lpSource->pstg;
lpDest->pstg->AddRef();
lpDest->tymed = TYMED_ISTORAGE;
return TRUE;
case TYMED_MFPICT:
{
// copy LPMETAFILEPICT struct + embedded HMETAFILE
HGLOBAL hDest = _AfxCopyGlobalMemory(NULL, lpSource->hGlobal);
if (hDest == NULL)
return FALSE;
LPMETAFILEPICT lpPict = (LPMETAFILEPICT)::GlobalLock(hDest);
ASSERT(lpPict != NULL);
lpPict->hMF = ::CopyMetaFile(lpPict->hMF, NULL);
if (lpPict->hMF == NULL)
{
::GlobalUnlock(hDest);
::GlobalFree(hDest);
return FALSE;
}
::GlobalUnlock(hDest);
// fill STGMEDIUM struct
lpDest->hGlobal = hDest;
lpDest->tymed = TYMED_MFPICT;
}
return TRUE;
case TYMED_GDI:
lpDest->tymed = TYMED_GDI;
lpDest->hGlobal = NULL;
break;
case TYMED_FILE:
{
USES_CONVERSION;
lpDest->tymed = TYMED_FILE;
ASSERT(lpSource->lpszFileName != NULL);
UINT cbSrc = ocslen(lpSource->lpszFileName);
LPOLESTR szFileName = (LPOLESTR)CoTaskMemAlloc(cbSrc*sizeof(OLECHAR));
lpDest->lpszFileName = szFileName;
if (szFileName == NULL)
return FALSE;
memcpy(szFileName, lpSource->lpszFileName, (cbSrc+1)*sizeof(OLECHAR));
return TRUE;
}
// unable to create + copy other TYMEDs
default:
return FALSE;
}
}
ASSERT(lpDest->tymed == lpSource->tymed);
switch (lpSource->tymed)
{
case TYMED_HGLOBAL:
{
HGLOBAL hDest = _AfxCopyGlobalMemory(lpDest->hGlobal,
lpSource->hGlobal);
if (hDest == NULL)
return FALSE;
lpDest->hGlobal = hDest;
}
return TRUE;
case TYMED_ISTREAM:
{
ASSERT(lpDest->pstm != NULL);
ASSERT(lpSource->pstm != NULL);
// get the size of the source stream
STATSTG stat;
if (lpSource->pstm->Stat(&stat, STATFLAG_NONAME) != S_OK)
{
// unable to get size of source stream
return FALSE;
}
ASSERT(stat.pwcsName == NULL);
// always seek to zero before copy
LARGE_INTEGER zero = { 0, 0 };
lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
// copy source to destination
if (lpSource->pstm->CopyTo(lpDest->pstm, stat.cbSize,
NULL, NULL) != NULL)
{
// copy from source to dest failed
return FALSE;
}
// always seek to zero after copy
lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
}
return TRUE;
case TYMED_ISTORAGE:
{
ASSERT(lpDest->pstg != NULL);
ASSERT(lpSource->pstg != NULL);
// just copy source to destination
if (lpSource->pstg->CopyTo(0, NULL, NULL, lpDest->pstg) != S_OK)
return FALSE;
}
return TRUE;
case TYMED_FILE:
{
USES_CONVERSION;
ASSERT(lpSource->lpszFileName != NULL);
ASSERT(lpDest->lpszFileName != NULL);
return CopyFile(OLE2T(lpSource->lpszFileName), OLE2T(lpDest->lpszFileName), FALSE);
}
case TYMED_ENHMF:
case TYMED_GDI:
{
ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
// with TYMED_GDI cannot copy into existing HANDLE
if (lpDest->hGlobal != NULL)
return FALSE;
// otherwise, use OleDuplicateData for the copy
lpDest->hGlobal = OleDuplicateData(lpSource->hGlobal, cfFormat, 0);
if (lpDest->hGlobal == NULL)
return FALSE;
}
return TRUE;
// other TYMEDs cannot be copied
default:
return FALSE;
}
}
/////////////////////////////////////////////////////////////////////////////
// OLE utility functions (some borrowed from OLE2UI library)
HGLOBAL AFXAPI _AfxOleGetObjectDescriptorData(
CLSID clsid,
DWORD dwDrawAspect,
SIZEL sizel,
POINTL pointl,
DWORD dwStatus,
LPCOLESTR lpszFullUserTypeName,
LPCOLESTR lpszSrcOfCopy)
{
HGLOBAL hMem = NULL;
LPOBJECTDESCRIPTOR lpOD;
DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
// Get the length of Full User Type Name; Add 1 for the null terminator
dwFullUserTypeNameLen = lpszFullUserTypeName ?
ocslen(lpszFullUserTypeName)+1 : 0;
// Get the Source of Copy string and it's length;
// Add 1 for the null terminator
if (lpszSrcOfCopy && lpszSrcOfCopy[0] != '\0')
dwSrcOfCopyLen = ocslen(lpszSrcOfCopy)+1;
else
{
// No src moniker so use user type name as source string.
lpszSrcOfCopy = lpszFullUserTypeName;
dwSrcOfCopyLen = dwFullUserTypeNameLen;
}
// Allocate space for OBJECTDESCRIPTOR and the additional string data
dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT,
dwObjectDescSize + (dwFullUserTypeNameLen + dwSrcOfCopyLen) *
sizeof(OLECHAR));
if (!hMem)
return NULL;
lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
// Set the FullUserTypeName offset and copy the string
if (lpszFullUserTypeName)
{
lpOD->dwFullUserTypeName = dwObjectDescSize;
ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName);
}
else
lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present
// Set the SrcOfCopy offset and copy the string
if (lpszSrcOfCopy)
{
lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen * sizeof(OLECHAR);
ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy);
}
else
lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present
// Initialize the rest of the OBJECTDESCRIPTOR
lpOD->cbSize = dwObjectDescSize +
(dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -