乌龟腹甲正常图片:如何实现菜单的拖拽

来源:百度文库 编辑:偶看新闻 时间:2024/05/05 16:43:26

如何实现菜单的拖拽

分类: 窗口界面&控件 2006-11-09 17:13 695人阅读 评论(1) 收藏 举报  为了让菜单支持拖拽,需要做:1、为菜单添加MNS_DRAGDROP风格MENUINFO Info ;Info.cbSize = sizeof(MENUINFO) ;Info.fMask = MIM_STYLE ;Info.dwStyle= MNS_DRAGDROP ;SetMenuInfo( hMenu , &Info ) ; 注:当WINVER>=0x500,才能找到NMS_DRAGDROP和下面相关常数的定义 2、处理WM_MENUDRAG消息其中, wParam 指定被拖拽菜单项的位置,lParam为菜单的句柄。返回值如果是MND_CONTINUE,则菜单仍然激活,如果鼠标被释放,它将被忽略!
就是说不实现拖拽功能,使用默认的处理方式!如果是MND_ENDMENU,则菜单将关闭。要实现拖拽,要返回该值! 重点在于,在WM_MENUDRAG内要启动拖操作,这里我使用了OLE拖-放传输协议,即调用 DoDragDrop : -          分配内存,大小是256字节。空间的大小要根据实际情况来定!
HGLOBAL hGlobal = ::GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT , 256 ) ;

-          将需的数据保存到分配的内存中,这里我将保存菜单的文本
LPVOID pvoid = ::GlobalLock( hGlobal ) ;LPTSTR lpstr = (LPTSTR)pvoid ;::GetMenuString( hMenu , pos , lpstr , MAX_PATH - 1 , MF_BYPOSITION ) ;::GlobalUnlock( hGlobal ) ;
注:hMenu 来自 lParam , pos 来自 wParam  -          准备IDataObject、IDropSource对象
STGMEDIUM stgMedium ;memset( &stgMedium , 0 , sizeof(STGMEDIUM) ) ;stgMedium.tymed = TYMED_HGLOBAL ;stgMedium.hGlobal = hGlobal ;stgMedium.pUnkForRelease = NULL ; CMenuDataObject *pDataObj = new CMenuDataObject (&stgMedium,m_uClipboardFormat);              CMenuDropSource *pDropSource = new CMenuDropSource ;              pDropSource->AddRef() ;pDataObj->AddRef() ;               注:CMenuDataObject 派生自 IDataObject ; CMenuDropSource 派生自 IDropSource m_uClipboardFormat 是自定义的数据格式,为了能区分出自已的数据。m_uClipboardFormat= RegisterClipboardFormat( “MyFormat” ) ;这里比较麻烦的是CMenuDataObjectCmenuDropSource实现,其不在本文的讨论范围,请参考相关资料,MSDN的例子等。http://www.cppblog.com/windcsn/category/995.html drag&drop 也要比较
详细的描述。
  
  -          调用DoDragDrop 启动拖操作         DWORD dwEffect = 0 ;HRESULT ret = ::DoDragDrop( pDataObj , pDropSource , DROPEFFECT_MOVE , &dwEffect );                     pDropSource->Release() ;pDataObj->Release() ;                 - 检查返回值,释放资源                     if( ret == DROPEFFECT_MOVE ){::GlobalFree( hGlobal ) ;return MND_ENDMENU ;}  注:如果你用MFC,这一切将变得很简单,IDataObjectIDataSource都由MFC实现:COleDataSource *pSource = new COleDataSource ;pSource->CacheData( (CLIPFORMAT)m_uClipboardFormat , &stgMedium ) ;     DROPEFFECT ret = DROPEFFECT_NONE ;ret = pSource->DoDragDrop( DROPEFFECT_MOVE ) ;   3、实现接收功能为了接收数据对象即支持“放”特性,它必须提供一个“放目标”对象。“放目标”
对象实现了接口IDropTarget,并且目标程序还必须把“放目标”对象与一个窗口联系在一起。因此,应用程序为了支持“放”特性,要调用OLE提供的API函数:RegisterDragDrop,当程序不再支持“放”特性,则可以调用RevokeDrapDrop函数取消。 OnCreate{… 窗口初始化RegisterDragDrop( m_hWnd , &m_DropTarget ) ;
} class CMyDropTarget : public IDropTarget ;CMyDropTarget m_DropTarget ; 因此,工作重点,就是实现 IDropTarget 。如果用MFC,可以让CMyDropTarget派生自COleDropTarget 。CMyDropTarget实现不在本文讨论范围,请参考相关资料。