zoukankan      html  css  js  c++  java
  • 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"
    %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"
     reging...
    ");
            if (!acedRegisterFilterWinMsg(func)) {
                acutPrintf(L"
     reg  failed
    ");
            }
            else{
                acutPrintf(L"
     reg success
    ");
                isReged = TRUE;
            }
        }
    }
    
    void RegMsg::unReg()
    {
        if (isReged) {
    
            if (!acedRemoveFilterWinMsg(func)) {
                acutPrintf(L"
     unreg  failed
    ");
            }
            else {
                acutPrintf(L"
     unreg success
    ");
                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
  • 相关阅读:
    如何让我domain里的机器都跟domain controller的时间保持一致?
    [PowerShell Utils] Create a list of virtual machines based on configuration read from a CSV file in Hyper-V
    Reboot server stuck at “Press ESC in 1 seconds to skip startup.nsh”
    [PowerShell Utils] Remotely install Hyper-V and Failover Cluster feature on a list of windows 2012 servers
    [PowerShell Utils] Automatically Change DNS and then Join Domain
    SharePoint 2016 IT Preview的新feature列表
    LeetCode Permutations问题详解
    Rotate Image 旋转图像
    单链表的快速排序(转)
    anagrams 查找序列里具有相同字符但顺序不同的单词
  • 原文地址:https://www.cnblogs.com/HelloQLQ/p/12160678.html
Copyright © 2011-2022 走看看