?? 實現右鍵菜單的方法.txt
字號:
網上看到好像網友問到在AutoCAD窗口中實現右鍵菜單的方法,覺得這種技術很實用,在許多開發應用中都能用得到,所以就寫了這篇文章,以供大家參考。由于本人水平有限,不對之處敬請原諒。
右鍵菜單,也叫快捷菜單,在Windows編程中叫上下文(context)菜單。ObjectARX本身提供了一套處理上下文菜單的機制。在 ObjectARX類庫中有一個名為AcEdUIContext的類,此類負責在ObjectARX應用中的上下文菜單中添加自己的菜單項,而原菜單項不會被破壞,這也是此種方法的優點之一。用AcEdUIContext類添加菜單時,菜單項的數目沒有限制,但必須是文本菜單。菜單可以層疊,但不允許使用鍵盤加速鍵,不能夠在狀態行顯示快捷菜單命令狀態提示。此類可以處理三種情況下的上下文菜單:一個默認上下文菜單,二是實體對象上下文菜單,三是命令執行時上下文菜單。雖然菜單出現的時機不同,但方法基本相同,它們之間主要的不同是所用的加載和卸載函數不同。下面加以詳細介紹。
在AcEdUIContext為中包含了三個重要的成員函數,他們分別是:
(1) AutoCAD系統獲取快捷菜單句柄函數
virtual void * getMenuContext(const AcRxClass * unnamed,const AcDbObjectIdArray& unnamed) = 0;
其中,第一個參數unnamed 是當前所選擇的實體的對象句柄,第二個參數unnamed是所選實體的實體ID數組。這兩個參數只有在實體對象上下文菜單中有效。
(2) 菜單項命令事件響應函數
virtual void onCommand(Adesk::UInt32 unnamed) = 0;
其中,unnamed是相應菜單項的菜單ID。此函數在用戶選擇執行快捷菜單中的某個菜單項時被調用。
(3) 菜單更新函數
virtual void OnUpdateMenu();
AutoCAD在快捷菜單彈出之前調用此函數。相當于MFC中的菜單更新事件,我們可以在這個函數中改變菜單項的檢查狀態或使能菜單項等。
其實,我們利用ObjectARX實現上下文菜單要做的工作主要是重載并填寫這幾個AcEdUIContext成員函數,其操作方法如下:
首先,我們從AcEdUIContext類派生一個自己的類,名字就叫CDefaultContextMenu吧,當然,你可以按自己的喜好起名字了:-)。然后,在派生的類中重載以上三個函數。
class CDefaultContextMenu: public AcEdUIContext
{
public:
CDefaultContextMenu();
~CDefaultContextMenu();
// 如下重載以下三個函數
virtual void* getMenuContext(const AcRxClass *pClass, const AcDbObjectIdArray& ids) ;
virtual void onCommand(Adesk::UInt32 cmdIndex);
virtual void OnUpdateMenu();
private:
CMenu *m_pDemoMenu; // 用來增加菜單項的MFC菜單對象,使用它是為了加載我們在VC中增加的菜單資源。
HMENU m_hDemoMenu; // 菜單項所對應的句柄,這才是我們真正要加載的的菜單項,它是m_pDemoMenu中的一項。
};
接下來我們需要做的是:(1)在構造函數中加載菜單資源;(2)在getMenuContext函數中添加顯示我們自己菜單項的代碼;(3)在 onCommand函數中處理命令執行代碼;(4)在OnUpdateMenu中修改菜單項的顯示狀態(此步可選可不選);(5)在析構函數中卸載資源。
--在構造函數中加載菜單資源
acDocManager->pushResourceHandle(_hdllInstance); // 切換當前使用的資源,千萬不要忘記加上吆!_hdllInstance是模塊
//實例指針,通過extern引用到使用的位置就可以了。
m_pDemoMenu= new CMenu; // 創建一個菜單對象
m_pDemoMenu->LoadMenu(IDR_DEMO_DEFAULT_MENU); // 使用創建的菜單對象加載在資源編輯器中編輯好的資源
acDocManager->popResourceHandle(); // 再把資源切換回來吧!
--在getMenuContext函數中添加顯示我們自己菜單項的代碼
m_hDemoMenu= m_pDemoMenu->GetSubMenu(0)->GetSafeHmenu(); // 這里我們就顯示已經加載的菜單(m_pDemoMenu)中的第一個子菜單吧!
return &m_hDemoMenu; // 返回子菜單對象的句柄
--在onCommand函數中處理命令執行代碼
acDocManager->pushResourceHandle(_hdllInstance); // 切換當前使用的資源
CString strMenuTitle, strPrompt;
m_pMenu->GetMenuString(cmdIndex,strMenuTitle,MF_BYCOMMAND); // 獲取一所選菜單項的文本標題
strPrompt.Format("\n您已經選取了菜單:%s\n",strMenuTitle);
acutPrintf(strPrompt); // 我們的例子顯示哪一個菜單項被選擇
acedPostCommandPrompt(); // 顯示命令提示
acDocManager->popResourceHandle(); // 將資源切換回來
--在OnUpdateMenu中修改菜單項的顯示狀態
m_pDemoMenu->EnableMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM1,MF_GRAYED); // 使菜單變灰
m_pDemoMenu->EnableMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM2,MF_ENABLED); // 使能菜單項
m_pDemoMenu->CheckMenuItem(IDR_DEMO_DEFAULT_MENU_ITEM3, MF_BYCOMMAND|MF_CHECKED); // 復選菜單項
--在析構函數中卸載資源
if (m_pMenu) delete m_pMenu; // 不釋放的話麻煩可大呀!!!
以上用默認上下文菜單為例對AcEdUIContext類的使用方法作了闡述,至于其他兩種基本是與默認上下文菜單相同。只不過在實體對象上下文菜單中的getMenuContext函數中可以對所選的實體進行響應,因為我們可以通過getMenuContext函數的參數獲取實體對象。
有了以上的準備工作,我們就可以按照菜單顯示時機加載不同種類的菜單了。
--首先,要行聲明一個全局的上下文菜單對象,如下:
CDefaultContextMenu *gpDefDemoCM; // 默認上下文菜單
CEntityContextMenu *gpEntDemoCM; // 實體對象上下文菜單
CCmdContextMenu *gpCmdDemoCM; // 命令時上下文菜單
--然后,在初始化ARX應用時創建并加載上下文菜單對象。
gpDefDemoCM = new CDefaultContextMenu; // 創建默認上下文菜單
gpEntDemoCM = new CEntityContextMenu; // 創建實體對象上下文菜單
gpCmdDemoCM = new CCmdContextMenu; // 創建命令時上下文菜單
acDocManager->pushResourceHandle(_hdllInstance); // 切換當前使用的資源
acedAddDefaultContextMenu(gpDefDemoCM, pAppID); // 向AutoCAD應用中添加默認上下文菜單
acedAddObjectContextMenu(AcDbEntity::desc(), gpEntDemoCM , pAppID); // 向AutoCAD應用中添加實體對象上下文菜單
// 向AutoCAD應用中添加命令時上下文菜單
// myCmd是一個命令函數。第一個參數是命令組名,第二個參數是全局命令名,
// 第三個參數是本地命令名,第四個參數是命令模式,第5和6個參數就不用說了,大家應該明白了。:-0
acedRegCmds->addCommand("MyGrp", "MyDemo", "MyDemo", ACRX_CMD_MODAL, &myCmd, gpCmdDemoCM );
acDocManager->popResourceHandle(); // 切換回資源
說明:pAppID是acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)中是第二個參數。acedAddObjectContextMenu中的第一個參數根據實體的不同而不同,如對于線實體則為AcDbLine:: desc()等。
--最后,在卸載ARX應用時,將加載的上下文菜單對象移除,并釋放內存空間。
HINSTANCE hInst = AfxGetResourceHandle(); // 保證資源正確
AfxSetResourceHandle(_hdllInstance);
acedRemoveDefaultContextMenu(gpDefDemoCM ); // 移除默認上下文菜單
acedRemoveObjectContextMenu(AcDbEntity::desc(), gpEntDemoCM ); // 移除實體對象上下文菜單
acedRegCmds->removeGroup("MyGrp"); // 移除命令組"MyGrp"
delete gpDefDemoCM;
delete gpEntDemoCM;
delete gpCmdDemoCM;
AfxSetResourceHandle(hInst);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -