枫叶棋语 发表于 前天 15:34

写1个acedGrRead+ acedSSget 配合,实现鼠标悬浮不点击状态选中图元

本来想在Jig 中使用,但是jIG过程ssget 返回5003, 大佬有别的方法也可以教我一下

#include <stdarx.h>
#include <memory>

// 全局变量记录上次选中的图元
static ads_name g_oldAdsEnt = { 0, 0 };
static AcDbObjectId g_objidOld = AcDbObjectId::kNull;

// 比较两个ads_name是否相同
bool CompareAdsEnt(const ads_name& left, const ads_name& right) {
return (left == right) && (left == right);
}

// 检查ads_name是否有效
bool IsValidAdsName(const ads_name& name) {
return name != 0 || name != 0;
}

bool SelectEntity(const AcGePoint3d& pt, ads_name& ss, AcDbObjectId& objid, AcDbEntity*& pEnt) {
// 释放之前的选择集
if (IsValidAdsName(ss)) {
    acedSSFree(ss);
    ss = ss = 0;
}

// 尝试选择图元
if (acedSSGet(nullptr, &pt, nullptr, nullptr, ss) != RTNORM) {
    return false;
}

// 检查选择集有效性
int len = 0;
if (acedSSLength(ss, &len) != RTNORM || len == 0) {
    return false;
}

// 获取第一个图元
ads_name ent;
if (acedSSName(ss, 0, ent) != RTNORM) {
    return false;
}

// 比较是否与上次选中的图元相同
if (CompareAdsEnt(ent, g_oldAdsEnt) && pEnt != nullptr) {
    return true;
}

// 获取对象ID
if (acdbGetObjectId(objid, ent) != Acad::eOk) {
    return false;
}

// 关闭之前打开的图元
if (pEnt != nullptr) {
    pEnt->close();
    pEnt = nullptr;
}

// 打开新图元
if (acdbOpenObject(pEnt, objid, AcDb::kForRead) == Acad::eOk) {
    // 更新记录
    g_oldAdsEnt = ent;
    g_oldAdsEnt = ent;
    g_objidOld = objid;

    acutPrintf(L"\n选中新图元(颜色: %d)", pEnt->colorIndex());
    return true;
}

return false;
}

void monitorInput() {
ads_name ss = { 0 };
AcDbObjectId objid = AcDbObjectId::kNull;
AcDbEntity* pEnt = nullptr;
const int trackFlags = 8 | 4 | 2 | 1; // 启用所有输入类型
std::unique_ptr<resbuf> result(new resbuf);
AcGePoint3d lastPoint, dragPt;
std::wstring inputBuffer;

acutPrintf(L"\n开始监控输入(按ESC退出)...");

while (true) {
    int inputType = 2;// 设定鼠标选图元样式
    int status = acedGrRead(trackFlags, &inputType, result.get());

    if (status == RTCAN) {
      acutPrintf(L"\n用户取消操作");
      break;
    }

    switch (inputType) {
    case 2: // 键盘输入
      if (result->resval.rint >= 32 && result->resval.rint <= 126) {
      wchar_t ch = static_cast<wchar_t>(result->resval.rint);
      inputBuffer += ch;

      if (inputBuffer.find(L"abc") != std::wstring::npos) {
          acutPrintf(L"\n检测到关键字'abc'");
          inputBuffer.clear();
      }
      }
      break;

    case 3: // 鼠标点击
      lastPoint.set(result->resval.rpoint);
      acutPrintf(L"\n点击坐标: (%.2f, %.2f)", lastPoint.x, lastPoint.y);
      break;

    case 5: // 鼠标拖拽
      dragPt.set(result->resval.rpoint);
      if (!lastPoint.isEqualTo(dragPt)) {
      SelectEntity(dragPt, ss, objid, pEnt);
      }
      break;
    }
}

// 清理资源
if (pEnt != nullptr) {
    pEnt->close();
}
if (IsValidAdsName(ss)) {
    acedSSFree(ss);
}
acutPrintf(L"\n监控结束");
}

你有种再说一遍 发表于 前天 18:43

本帖最后由 你有种再说一遍 于 2026-1-4 22:04 编辑

悬浮不点击图元从而选中,这个功能应该用四叉树做,
判断当前鼠标点位于四叉树哪个最小节点,获取节点内的图元,
节点中每个 图元.包围盒.Contains(pt) 即可,这样就不需要调用选择集.

你可以用鼠标钩子+键盘钩子.
钩子的鼠标点高频写入一个静态变量中,然后使用的时候要从屏幕坐标转图纸WCS坐标.

而且也不需要jig,用jig目的是basepoint+当前鼠标点构成的向量,
然后不断修改和刷新多个图元,
不必为了展示技术而加入不必要的东西,除非你有其它逻辑需要.

这样下来你就没有用到任何的cad提供的交互API,完全绕过交互报错.
页: [1]
查看完整版本: 写1个acedGrRead+ acedSSget 配合,实现鼠标悬浮不点击状态选中图元