野狼地带分享 http://blog.sciencenet.cn/u/huguanhu 踏实做人,认真做事。

博文

一个在AutoCAD里添加菜单的类,用COM接口实现(转载)

已有 4926 次阅读 2009-11-10 12:06 |个人分类:生活点滴|系统分类:科研笔记|关键词:菜单,com,autocad| AutoCAD, 菜单, com

AddCADFrameMenu.h文件如下:

/*-------------------------------------------------------------------------
作者: Racky Ye
该类封装了在AuToCAD上添加菜单及子菜单的方法,使用COM接口实现
大家可以任意修改,添加新功能,希望大家能多交流
Email: yeguixi@126.com 
--------------------------------------------------------------
 使用方法:
CAddCADFrameMenu menu;
menu.AddMenu("我的菜单");
menu.AddSubMenu("弹出对话框", "_DLG ");
menu.AddSubMenu("绘制线条", "_DRAWL ");
menu.AddSubMenu("*Line");// 加"*"号表示是二级子菜单
menu.AddSubMenu("$CIRCLE", "_CIRCLE ");//加"$"号表示二级子菜单下的菜单条
menu.AddSubSeparator();
menu.AddSubMenu("$PLINE", "_PLINE ");//加"$"号表示二级子菜单下的菜单条
menu.AddSeparator();
menu.AddSubMenu("选择文件夹", "_SELFOLDER ");
menu.AddSubMenu("*TEXT");// 加"*"号表示是二级子菜单
menu.AddSubMenu("$MTEXT", "_TEXT ");//加"$"号表示二级子菜单下的菜单条
menu.CreateMenus();
--------------------------------------------------------------
----------------------------------------------------------------------------
*/


#if !defined(AFX_ADDCADFRAMEMENU_H__153847F5_DE2C_4B6E_83E8_5BE9FE780CD8__INCLUDED_)
#define AFX_ADDCADFRAMEMENU_H__153847F5_DE2C_4B6E_83E8_5BE9FE780CD8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include 
<afxtempl.h>
#include 
"acad15.h"

 

typedef 
struct CADMenu
{
 
char name[64];
 
char order[64];
}
CADMenu;


class CAddCADFrameMenu  
{
public:
 CAddCADFrameMenu();
 
virtual ~CAddCADFrameMenu();

 
// 创建菜单
 void CreateMenus();
 
// 添加菜单
 void AddMenu(const char* menuName);
 
// 添加子菜单,menuName-菜单名"--"为分隔符,command要加空格
 void AddSubMenu(const char* menuName, const char* command=NULL);
 
// 添加分隔符
 void AddSeparator();
 
// 添加二级子菜单分隔符
 void AddSubSeparator();

 
static bool IsMenuExist(IAcadPopupMenu *&pMnu,long &index,const char *mnuname,IAcadPopupMenus *mnus);//菜单是否存在,避免二次加载 add by zhengzhilin
 static bool GetAcadApplication(IAcadApplication *&pAcadApp);
 
static bool GetAcadMenuGroup(IAcadMenuGroup  **pVal,LPCTSTR menuname);
 
static bool GetLastMenuFromMenubar(CString &sMenu);
 
static void ClearMenu(IAcadPopupMenus *mnus,LPCTSTR menuname);
 
static bool GetAcadApplication(LPDISPATCH * pVal);
 
static bool GetAcadMenuGroup(IAcadMenuGroup  **pVal);
 
static void CleanUpMenus(); //创建了Menu一定要调用这个函数

private:

 
class CCADMenuArray : public CArray <CADMenu*, CADMenu*>
 
{
 
public:
  
int AddMenu(CADMenu& menu);
  
int AddMenu(const char* menuName, const char* command);
  
~CCADMenuArray();
 }
;
 
 CArray 
<CCADMenuArray*, CCADMenuArray*> m_menus;
 
int m_menuCount;  // 菜单个数

 CStringArray m_TopMenuNames; 
// 菜单名


}
;

#endif // !defined(AFX_ADDCADFRAMEMENU_H__153847F5_DE2C_4B6E_83E8_5BE9FE780CD8__INCLUDED_)

AddCADFrameMenu.cpp文件如下:

/*-------------------------------------------------------------------------
作者:Racky Ye
该类封装了在AuToCAD上添加菜单及子菜单的方法,使用COM接口实现
大家可以任意修改,添加新功能,希望大家能多交流
Email: yeguixi@126.com 
--------------------------------------------------------------
*/


#include 
"stdafx.h"
#include 
"resource.h"
#include 
"AddCADFrameMenu.h"
#include 
"acad15_i.c"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

static CStringArray stcMyTopMenuNames;//存储新添加的CAD顶级菜单项名称

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAddCADFrameMenu::CAddCADFrameMenu()
{
 m_menuCount 
= 0;
 m_TopMenuNames.RemoveAll();
}


CAddCADFrameMenu::
~CAddCADFrameMenu()
{
 
int num = m_menus.GetSize();
 
for (int i=0; i<num; i++{
  
if (m_menus.GetAt(i) != NULL) 
   delete m_menus[i];
 }

}


int CAddCADFrameMenu::CCADMenuArray::AddMenu(CADMenu& menu)
{
 CADMenu
* pMenu = new CADMenu;
 sprintf(pMenu
->name, menu.name);
 sprintf(pMenu
->order, menu.order);
 
return Add(pMenu);
}


int CAddCADFrameMenu::CCADMenuArray::AddMenu(const char* menuName, const char* command)
{
 
if (sizeof(menuName) > 63{
#ifdef _DEBUG
  acutPrintf(
"menuName'%s'长度超出范围 ", menuName);
#endif  
  
return -99
 }

 
if (sizeof(command) > 63{
#ifdef _DEBUG
  acutPrintf(
"command'%s'长度超出范围 ", command);
#endif  
  
return -99
 }

 
 CADMenu
* pMenu = new CADMenu;
 sprintf(pMenu
->name, menuName);
 
if (command != NULL)
  sprintf(pMenu
->order, command);
 
return Add(pMenu); 
}


CAddCADFrameMenu::CCADMenuArray::
~CCADMenuArray()
{
 
for (int i=0; i<m_nSize; i++{
  
if (GetAt(i) != NULL) {
   delete GetAt(i);
  }

 }
 
}


void CAddCADFrameMenu::AddSubMenu(const char* menuName, 
          
const char* command)
{
 RXASSERT(menuName 
!= NULL);
 
if (m_menuCount == 0{
#ifdef _DEBUG
  acutPrintf(
"添加子菜单%s前没有调用AddMenu添加一个菜单条目!无法添加子菜单 ", menuName);
#endif
  
return;
 }

 m_menus[m_menuCount
-1]->AddMenu(menuName, command);
}


void CAddCADFrameMenu::AddSeparator()
{
 m_menus[m_menuCount
-1]->AddMenu("--""");
}


void CAddCADFrameMenu::AddSubSeparator()
{
 m_menus[m_menuCount
-1]->AddMenu("$--""");
}


void CAddCADFrameMenu::AddMenu(const char* menuName)
{
 m_TopMenuNames.Add(menuName);
 CCADMenuArray
* pArr = new CCADMenuArray;
 m_menuCount 
= m_menus.Add(pArr) + 1;
}


bool CAddCADFrameMenu::GetAcadApplication(LPDISPATCH * pVal)

 LPDISPATCH pDispatch 
= acedGetAcadWinApp()->GetIDispatch(TRUE);
 
if (pDispatch == NULL)
  
return false;
 
*pVal = pDispatch;
 
return true;
}


bool CAddCADFrameMenu::GetAcadApplication(IAcadApplication *&pAcadApp)
{
 LPDISPATCH  pDisp 
= NULL;
 
 
if (!GetAcadApplication(&pDisp))
  
return false;
 
 HRESULT hr 
= S_OK;
 hr 
= pDisp->QueryInterface(IID_IAcadApplication, (LPVOID*)&pAcadApp);
 
if (FAILED(hr))
  
return false;

 
return true;
}


bool CAddCADFrameMenu::GetLastMenuFromMenubar(CString &sMenu)
{
 IAcadApplication 
*pAcad = NULL;
 
if(!GetAcadApplication(pAcad))
  
return false;

 IAcadMenuBar 
*pMenuBar=NULL;
 IAcadPopupMenu  
*pPopUpMenu=NULL;
 
 pAcad
->get_MenuBar(&pMenuBar);
    pAcad
->Release();
    
long numberOfMenus;
    pMenuBar
->get_Count(&numberOfMenus);

 
//得到菜单栏上面的最后一个菜单
 BSTR name;
 VARIANT vIndex;
 vIndex.vt
=VT_I4;
 vIndex.lVal
=numberOfMenus-1;
 
 pMenuBar
->Item(vIndex,&pPopUpMenu);
 pMenuBar
->Release();
 pPopUpMenu
->get_NameNoMnemonic(&name);
 pPopUpMenu
->Release();
 
 sMenu.Format(
"%S",name);//debug 大写,用于转化LPWSTR类型字符串
 SysFreeString(name);

 
return true;
}


bool CAddCADFrameMenu::GetAcadMenuGroup(IAcadMenuGroup  **pVal,LPCTSTR menuname)
{
 IAcadApplication 
*acadApp = NULL;
 HRESULT hr 
= S_OK;
 
 
if(!GetAcadApplication(acadApp))
  
return false;
 
 LPDISPATCH  pTempDisp 
= NULL;
 IAcadMenuGroups 
*mnuGrps = NULL;
 
long cnt = 0, cntmnu=0;
 
 
//得到菜单组集
 hr = acadApp->get_MenuGroups(&mnuGrps);
 
if (FAILED(hr))
 
{
  acadApp
->Release();
  
return false;
 }

 acadApp
->Release();
 
 mnuGrps
->get_Count(&cnt);
 
 
//得到菜单组
 IAcadMenuGroup *mnuGrp = NULL;
 IAcadPopupMenus  
*mnus = NULL;
 IAcadPopupMenu 
*pPopUpMenu=NULL;
 
 VARIANT  vtName,vtMenu;
 vtName.vt 
= VT_I4;
 vtMenu.vt 
= VT_I4;

 BSTR  mnuName;
 
bool found = false ;
 
for (long i=0; i < cnt; i++)
 
{
  vtName.lVal 
= i;
  hr 
= mnuGrps->Item(vtName, &mnuGrp);
  
if (FAILED(hr))
  
{
   
return false;
  }

  
  mnuGrp
->get_Menus(&mnus);

  mnus
->get_Count(&cntmnu);

  
for(long j=0;j<cntmnu;j++)
  
{
   vtMenu.lVal
=j;
   hr
=mnus->Item(vtMenu,&pPopUpMenu);
   
if(FAILED(hr))
    
continue;

   pPopUpMenu
->get_Name(&mnuName);
   pPopUpMenu
->Release();

   CString sMenuName(mnuName);
   SysFreeString(mnuName);
   
   sMenuName.Replace(
"&","");//debug
   if(sMenuName.CompareNoCase(menuname)==0)
   
{
    found
=true;
    
*pVal = mnuGrp;
    
break;
   }

  }


  mnus
->Release();

  
if(found)
  
{
   
break;
  }

  
else
  
{
   mnuGrp
->Release();
  }

 }


 mnuGrps
->Release();
 
 
return found;
}


bool CAddCADFrameMenu::GetAcadMenuGroup(IAcadMenuGroup  **pVal)
{
 IAcadApplication 
*acadApp = NULL;
 HRESULT hr 
= S_OK;
 
 
if(!GetAcadApplication(acadApp))
  
return false;

 LPDISPATCH  pTempDisp 
= NULL;
 IAcadMenuGroups 
*mnuGrps = NULL;
 
long cnt = 0;
 
 
//得到菜单组集
 hr = acadApp->get_MenuGroups(&mnuGrps);
 
if (FAILED(hr))
 
{
  acadApp
->Release();
  
return false;
 }

 acadApp
->Release();

 mnuGrps
->get_Count(&cnt);
 
 
//得到菜单组
 IAcadMenuGroup *mnuGrp = NULL;
 
 VARIANT  vtName;
 vtName.vt 
= VT_I4;
 BSTR  grpName;
 
bool found = false ;
 
for (long i=0; i < cnt; i++)
 
{
  vtName.lVal 
= i;
  hr 
= mnuGrps->Item(vtName, &mnuGrp);
  
if (FAILED(hr))
   
continue;
  
  hr  
= mnuGrp->get_Name(&grpName);
  CString cgrpName(grpName);
  SysFreeString(grpName);
  
  
if (cgrpName.CompareNoCase("Acad")==0
  
{
   found 
= true;
   
*pVal = mnuGrp;
   
break;
  }

  
else
  
{
   mnuGrp
->Release();
  }

 }


 mnuGrps
->Release();
 
 
return found;
}


void CAddCADFrameMenu::CreateMenus()
{
 CMDIFrameWnd 
* pMainFrame = acedGetAcadFrame();
 pMainFrame
->LockWindowUpdate();
 
 
//得到菜单栏上面的最后一个菜单
 CString sName;
 
if(!GetLastMenuFromMenubar(sName))
  
return;

 sName.Replace(
"&","");//debug
 
 IAcadMenuGroup 
*mnuGrp = NULL;
 
if (!GetAcadMenuGroup(&mnuGrp,sName))
  
return ;

 
//得到所有菜单组
 IAcadPopupMenus   *mnus = NULL;
  IAcadPopupMenu   
*mnu = NULL;
 IAcadPopupMenuItem  
*mnuitem = NULL;
 HRESULT hr 
= S_OK;
 hr 
= mnuGrp->get_Menus(&mnus);
 
long cnt = 0l;
 hr 
= mnus->get_Count(&cnt);
 
int i = 0;
 
int j = 0;
 
int k = 0;
 VARIANT index;
 VariantInit(
&index);
 V_VT(
&index) = VT_I4;
 CArray
<IAcadPopupMenu*, IAcadPopupMenu*> MnuAdrs; 

 
long lIndex=0;
 WCHAR MenuName[
256];
 
for (i = 0; i < m_menuCount; i++
 
{
  CString tmpMenu
=m_TopMenuNames[i];
  tmpMenu.Replace(
"&","");
  
if(IsMenuExist(mnu,lIndex,tmpMenu,mnus))//处理二次加载
  {
   V_I4(
&index) = lIndex;
  }

  
else
  
{
   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_TopMenuNames[i], 
-1, MenuName, 256); 
   mnus
->Add(MenuName, &mnu); 
   V_I4(
&index) = cnt++;
  }

  
  MnuAdrs.Add(mnu);
  mnu
->InsertInMenuBar(index);
 }


 IAcadPopupMenu 
*MenuItem = NULL;
 
int subMenuNum = 0;
 CCADMenuArray
* Menus;
 WCHAR szSubMenu[
256];
 WCHAR szSubMenuMacro[
256];
 CString MenusName;
 CString Menusorder;
 
for (j = 0; j < m_menuCount; j++{
  Menus 
= m_menus.GetAt(j);
  subMenuNum 
= Menus->GetSize();
  
for (k = 0; k < subMenuNum; k++
   mnu 
= MnuAdrs.GetAt(j);
   
if (!strcmp("--", Menus->GetAt(k)->name)) {
    V_I4(
&index) = k;
    mnu
->AddSeparator(index, &mnuitem);
   }

   
else {
    V_I4(
&index) = k;    
    MenusName 
= Menus->GetAt(k)->name; 
    Menusorder 
= Menus->GetAt(k)->order;
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, MenusName, 
-1, szSubMenu, 256); 
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Menusorder, 
-1, szSubMenuMacro, 256); 
    
if (strcspn(Menus->GetAt(k)->name, "*"< (size_t)MenusName.GetLength()){
     MenusName.TrimLeft(
'*');
     MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, MenusName, 
-1, szSubMenu, 256); 
     hr 
= mnu->AddSubMenu(index, szSubMenu, &MenuItem);
    }
    
    
else if (strcspn(Menus->GetAt(k)->name, "$"< (size_t)MenusName.GetLength() ){        
     MenusName.TrimLeft(
'$');
     
if(MenusName.Compare("--")==0)//添加子菜单的分隔符
     {
      hr 
= MenuItem->AddSeparator(index, &mnuitem);
     }

     
else
     
{
      MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, MenusName, 
-1, szSubMenu, 256); 
      hr 
= MenuItem->AddMenuItem(index, szSubMenu, szSubMenuMacro, &mnuitem);
     }

    }

    
else {
     hr 
= mnu->AddMenuItem(index, szSubMenu, szSubMenuMacro, &mnuitem);
    }

   }

  }

 }


 
for (i=0; i<MnuAdrs.GetSize(); i++)
 
{
  MnuAdrs[i]
->Release();
 }

 mnuitem
->Release();
 mnus
->Release();
 mnuGrp
->Release();
 pMainFrame
->UnlockWindowUpdate(); 
 
 stcMyTopMenuNames.Copy(m_TopMenuNames);
//将顶级菜单名存入静态数组中,卸载时使用

 
return ;
}


bool CAddCADFrameMenu::IsMenuExist(IAcadPopupMenu *&pMnu,long &index,const char *mnuname,IAcadPopupMenus *mnus)
{
 ASSERT(mnus
!=NULL);
 
 
long cnt = 0l;
 HRESULT hr 
= mnus->get_Count(&cnt);
 
bool found = false;
 
int curMenuIndex=-1;
 BSTR tempName;

#ifdef _DEBUG
 acutPrintf(
"IsMenuExist cnt=%ld ",cnt);
#endif
 
 
//
 IAcadPopupMenu *toolsMenu = NULL;
 
for (long i=0; i < cnt; i++)
 
{
  VARIANT vtName;
  VariantInit(
&vtName);
  V_VT(
&vtName) = VT_I4;
  V_I4(
&vtName) = i;
  hr 
= mnus->Item(vtName, &toolsMenu);
  
if (FAILED(hr))
   
return false;
  hr 
= toolsMenu->get_NameNoMnemonic(&tempName);
  CString mnuName(tempName);

#ifdef _DEBUG
  acutPrintf(
" %d,%s",i,mnuName);
#endif
  
if(mnuName.Compare(mnuname)==0)
  
{
   index
=i;
   pMnu
=toolsMenu;
   
return true;
  }
 
 }

 pMnu
=NULL;
 
return false;
}


void CAddCADFrameMenu::CleanUpMenus()
{
 IAcadMenuGroup 
*mnuGrp = NULL;
 
for(int i=0;i<stcMyTopMenuNames.GetSize();i++)
 
{
  CString sMenu
=stcMyTopMenuNames.GetAt(i);
  sMenu.Replace(
"&","");

  
if (!GetAcadMenuGroup(&mnuGrp,sMenu))
  
{
#ifdef _DEBUG
   acutPrintf(
"没有找到 %s 所属的菜单组,无法卸载。 ",sMenu);
#endif
   
//   mnuGrp->Release();
   continue;
  }


  
//得到所有菜单组 
  IAcadPopupMenus  *mnus = NULL;
  HRESULT hr 
= S_OK;
  hr 
= mnuGrp->get_Menus(&mnus);

  ClearMenu(mnus,sMenu);

  mnus
->Release();
  mnuGrp
->Release();

 }


 stcMyTopMenuNames.RemoveAll();
}


void CAddCADFrameMenu::ClearMenu(IAcadPopupMenus *mnus,LPCTSTR menuname)
{
 
long cnt = 0l;
 HRESULT hr 
= mnus->get_Count(&cnt);
 
 
//now get Tools menu
 IAcadPopupMenu *toolsMenu = NULL;
 BSTR   tempName;
 VARIANT vtName;
 VariantInit(
&vtName);

 
bool found = false;
 
for (long i=0; i < cnt; i++){
  vtName.vt 
= VT_I4;
  vtName.lVal 
= i;
  hr 
= mnus->Item(vtName, &toolsMenu);
  
if (FAILED(hr))
   
return ;
  
  hr 
= toolsMenu->get_NameNoMnemonic(&tempName);
  CString mnuName(tempName);
  SysFreeString(tempName);
  
if(mnuName.CompareNoCase(menuname)==0)
  
{
   found 
= true;
   
break;
  }

 }

 
 
if (!found)
 
{
  acutPrintf(
"没有找到菜单 : %s ",menuname);
  
return;
 }

 
 hr 
= toolsMenu->get_Count(&cnt);
 VARIANT vIndex;
 vIndex.vt 
= VT_I4;
 vIndex.lVal 
= cnt;
 IAcadPopupMenuItem 
*cmd1 = NULL;
 
while(cnt--)
 
{
  vIndex.lVal
=cnt;
  hr
=toolsMenu->Item(vIndex,&cmd1);
  hr
=cmd1->Delete();
  cmd1
->Release();
 }

 
 toolsMenu
->RemoveFromMenuBar();
 toolsMenu
->Release();

 mnus
->RemoveMenuFromMenuBar(vtName);
 
 
return;
 
}



http://blog.sciencenet.cn/blog-83029-269915.html


下一篇:《走西口》田家大院的祖训

0

发表评论 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2019-11-20 04:00

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部