明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 830|回复: 0

[图形系统] 魔改系列-2循环选择

[复制链接]
发表于 2024-1-23 00:52:14 | 显示全部楼层 |阅读模式
本帖最后由 你有种再说一遍 于 2024-10-20 16:20 编辑


# 循环选择
1,选择状态有夹点显示,此时缓冲区有id集合且不为0.
2,亮显没有夹点显示.
在Acad.net提供的手选函数,无法在缓冲区不为0时再选择,如果此时循环再手选,不会发生阻塞,而是直接就是ok的...


问题代码展示:
```csharp
    [CommandMethod(nameof(LoopBug))]
    public void LoopBug() {
        Document doc = Acap.DocumentManager.MdiActiveDocument;
        Editor ed = doc.Editor;
        for (int i = 0; i < 5; i++) {
            // 第一次会阻塞后执行手选,第二次就不会了.
            var opts = new PromptSelectionOptions() { MessageForAdding = "\n请选择图元:" };
            var ss = ed.GetSelection(opts);
            if (ss.Status != PromptStatus.OK) {
                ed.WriteMessage("\n未选择任何图元.");
                continue;
            }
            var ids = ss.Value.GetObjectIds();
            ed.WriteMessage("\n选择了图元数:" + ids.Length);
            ed.SetImpliedSelection(ids);
        }
    }
```


我们很容易想到一个解决方案,
如果不设置缓冲区,那么是不是只能亮显了?
但是亮显图元无法用shift剔除.
重点:
此时需要通过键盘钩子进行拦截shift键入,然后发送消息结束ssget.把全部图元亮显,求出鼠标矩形在哪些图元上面,暗显并ids也减去.
shift抬起时候,恢复亮显.


```csharp
[CommandMethod(nameof(Pick), CommandFlags.UsePickSet)]//记得加这个flag
public void Pick() {
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;


var opts = new PromptSelectionOptions("\n请选择对象:");
opts.AllowNone = true;
opts.AllowArbitraryInput = true; // 允许任意输入
//opts.SingleOnly = true;//只一个对象不回车
opts.SelectEverythingInAperture = true;// 点击模式


// 过滤器
SelectionFilter fr = new (new TypedValue[] {
    new TypedValue((int)DxfCode.Start, "LINE"),
});


    var ss = ed.SelectImplied();//预选
    if (ss.Status == PromptStatus.OK) {
      foreach(var id in ss.Value.GetObjectIds()){
         if(!fr.Contains(id)){ // 伪代码看懂就行
              _ids.Add(id);
         }
     }
      // 清空选择集
      ed.SetImpliedSelection(new ObjectId[] { });
    }


    // 循环选择,重新手选
    while(true){
      _ids.ForEach=>{ent.Highlight();}//亮显
      ss = ed.GetSelection(opts,fr);
      if (ss.Status == PromptStatus.OK) {
         _ids.ForEach=>{ent.Unhighlight();}//暗显
         _ids.AddRange(ss.Value.GetObjectIds());
         ed.SetImpliedSelection(new ObjectId[] { });
         continue;
      }
      
      if(ss.Status == PromptStatus.Cancel) {
/* 键盘钩子发送Esc消息才到这个状态
方案一:
先选中ids,再开启新选择集,然后减选.
我怀疑不行,因为选中状态(缓冲区有对象)会直接跳过手选.
shift按着也可能不切换到新选择集的反选模式.
释放shift也要结束这个选择集
         _ids.ForEach=>{ent.Unhighlight();}//暗显
         ed.SetImpliedSelection(_ids.ToArray());//重设选择集
         var s2 = ed.GetSelection();
         if(s2.Status == PromptStatus.OK) {
           _ids.RemoveAll(s2.Value.GetObjectIds());
         }
方案二:
不重设选择集,获取选择集矩形两个点ss.PickedPoint,然后直接剔除集合
         ?
*/
      }
      // 结束循环
      _ids.ForEach=>{ent.Unhighlight();}//暗显
      break;  
    }
}


HashSet<ObjectId> _ids = new();


void 键盘钩子(s,e) {
  if(e.Key == "shift".KeyCode()){
    Acad.Handle.Foucs().发送异步Esc消息();
    //这里_ids.事务跨线程!无法操作图元.
  }
}
```


选择集的本质:
啊?其实可以自己实现一个两点矩形,然后通过选框范围,再触发四叉树选择.
选框还可以利用透明winform画一个颜色,并且才用滤镜算法...很麻烦吗?
(完)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 04:05 , Processed in 0.134119 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表