2025-11-27 16:46:48 +09:00

234 lines
6.2 KiB
C++

// ==========================================================================
// Class Implementation : COXDragDropCommands
// ==========================================================================
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "OXDragDropCommands.h"
#include "OXBitmapMenuOrganizer.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// format for drag'n'drop item
CLIPFORMAT COXDragDropCommands::m_cfCommandButton=
(CLIPFORMAT)::RegisterClipboardFormat(_T("UTB_Command_Button"));
COleDataSource* COXDragDropCommands::PrepareDragDropData(LPCTSTR lpszText,
int nImageIndex,
int nCommandID,
BYTE fsStyle/*=0*/,
HMENU hSubmenu/*=NULL*/)
{
ASSERT(lpszText!=NULL);
// allocate our data object
COleDataSource* pDataSource=new COleDataSource;
//////////////////////
// internal m_cfCommandButton format
//
// command ID + (text) + (NULL) + image index + button style +
// if finished - 0
// otherwise - 1 if next item in menu
// 2 if previous one is the last in hierarchy +
// command ID + (text) + (NULL) + image index + button style + ...
//////////////////////
int nEntryMemSize=(lstrlen(lpszText)+1)*sizeof(TCHAR)+3*sizeof(int)+sizeof(BYTE);
if(hSubmenu!=NULL)
{
nEntryMemSize+=CalcMenuDataSize(hSubmenu);
}
// allocate the memory
HGLOBAL hgItemData=::GlobalAlloc(GPTR,nEntryMemSize);
BYTE* lpItemData=(BYTE*)GlobalLock(hgItemData);
::ZeroMemory(lpItemData,nEntryMemSize);
// if image hasn't been specified and item is not a popup menu
// the we wil try to find out if there is image assigned to the
// item by COXBitmapMenuOrganizer object
if(nCommandID!=-1 && nImageIndex==-1)
{
COXBitmapMenuOrganizer* pBMOrganizer=
COXBitmapMenuOrganizer::FindOrganizer(AfxGetMainWnd()->GetSafeHwnd());
if(pBMOrganizer!=NULL)
{
COXImageInfo* pImageInfo=pBMOrganizer->GetMenuItemImageInfo(nCommandID);
if(pImageInfo!=NULL)
{
nImageIndex=pImageInfo->GetIndex();
}
}
}
WriteItemDragDropData(lpItemData,lpszText,nImageIndex,nCommandID,fsStyle);
if(hSubmenu!=NULL)
{
lpItemData-=sizeof(int);
(*(int*)lpItemData)=2;
lpItemData+=sizeof(int);
WriteMenuDragDropData(lpItemData,hSubmenu);
}
lpItemData-=sizeof(int);
(*(int*)lpItemData)=0;
lpItemData+=sizeof(int);
::GlobalUnlock(hgItemData);
// save the item data
pDataSource->CacheGlobalData(m_cfCommandButton,hgItemData);
return pDataSource;
}
DROPEFFECT COXDragDropCommands::DoDragDrop(COleDataSource* pDataSource,
COleDropSource* pOleDropSource)
{
ASSERT(pDataSource!=NULL);
ASSERT(pOleDropSource!=NULL);
// start drag'n'drop operation
return pDataSource->DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE,
NULL,pOleDropSource);
}
int COXDragDropCommands::CalcMenuDataSize(HMENU hMenu)
{
ASSERT(hMenu!=NULL);
ASSERT(::IsMenu(hMenu));
int nSize=0;
CMenu* pMenu=CMenu::FromHandle(hMenu);
COXBitmapMenu* pBitmapMenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pMenu);
int nItemCount=pMenu->GetMenuItemCount();
for(int nIndex=0; nIndex<nItemCount; nIndex++)
{
CString sText;
if(pBitmapMenu!=NULL)
{
MENUITEMINFO mii={ sizeof(MENUITEMINFO) };
mii.fMask=MIIM_DATA;
#if _MFC_VER > 0x0421
VERIFY(pBitmapMenu->GetMenuItemInfo(nIndex,&mii,TRUE));
#else
VERIFY(::GetMenuItemInfo(pBitmapMenu->m_hMenu,nIndex,TRUE,&mii));
#endif
COXItemInfo* pItemInfo=(COXItemInfo*)mii.dwItemData;
ASSERT(pItemInfo!=NULL);
sText=pItemInfo->GetText();
}
else
{
pMenu->GetMenuString(nIndex,sText,MF_BYPOSITION);
}
nSize+=sText.GetLength()+sizeof(TCHAR)+3*sizeof(int)+sizeof(BYTE);
if(pMenu->GetMenuItemID(nIndex)==(UINT)-1)
{
nSize+=CalcMenuDataSize(pMenu->GetSubMenu(nIndex)->GetSafeHmenu());
}
}
return nSize;
}
void COXDragDropCommands::WriteItemDragDropData(BYTE*& lpData, LPCTSTR lpszText,
int nImageIndex, int nCommandID,
BYTE fsStyle)
{
ASSERT(lpData!=NULL);
// write button command ID into global memory
(*(int*)lpData)=nCommandID;
lpData+=sizeof(int);
// write button text into global memory
lstrcpy((LPTSTR)lpData,lpszText);
lpData+=(lstrlen(lpszText)+1)*sizeof(TCHAR);
// write button image index into global memory
(*(int*)lpData)=nImageIndex;
lpData+=sizeof(int);
// write button style into global memory
(*(BYTE*)lpData)=fsStyle;
lpData+=sizeof(BYTE);
// finish flag set to FALSE
(*(int*)lpData)=1;
lpData+=sizeof(int);
}
void COXDragDropCommands::WriteMenuDragDropData(BYTE*& lpData, HMENU hMenu)
{
ASSERT(lpData!=NULL);
ASSERT(hMenu!=NULL);
ASSERT(::IsMenu(hMenu));
CMenu* pMenu=CMenu::FromHandle(hMenu);
COXBitmapMenu* pBitmapMenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pMenu);
int nItemCount=pMenu->GetMenuItemCount();
for(int nIndex=0; nIndex<nItemCount; nIndex++)
{
CString sText;
if(pBitmapMenu!=NULL)
{
MENUITEMINFO mii={ sizeof(MENUITEMINFO) };
mii.fMask=MIIM_DATA;
#if _MFC_VER > 0x0421
VERIFY(pBitmapMenu->GetMenuItemInfo(nIndex,&mii,TRUE));
#else
VERIFY(::GetMenuItemInfo(pBitmapMenu->m_hMenu,nIndex,TRUE,&mii));
#endif
COXItemInfo* pItemInfo=(COXItemInfo*)mii.dwItemData;
ASSERT(pItemInfo!=NULL);
sText=pItemInfo->GetText();
}
else
{
pMenu->GetMenuString(nIndex,sText,MF_BYPOSITION);
}
WriteItemDragDropData(lpData,sText,-1,pMenu->GetMenuItemID(nIndex),0);
if(nIndex==nItemCount-1)
{
lpData-=sizeof(int);
(*(int*)lpData)=2;
lpData+=sizeof(int);
}
if(pMenu->GetMenuItemID(nIndex)==(UINT)-1)
{
WriteMenuDragDropData(lpData,pMenu->GetSubMenu(nIndex)->GetSafeHmenu());
}
}
}