note : append menu to menu on right click menu
来源:互联网 发布:知乎首页代码 编辑:程序博客网 时间:2024/05/22 01:36
今天想实现一个右键菜单出现时,出现的总菜单 = 公用菜单(编辑类的功能) + 具体菜单每个View一个特定菜单)
从CodeProject上找了一个函数MergeMenu, 搞定.
bool MergeMenu( CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel);效果图:
附件菜单到菜单的实现
基类View
#pragma once// CViewNormal viewclass CViewNormal : public CView{ DECLARE_DYNCREATE(CViewNormal)protected: CViewNormal(); virtual ~CViewNormal();public: virtual void OnDraw(CDC* pDC); void SetName(wchar_t * pName); /// 在pMenuOrg基础上,加上功能菜单 virtual void AppendFunctionMenu(CMenu * pMenuOrg); /// 在pMenuOrg上附加"菜单资源ID"为 nMenuIDRc 的子菜单 /// 只有子类知道具体要附加什么子菜单 /// 子类实现虚函数 AppendFunctionMenu /// 调用AppendFunctionMenuID, 附加自己的子菜单 void AppendFunctionMenuID(CMenu * pMenuOrg, UINT nMenuIDRc); bool MergeMenu( CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel); /// 显示区重置 void fnDispAreaReset();protected: void WriteToRichEditCtrl(const wchar_t * szMsg);#ifdef _DEBUG virtual void AssertValid() const;#ifndef _WIN32_WCE virtual void Dump(CDumpContext& dc) const;#endif // #ifndef _WIN32_WCE#endif // #ifdef _DEBUGprotected: DECLARE_MESSAGE_MAP()public: virtual void OnInitialUpdate(); virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); afx_msg void OnDestroy(); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); LRESULT OnEditCut(WPARAM wparam, LPARAM lparam); LRESULT OnEditCopy(WPARAM wparam, LPARAM lparam); LRESULT OnEditPaste(WPARAM wparam, LPARAM lparam); LRESULT OnEditSelectAll(WPARAM wparam, LPARAM lparam); LRESULT OnEditDispAreaReset(WPARAM wparam, LPARAM lparam);private: CString m_strName; CRichEditCtrl m_RichEdit;};
// ViewNormal.cpp : implementation file//#include "stdafx.h"#include "MainFrm.h"#include <afxpriv.h>#include <stdio.h>#include "srcR3.h"#include "ViewNormal.h"#include "string/stringHelper.h"// CViewNormalIMPLEMENT_DYNCREATE(CViewNormal, CView)CViewNormal::CViewNormal(){ m_strName = L"";}CViewNormal::~CViewNormal(){}/// @attention ON_MESSAGE 才能响应控件的右键菜单!BEGIN_MESSAGE_MAP(CViewNormal, CView) ON_WM_CREATE() ON_WM_DESTROY() ON_MESSAGE(ID_EDIT_CUT_ON_EDIT_CTRL, OnEditCut) ON_MESSAGE(ID_EDIT_COPY_ON_EDIT_CTRL, OnEditCopy) ON_MESSAGE(ID_EDIT_PASTE_ON_EDIT_CTRL, OnEditPaste) ON_MESSAGE(ID_EDIT_SEL_ALL_ON_EDIT_CTRL, OnEditSelectAll) ON_MESSAGE(ID_EDIT_DISP_AREA_RESET_ON_EDIT_CTRL, OnEditDispAreaReset)END_MESSAGE_MAP()void CViewNormal::DoDataExchange(CDataExchange* pDX){ CView::DoDataExchange(pDX);}// CViewNormal drawingvoid CViewNormal::OnDraw(CDC* pDC){ CDocument* pDoc = GetDocument(); pDC->TextOutW(10, 10, m_strName);}// CViewNormal diagnostics#ifdef _DEBUGvoid CViewNormal::AssertValid() const{CView::AssertValid();}#ifndef _WIN32_WCEvoid CViewNormal::Dump(CDumpContext& dc) const{CView::Dump(dc);}#endif#endif //_DEBUGvoid CViewNormal::SetName(wchar_t * pName){ m_strName = (NULL != pName) ? pName : L"I have not name";}void CViewNormal::AppendFunctionMenu(CMenu * pMenuOrg){ TRACE(L">> CViewNormal::AppendFunctionMenu");}// CViewNormal message handlersint CViewNormal::OnCreate(LPCREATESTRUCT lpCreateStruct){ DWORD dwStyle = 0; if (CView::OnCreate(lpCreateStruct) == -1) return -1; dwStyle = WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_AUTOHSCROLL | ES_MULTILINE | WS_HSCROLL | WS_VSCROLL; if (!m_RichEdit.Create( dwStyle, CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST)) { TRACE0("Failed to create RichEdit window\n"); return -1; } /// 将鼠标消息送给父窗口 /// @note 不设置这个, 进不了CRichEditCtrl控件父窗口的OnNotify m_RichEdit.SetEventMask(ENM_MOUSEEVENTS); /// 设置选择范围为不选择内容 m_RichEdit.SetSel(0,0); return 0;}void CViewNormal::OnInitialUpdate(){ CRect rt; CString strMsg; CView::OnInitialUpdate(); /// 将控件铺满View客户区 /// 如果要在这个view中放置别的控件, 请不要铺满, 自己来摆放控件位置 GetClientRect(&rt); m_RichEdit.MoveWindow(rt); fnDispAreaReset();}void CViewNormal::OnDestroy(){ m_RichEdit.DestroyWindow(); CView::OnDestroy();}BOOL CViewNormal::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo){ return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);}LRESULT CViewNormal::OnEditCut(WPARAM wparam, LPARAM lparam){ TRACE(L">> CViewNormal::OnEditCut\r\n"); m_RichEdit.Cut(); return 0;}LRESULT CViewNormal::OnEditCopy(WPARAM wparam, LPARAM lparam){ TRACE(L">> CViewNormal::OnEditCopy\r\n"); m_RichEdit.Copy(); return 0;}LRESULT CViewNormal::OnEditPaste(WPARAM wparam, LPARAM lparam){ TRACE(L">> CViewNormal::OnEditPaste\r\n"); m_RichEdit.Paste(); return 0;}LRESULT CViewNormal::OnEditSelectAll(WPARAM wparam, LPARAM lparam){ TRACE(L">> CViewNormal::OnEditSelectAll\r\n"); m_RichEdit.SetSel(0, -1); return 0;}LRESULT CViewNormal::OnEditDispAreaReset(WPARAM wparam, LPARAM lparam){ fnDispAreaReset(); return 0;}void CViewNormal::WriteToRichEditCtrl(const wchar_t * szMsg){ int nOldLines = 0; int nNewLines = 0; int nScroll = 0; long nInsertionPoint = 0; CHARFORMAT cf; nOldLines = m_RichEdit.GetLineCount(); cf.cbSize = sizeof(CHARFORMAT); cf.dwMask = CFM_COLOR; cf.dwEffects = 0; ///< To disable CFE_AUTOCOLOR cf.crTextColor = RGB(128, 128, 128); m_RichEdit.SetSelectionCharFormat(cf); nInsertionPoint = m_RichEdit.GetWindowTextLength(); m_RichEdit.SetSel(nInsertionPoint, -1); m_RichEdit.ReplaceSel(szMsg); nNewLines = m_RichEdit.GetLineCount(); nScroll = nNewLines - nOldLines; m_RichEdit.LineScroll(nScroll);}void CViewNormal::fnDispAreaReset(){ std::wstring strMsg; TRACE(L">> CViewNormal::OnEditDispAreaReset\r\n"); m_RichEdit.SetSel(0, -1); m_RichEdit.Cut(); strMsg = StringFormatV( L"[%s]\r\n" L"%s\r\n", m_strName, COleDateTime::GetCurrentTime().Format(L"%y-%m-%d %H:%M:%S")); WriteToRichEditCtrl(strMsg.c_str());}BOOL CViewNormal::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult){ BOOL bRc = TRUE; CString csMsg; UINT uMessage = 0; MSGFILTER * lpMsgFilter = (MSGFILTER *)lParam; CPoint point; CMenu menu; CMenu * pMenuPopup = NULL; CMainFrame * pMainFrame = NULL; HWND hWndObj = NULL; if ((AFX_IDW_PANE_FIRST == wParam) && (EN_MSGFILTER == lpMsgFilter->nmhdr.code) && (WM_RBUTTONDOWN == lpMsgFilter->msg)) { /// View中的RichEdit, 右键按下, 准备弹出菜单 ::GetCursorPos(&point); menu.LoadMenu(IDR_MENU_RIGHT_CLICK); ///< 公用菜单 pMenuPopup = menu.GetSubMenu(0); ASSERT(NULL != pMenuPopup); /// 附加每个View特有的功能菜单 /// 虚函数, 由子类实现 AppendFunctionMenu(pMenuPopup); uMessage = pMenuPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, this); pMenuPopup->DestroyMenu(); bRc = PostMessage(uMessage, 0, 0); TRACE(L"<< %s = PostMessage(0x%X, 0, 0)\r\n", bRc ? L"TRUE" : L"FALSE", uMessage); } return CView::OnNotify(wParam, lParam, pResult);}void CViewNormal::AppendFunctionMenuID(CMenu * pMenuOrg, UINT nMenuIDRc){ CMenu menuToBeAdd; CMenu * pMenuToBeAdd = NULL; menuToBeAdd.LoadMenu(nMenuIDRc); pMenuToBeAdd = menuToBeAdd.GetSubMenu(0); ASSERT(NULL != pMenuToBeAdd); MergeMenu(pMenuOrg, pMenuToBeAdd, false); pMenuToBeAdd->DestroyMenu();}bool CViewNormal::MergeMenu(CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel){ // MergeMenu original url from : // http://www.codeproject.com/Articles/1577/Merging-Two-Menus# // Abstract: // Merges two menus. // // Parameters: // pMenuDestination - [in, retval] destination menu handle // pMenuAdd - [in] menu to merge // bTopLevel - [in] indicator for special top level behavior // // Return value: // <false> in case of error. // // Comments: // This function calles itself recursivley. If bTopLevel is set to true, // we append popups at top level or we insert before <Window> or <Help>. // get the number menu items in the menus int iMenuAddItemCount = pMenuAdd->GetMenuItemCount(); int iMenuDestItemCount = pMenuDestination->GetMenuItemCount(); // if there are no items return if( iMenuAddItemCount == 0 ) return true; // if we are not at top level and the destination menu is not empty // -> we append a seperator if( !bTopLevel && iMenuDestItemCount > 0 ) pMenuDestination->AppendMenu(MF_SEPARATOR); // iterate through the top level of <pMenuAdd> for( int iLoop = 0; iLoop < iMenuAddItemCount; iLoop++ ) { // get the menu string from the add menu CString sMenuAddString; pMenuAdd->GetMenuString( iLoop, sMenuAddString, MF_BYPOSITION ); // try to get the submenu of the current menu item CMenu* pSubMenu = pMenuAdd->GetSubMenu(iLoop); // check if we have a sub menu if (!pSubMenu) { // normal menu item // read the source and append at the destination UINT nState = pMenuAdd->GetMenuState( iLoop, MF_BYPOSITION ); UINT nItemID = pMenuAdd->GetMenuItemID( iLoop ); if( pMenuDestination->AppendMenu( nState, nItemID, sMenuAddString )) { // menu item added, don't forget to correct the item count iMenuDestItemCount++; } else { TRACE( "MergeMenu: AppendMenu failed!\n" ); return false; } } else { // create or insert a new popup menu item // default insert pos is like ap int iInsertPosDefault = -1; // if we are at top level merge into existing popups rather than // creating new ones if( bTopLevel ) { ASSERT( sMenuAddString != "&?" && sMenuAddString != "?" ); CString sAdd( sMenuAddString ); sAdd.Remove('&'); // for comparison of menu items supress '&' bool bAdded = false; // try to find existing popup for( int iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ ) { // get the menu string from the destination menu CString sDest; pMenuDestination->GetMenuString( iLoop1, sDest, MF_BYPOSITION ); sDest.Remove( '&' ); // for a better compare (s.a.) if( sAdd == sDest ) { // we got a hit -> merge the two popups // try to get the submenu of the desired destination menu item CMenu* pSubMenuDest = pMenuDestination->GetSubMenu( iLoop1 ); if( pSubMenuDest ) { // merge the popup recursivly and continue with outer for loop if( !MergeMenu( pSubMenuDest, pSubMenu, false)) return false; bAdded = true; break; } } // alternativ insert before <Window> or <Help> if( iInsertPosDefault == -1 && ( sDest == "Window" || sDest == "?" || sDest == "Help" )) iInsertPosDefault = iLoop1; } if( bAdded ) { // menu added, so go on with loop over pMenuAdd's top level continue; } } // if the top level search did not find a position append the menu if( iInsertPosDefault == -1 ) iInsertPosDefault = pMenuDestination->GetMenuItemCount(); // create a new popup and insert before <Window> or <Help> CMenu NewPopupMenu; if( !NewPopupMenu.CreatePopupMenu() ) { TRACE( "MergeMenu: CreatePopupMenu failed!\n" ); return false; } // merge the new popup recursivly if( !MergeMenu( &NewPopupMenu, pSubMenu, false)) return false; // insert the new popup menu into the destination menu HMENU hNewMenu = NewPopupMenu.GetSafeHmenu(); if( pMenuDestination->InsertMenu( iInsertPosDefault, MF_BYPOSITION | MF_POPUP | MF_ENABLED, (UINT)hNewMenu, sMenuAddString )) { // don't forget to correct the item count iMenuDestItemCount++; } else { TRACE( "MergeMenu: InsertMenu failed!\n" ); return false; } // don't destroy the new menu NewPopupMenu.Detach(); } } return true;}
子类View
#pragma once#include "ViewNormal.h"// CViewDrvManager viewclass CViewDrvManager : public CViewNormal{DECLARE_DYNCREATE(CViewDrvManager)protected:CViewDrvManager(); // protected constructor used by dynamic creationvirtual ~CViewDrvManager(); virtual void AppendFunctionMenu(CMenu * pMenuOrg);public:virtual void OnDraw(CDC* pDC); // overridden to draw this view#ifdef _DEBUGvirtual void AssertValid() const;#ifndef _WIN32_WCEvirtual void Dump(CDumpContext& dc) const;#endif#endifprotected:DECLARE_MESSAGE_MAP()public: LRESULT OnViewLsMiniFilterInstall(WPARAM wparam, LPARAM lparam); LRESULT OnViewLsMiniFilterRun(WPARAM wparam, LPARAM lparam); LRESULT OnViewLsMiniFilterStop(WPARAM wparam, LPARAM lparam); LRESULT OnViewLsMiniFilterUnInstall(WPARAM wparam, LPARAM lparam);};
// ViewDrvManager.cpp : implementation file//#include "stdafx.h"#include "srcR3.h"#include "ViewDrvManager.h"#include "TreeViewNormal.h"// CViewDrvManagerIMPLEMENT_DYNCREATE(CViewDrvManager, CViewNormal)CViewDrvManager::CViewDrvManager(){}CViewDrvManager::~CViewDrvManager(){}BEGIN_MESSAGE_MAP(CViewDrvManager, CViewNormal) ON_MESSAGE(ID_IDR_LSMINIFILTER_INSTALL, OnViewLsMiniFilterInstall) ON_MESSAGE(ID_IDR_LSMINIFILTER_RUN, OnViewLsMiniFilterRun) ON_MESSAGE(ID_IDR_LSMINIFILTER_STOP, OnViewLsMiniFilterStop) ON_MESSAGE(ID_IDR_LSMINIFILTER_UNINSTALL, OnViewLsMiniFilterUnInstall)END_MESSAGE_MAP()// CViewDrvManager drawingvoid CViewDrvManager::OnDraw(CDC* pDC){CDocument* pDoc = GetDocument();// TODO: add draw code here}// CViewDrvManager diagnostics#ifdef _DEBUGvoid CViewDrvManager::AssertValid() const{CView::AssertValid();}#ifndef _WIN32_WCEvoid CViewDrvManager::Dump(CDumpContext& dc) const{CView::Dump(dc);}#endif#endif //_DEBUG// CViewDrvManager message handlersvoid CViewDrvManager::AppendFunctionMenu(CMenu * pMenuOrg){ AppendFunctionMenuID(pMenuOrg, IDR_MENU_DRV_MANAGER);}LRESULT CViewDrvManager::OnViewLsMiniFilterInstall(WPARAM wparam, LPARAM lparam){ WriteToRichEditCtrl(L"CViewDrvManager::OnViewLsMiniFilterInstall\r\n"); return 0;}LRESULT CViewDrvManager::OnViewLsMiniFilterRun(WPARAM wparam, LPARAM lparam){ WriteToRichEditCtrl(L"CViewDrvManager::OnViewLsMiniFilterRun\r\n"); return 0;}LRESULT CViewDrvManager::OnViewLsMiniFilterStop(WPARAM wparam, LPARAM lparam){ WriteToRichEditCtrl(L"CViewDrvManager::OnViewLsMiniFilterStop\r\n"); return 0;}LRESULT CViewDrvManager::OnViewLsMiniFilterUnInstall(WPARAM wparam, LPARAM lparam){ WriteToRichEditCtrl(L"CViewDrvManager::OnViewLsMiniFilterUnInstall\r\n"); return 0;}
- note : append menu to menu on right click menu
- note : CRichEdit right click menu on CView
- Right Click Menu Lag on my pc
- How to add application to right click menu in Windows
- hiho1088 Right-click Context Menu 递归 贪心
- hihocder 1088 : Right-click Context Menu
- Menu
- Menu
- menu
- menu
- menu
- Menu
- MENU
- menu
- menu
- Menu
- Menu
- menu
- cocos2d-x 内存管理链接
- 正则表达式的使用及一些符号的意思
- 时间段时间控件
- 经典vim插件功能说明、安装方法和使用方法介绍(已更新)
- IOS 打电话_Email_SMS_Safari
- note : append menu to menu on right click menu
- 黑马程序员--基础学习总结之集合
- 反射中方法的获取和执行
- 隐马尔可夫模型(HMM)攻略
- java环境配置
- (step3.1.3)hdu 2046(骨牌铺方格)
- 原生Javascript操作DOM的一些常用方法集合
- Apache负载均衡的三大规则
- 追寻我的梦