ObjectArx 使用消息鈎子實現鼠標滾輪旋轉實體


測試結果:

 

實現方法:主要是程序注冊一個消息函數:func,攔截鼠標滾輪觸發的消息,需要注意的是,以寫的方式處理實體時需要鎖定文檔。注冊func的主要方法是:
BOOL acedRegisterFilterWinMsg(
const AcedFilterWinMsgFn pfn
);
AcedFilterWinMsgFn 這個類型 是一個函數指針,其實他是這樣的:
typedef BOOL (* AcedFilterWinMsgFn)(MSG*);接受一個MSG *的參數,返回BOOL類型的函數。

這個MSG是個struct,參數內部是這樣的:

typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG

我們主要使用到的是message成員,和wParam成員。使用message成員過濾出鼠標滾輪滑動的消息,wParam的值來區分滾輪上和下的運動,然后我們就把實體的旋轉寫在這個里面。詳細見代碼:、

BOOL func(MSG *msg) {

    int zdFx = 0;

    if (msg->message == WM_MOUSEWHEEL) {

        zdFx = (short)HIWORD(msg->wParam);
        acutPrintf(L"\n%d", zdFx);
        if (zdFx == 120) {

            AcDbEntity * pEnt = NULL;

            ErrorStatus es = acdbOpenObject(pEnt, oId, AcDb::kForWrite);
            if (es == Acad::eOk) {

                pEnt->transformBy(matx1);
                pEnt->close();
            }

        }
        else if (zdFx == -120) {

            AcDbEntity * pEnt = NULL;

            ErrorStatus es = acdbOpenObject(pEnt, oId, AcDb::kForWrite);

            if (es == Acad::eOk) {

                pEnt->transformBy(matx2);
                pEnt->close();
            }
        }
        return TRUE;
    }


    return FALSE;
}

 

這個func是個全局函數,這樣方便我在注冊func的類里面調用。因為注冊了這個消息,cad默認的滾輪放大縮小的功能就會被屏蔽掉,需要使用解除注冊的方法來取消對這個消息的監視。這個方法是:
BOOL acedRemoveFilterWinMsg(
const AcedFilterWinMsgFn pfn
);
我把注冊和取消的方法封裝到一個類里面,並且定義了一個BOOL類型的全局變量來避免重復注冊和重復取消,見代碼:

#include "stdafx.h"
#include "RegMsg.h"

static bool isReged = FALSE;
extern BOOL func(MSG *msg);
RegMsg::RegMsg()
{
}


RegMsg::~RegMsg()
{
}

void RegMsg::reg()
{
    if (!isReged) {
        acutPrintf(L"\n reging...\n");
        if (!acedRegisterFilterWinMsg(func)) {
            acutPrintf(L"\n reg  failed\n");
        }
        else{
            acutPrintf(L"\n reg success\n");
            isReged = TRUE;
        }
    }
}

void RegMsg::unReg()
{
    if (isReged) {

        if (!acedRemoveFilterWinMsg(func)) {
            acutPrintf(L"\n unreg  failed\n");
        }
        else {
            acutPrintf(L"\n unreg success\n");
            isReged = FALSE;
        }
    }
}
View Code

 

最后我需要做的就是,選擇要選擇的實體,把實體的ObjectId傳入到func函數里,在func函數里進行旋轉操作,我發現,必須在func函數里每滑動依次鼠標,就需要對實體進行依次開閉操作,如果,只是在處理函數里只旋轉,而不關閉實體,cad里的實體是不會旋轉的,到最后你什么時候關閉這個打開的實體,這個實體才會旋轉到最后一次的操作上來。
下面是我在命令類的全局參數和定義的操作命令:

#define PI 3.14159265358979323846

BOOL func(MSG *msg);

AcDbObjectId oId;
AcGeMatrix3d matx1;
AcGeMatrix3d matx2;
RegMsg * reg = NULL;
View Code

 

static void ECDMyGroupMyRegMsg() {

        acDocManager->lockDocument(acDocManager->curDocument());

        if (reg == NULL) {
            reg = new RegMsg();

            AcRxClass *cls = AcDbEntity::desc();

            AcDbEntity * pEnt = NULL;

            AcGePoint3d pickPoint;

            if (CSelectUtil::PromptSelectEntity(L"選擇實體:", cls, pEnt, pickPoint, true)) {

                oId = pEnt->objectId();
                pEnt->close();
                matx1 = AcGeMatrix3d::rotation(1.0 / 18 * PI, AcGeVector3d::kZAxis, pickPoint);
                matx2 = AcGeMatrix3d::rotation(-1.0 / 18 * PI, AcGeVector3d::kZAxis, pickPoint);

                reg->reg();
            }
        }

    }
View Code

 

static void ECDMyGroupMyUnRegMsg() {

        acDocManager->unlockDocument(acDocManager->curDocument());

        if (reg != NULL) {

            reg->unReg();

            reg = NULL;

            delete reg;
        }
    }
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM