王朝网络
分享
 
 
 

如何实现菜单的拖拽

王朝other·作者佚名  2006-11-22
宽屏版  字体: |||超大  

为了让菜单支持拖拽,需要做:

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” ) ;

这里比较麻烦的是CMenuDataObject和CmenuDropSource实现,其不

在本文的讨论范围,请参考相关资料,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,这一切将变得很简单,IDataObject和IDataSource都由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实现不在本文讨论范围,请参考相关资料。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有