首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > 如何实现菜单的拖拽
【标  题】:如何实现菜单的拖拽
【关键字】:
【来  源】:http://blog.csdn.net/lbird/archive/2006/11/09/1375887.aspx

如何实现菜单的拖拽

 
为了让菜单支持拖拽,需要做:
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实现不在本文讨论范围,请参考相关资料。


 
autodesk校园招聘的一道题目——判定BST:【上一篇】
WINDOWS XP sp2 Platfrom SDK下载地址:【下一篇】
【相关文章】
没有相关文章
【随机文章】
  • 关于#include的补充说明
  • Linux环境下的嗅探器
  • XPath序列之四
  • C#中操作Excel的方法(一)
  • open打开文件
  • windows2003+oracle ofs 双机
  • Dreamweaver 4 简明教程(三、制作前的准备工作——定义网站)
  • 管理中的帕金森定律
  • 创建一个基于模板的数据库记录集操作类(一)
  • Visual Studio 2005开发资料
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.