本帖最后由 highflybird 于 2009-5-5 01:19 AM 編輯
很久沒(méi)摸arx了,不久看到了一篇介紹鉤子技術(shù)在 AutoCAD中應(yīng)用的文章,不敢獨(dú)享,特此奉獻(xiàn)給大家。
鉤子技術(shù)是很有用的一種技術(shù),它如同給函數(shù)掛上一個(gè)鉤子(我們自己的函數(shù)),讓它在執(zhí)行前先執(zhí)行我們掛的鉤子(我們掛接的函數(shù)),從而達(dá)到攔截事件和函數(shù)調(diào)用等的目的。在autocad中,利用鉤子技術(shù)可以為我們做很多事情:如建立快捷鍵(不希望更改已有菜單),等待或者觸發(fā)特定消息(如鼠標(biāo),鍵盤(pán)),可以獲得比反應(yīng)器更強(qiáng)大的功能,等等。
objectARX提供了幾種向autocad注冊(cè)鉤子函數(shù)的ARX API函數(shù),見(jiàn)下面:
acedRegisterFilterWinMsg,注冊(cè)一個(gè)鉤子函數(shù) acedRemoveFilterWinMsg,注銷(xiāo)一個(gè)鉤子函數(shù) acedRegisterWatchWinMsg, 監(jiān)測(cè)鉤子函數(shù) acedRemoveWatchWinMsg, 移除監(jiān)測(cè)函數(shù)
其具體用法各位不妨參考幫助文件。
下面函數(shù)提供一個(gè)例程,該例程定義了一個(gè)快捷命令 Ctrl+I,當(dāng)用戶(hù)按下快捷鍵時(shí)候,autocad 將執(zhí)行appload命令。
我這里采用了向?qū)?/span>方式創(chuàng)建了一個(gè)新工程Hook
采不采用MFC對(duì)這個(gè)程序沒(méi)有影響.
在acrxEntryPoint.cpp 中開(kāi)頭添加如下代碼:
- #include <aced.h> //僅因?yàn)榘姹据^低,所以加了這兩個(gè)
- #include <rxmfcapi.h> //對(duì)于高版本無(wú)須此兩個(gè)
復(fù)制代碼
并申明函數(shù):
- //------------------------------------------------------------------------------------------------
- //函數(shù)原型及其全局變量申明
- void sendCommandToAutoCAD(HWND hWndAcad,CString cmd); //向AutoCAD窗口發(fā)送字符串命令(cmd)
- void watchCtrlI(const MSG * pMsg); //鉤子監(jiān)測(cè)函數(shù)
- void Accelerator(void); //快捷鍵注冊(cè)函數(shù)
- static BOOL filterCtrlKeyDone = FALSE;
- //------------------------------------------------------------------------------------------------
復(fù)制代碼
函數(shù)定義
- void Accelerator(void)
- {
- if(filterCtrlKeyDone == TRUE)
- {
- acutPrintf(_T("Hook has already been registered!\n")); //如果鉤子已經(jīng)注冊(cè),則返回
- return;
- }
- if(acedRegisterWatchWinMsg(watchCtrlI) == FALSE)
- acedPrompt(_T("Hook can't be registered!\n")); //無(wú)法注冊(cè)鉤子
- else
- {
- acedPrompt(_T("Shortcut Ctrl+I has been defined!\n")); //快捷命令Ctrl + I 已經(jīng)定義
- filterCtrlKeyDone = TRUE;
- }
- return;
- }
- //鉤子監(jiān)測(cè)函數(shù),監(jiān)測(cè)Ctrl+I鍵盤(pán)消息
- void watchCtrlI(const MSG *pMsg)
- {
- if (pMsg->message == WM_CHAR && pMsg->wParam == 9) //發(fā)生鍵盤(pán)Ctrl + I消息
- {
- sendCommandToAutoCAD(adsw_acadMainWnd(), _T("appload\n"));
- //這里可以是你自己定義的任何函數(shù)
- }
- return;
- }
- //向AutoCAD窗口發(fā)送字符串命令(cmd)
- void sendCommandToAutoCAD(HWND hWndAcad,CString cmd)
- {
- if(! hWndAcad)
- return;
- COPYDATASTRUCT cmdMsg;
- cmdMsg.dwData = (DWORD)1;
- cmdMsg.cbData = (DWORD)_tcslen(cmd) + 1;
- cmdMsg.lpData = cmd.GetBuffer(cmd.GetLength() + 1);
- SendMessage(hWndAcad,WM_COPYDATA,(WPARAM)hWndAcad, (LPARAM)& cmdMsg);
- return;
- }
復(fù)制代碼
修改一下初始化入口On_kInitAppMsg和卸載函數(shù)On_kUnloadAppMsg
- virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
- // TODO: Load dependencies here
- // You *must* call On_kInitAppMsg here
- AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
-
- // TODO: Add your initialization code here
- //我在這里添加到了初始化,如果你感覺(jué)不好的話,可以定義到命令組里
- Accelerator();
- return (retCode) ;
- }
- virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
- // TODO: Add your code here
- // You *must* call On_kUnloadAppMsg here
- AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
- // TODO: Unload dependencies here
- //卸載arx程序前卸載鉤子函數(shù)
- if(filterCtrlKeyDone == TRUE)
- {
- acedRemoveWatchWinMsg(watchCtrlI);
- acutPrintf(_T("\nHook has been removed!\n"));
- }
- return (retCode) ;
- }
復(fù)制代碼
編譯后,形成arx,加載hook.arx,然后當(dāng)你用快捷鍵的時(shí)候,你就會(huì)發(fā)現(xiàn)彈出appload對(duì)話框了。 最終效果如下圖: 如果你感覺(jué)到代碼不好讀或者有出入,見(jiàn)我下面的附件: 在vs2002 + arx2006 + autocad2006 編譯成功并運(yùn)行正確。
我這個(gè)例子僅僅很簡(jiǎn)單,希望大家討論。 這個(gè)利用鉤子技術(shù)在autocad 中定義快捷命令的思路,具有較大的啟發(fā)意義。因?yàn)?,?duì)于在autocad 平臺(tái)上開(kāi)發(fā)cad系統(tǒng)來(lái)說(shuō),如果直接與autocad建立底層聯(lián)系(如等待或者觸發(fā)特定的消息),利用鉤子技術(shù)是很必要的。
|
|