x_s_s_1 发表于 2022-3-27 17:17:39

【抛砖引玉】关于右键菜单,另类实现工具面板

本帖最后由 x_s_s_1 于 2022-3-27 17:57 编辑

文章较长,且逻辑性不强,没兴趣请跳过:lol
对于可能长时间处于一个固定状态的制图工作,一个大面板可能效率不高。我针对于自己的实际需要,采用了右键菜单,模拟小面板。这样做的好处在于1.提高效率;2.可以用快捷键,经常打游戏的asdfqwe用得比较溜的,可以试试。效果如下:

本人水平有限,对于mnu文件和popupmenu对象一知半解,希望各位网友指正。
思路是这样的
1.准备ini文件,通过读ini文件,修改菜单;(这里可以改成读excel,方便修改,我对这方面不熟,用的读txt文件)
文件格式为
"模态标签","模态名称"
"快捷键","命令提示","命令"
下面是ini文件片段

MODE1,转换出图
1,计算导入,AAJSSDRGL
a,图纸转换,XTY-CMD-YJK
MODE2,基础绘制
a,范围选数,XTY-CMD-FWXS
s,墙柱填充,XTY-CMD-HATCH
d,承台桩定位,AACTZDWBZ
。。。

2.读取ini文件(我用的文件名为XTDI-COMMAND.INI,把他放到支持文件夹),形成表;
(defun xty-mnu-getini (/ F FILE LST LST1 TXT temp)
(setqfile (findfile "XTDI-COMMAND.INI")
f    (open file "r")
lst'() ;_准备总表
lst1 '() ;_准备分表
)
(while (setq txt (read-line f)) ;_读每行
    (if(wcmatch txt "MODE*") ;_当为mode
      (setq lst   (if lst1
       (cons (reverse lst1) lst)
   ) ;_当分表不空,倒置分表组总表
      lst1 (list(xty-str-tolstby txt ",")) ;_mode放入分表
      )
      (setq temp (xty-str-tolstby txt ",")
      temp (list(strcat (car temp)"."(cadr temp))(strcat (caddr temp)" "))
      lst1 (cons temp lst1)
      ) ;_非mode放入分表
    )
)
(close f)
(setqlst (cons (reverse lst1) lst) ;_最后一个分表要倒置组入总表
lst (reverse lst) ;_倒置总表
)
)3.替换autocad的默认右键菜单项,我用的是autocad2020中文版,默认菜单的名称为"默认菜单";
;;;=============================================
;;;      通用函数替换菜单全部项
;;;参数: mnugname--------要修改的菜单组名
;;;       mnuname---------要修改的菜单名
;;;       itemlst-----要修改的菜单项表
;;;返回值:修改的菜单对象
;;;示例:(xty-mnu-changepop "acad" "默认菜单" '(("a.l""line ")))
(defun xty-mnu-changepop(mnugname mnuname itemlst / mnug mnus pop stct i)
(setqmnug (vl-catch-all-apply
         'vlax-invoke-method
         (list *xty-mnugs* 'item mnugname)
       ) ;_菜单组是否存在
)
(if (null (vl-catch-all-error-p mnug)) ;_如果存在要搜索菜单组
    (progn
      (setq mnus (vlax-get-property mnug 'menus)) ;_菜单组中的菜单
      (setq stct (vl-catch-all-apply
       'vlax-invoke-method
       (list mnus 'item mnuname)
   )
      )
      (if (null (vl-catch-all-error-p stct)) ;_如果存在右键弹出菜单pop0
(progn
    (vlax-for pop stct (vlax-invoke-method pop 'delete)) ;_删除所有菜单项
    (setq i 0)
    (foreach n itemlst
      (vlax-invoke-method stct 'addmenuitem i (car n) (cadr n))
      (setq i (1+ i))
    ) ;_重新写菜单项
)
      )
    )
)
stct
)
4.主程序,写mnu文件(我用的名称是CareFromOldXia,可以相应修改),加载到autocad。这里要考虑修改了ini文件,重新加载的方法。现阶段版本autocad都是用cuix文件,所以在重载的时候要将相关文件都删掉;注意*xty-Installfolder*全局变量,这里是我自己的默认文件夹,请根据需求自行修改。
(defun c:xty-cmd-updatemytb(/ a b f i lst lst1 mymnu n)
(setqmymnu (vl-catch-all-apply
    'vlax-invoke-method
    (list *xty-mnugs*
          'item
          "CareFromOldXia"
          )
    )
) ;_获取我的工具条
(vl-catch-all-apply
    'vlax-invoke-method
    (list mymnu
    'unload
    )
    ) ;_删除我的工具条
(foreach n'("CareFromOldXia.cuix"
    "CareFromOldXia.mnr"
    "CareFromOldXia_light.mnr"
    "CareFromOldXia.bak.cuix"
    )
    (vl-catch-all-apply 'vl-file-delete (list (findfile n)))
    ) ;_删除加载菜单生成文件,避免不更新
(setqlst(xty-mnu-getini)
lst1 (mapcar 'car lst)
f    (findfile "CareFromOldXia.mnu")
f    (open f "w")
i    1
)
(write-line "***menugroup=CareFromOldXia" f)
(write-line "***POP0" f);_这里是为其它程序预留的,可以删掉
(write-line "**SNAP" f);_这里是为其它程序预留的,可以删掉
(write-line "" f);_这里是为其它程序预留的,可以删掉
(write-line "***TOOLBARS=allbar" f)
(write-line "**工作模态" f)
(write-line
    "ID_TBA_00 "
    f
    )
(write-line
    "ID_TBA_01 ^c^cxty-cmd-updatemytb"
    f
    )
(setqn (car lst1)
i 0
)
(foreach nlst1
    (setq a (car n)
    b (cadr n)
    )
    (write-line
      (strcat
"ID_TBA_"
(xty-tr-add0 (itoa (setq i (1+ i))) 2)
" [_Button(\"工作模态切换至"
b
"\",\"BMP\\\xty_"
a
"_16.bmp\",\"BMP\\\xty_"
a
"_32.bmp\")]^c^c^p(setenv \"xty-myworkmode\" \""
a
"\");xty-cmd-menumode"
)
      f
      )
    )
(close f)
(setq
    mymnu
   (vl-catch-all-apply
       'vlax-invoke-method
       (list *xty-mnugs*
       'load
       (strcat *xty-Installfolder* "\\CareFromOldXia.mnu")
       )
       )
    )
(princ)
)
5.点击按钮,切换工作模态。
(defun c:xty-cmd-menumode (/ mode lst lst1 lst2 lst3 n)
(setqmode (getenv "xty-myworkmode");_此处设置环境变量"xty-myworkmode",可根据需要修改
lst(xty-mnu-getini)
lst1 (mapcar 'car lst)
lst2 (mapcar 'car lst1)
lst3 (mapcar 'cdr lst)
n(-(length lst2)(length(member mode lst2)))
lst3(nth n lst3)
)
(xty-mnu-changepop "acad" "默认菜单" lst3)
(princ (strcat"\n当前工作模态切换为:"(cadr(nth n lst1))))
(princ)
)
6.一些用到的函数以及全局变量
;;;全局变量
(setq *xty-acobj* (vlax-get-acad-object));_cad本身
(setq *xty-mnugs* (vlax-get-property *xty-acobj* 'MenuGroups));_菜单组集合
;;;=============================================
;;;      通用函数 将字符串以给定Key分解成表
;;;参数:Str------字符串
;;;      Key------分隔符
;;;返回值 字符串表
(defun xty-str-ToLstBy (Str Key / i s lst)
(while
    (setq i (vl-string-search Key Str))
   (setq
       s   (substr Str 1 i)
       Str
   (substr Str
       (+ 1
          (strlen key)
          (if i
      i
      0
          )
       )
   )
       Lst (cons s Lst)
   )
)
(vl-remove "" (reverse (cons str Lst)))
)
;;;=============================================
;;;      通用函数加前导0
;;;参数: str-------字符串
;;;       n---------加零后字符串长度
;;;返回值:加前导零后字符串
(defun xty-tr-add0 (str n)
(setq n (- n (strlen str)))
(repeat n (setq str (strcat "0" str)))
str
)
7.存在的问题,修改acad默认菜单是比较危险的事情,我现阶段的编程水准导致我无法解决该问题。我在CareFromOldXia.mnu中预留了pop0,
(write-line "***POP0" f);_这里是为其它程序预留的,可以删掉
(write-line "**SNAP" f);_这里是为其它程序预留的,可以删掉
(write-line "" f);_这里是为其它程序预留的,可以删掉
也预留了函数
;;;=============================================
;;;      通用函数显示局部快捷菜单
;;;参数: mnugname--------要修改的菜单组名
;;;       mnuname---------要修改的菜单名
;;;       itemlst-----要修改的菜单项表
;;;返回值:无,显示快捷菜单
(defun xty-mnu-local(mnugname mnuname itemlst)
(xty-mnu-changepop mnugname mnuname itemlst)
      (menucmd "P0=CareFromOldXia.POP0")
      (menucmd "P0=*")
)
但是无法找到右键弹出菜单的方法,反应器也不行,好像采用了cuix以后的版本都将右键默认菜单固定为acad.cuix。8.用到的BMP文件,可根据自己需要自定义




x_s_s_1 发表于 2022-3-29 15:02:14

e2002 发表于 2022-3-29 11:24
看起来似乎是:点击了1234567这个工具栏上的某个图标,然后切换为对应的右键菜单?如果理解错误请谅解。

...

确实是点击某个图标,然后切换右键菜单。专业所致,在某个工作状态下,使用的命令大部分是重复的,搞个大面板难得找,而且只是在切换工作状态的时候才点工具栏(1.2.3.4.5...)。和ribbon的意思差不多,不过我平时ribbon是关的,节省显示区域,只有某个工作状态才打开,两个显示器都不蛮够用。

e2002 发表于 2022-3-29 11:24:54

本帖最后由 e2002 于 2022-3-29 11:26 编辑

看起来似乎是:点击了1234567这个工具栏上的某个图标,然后切换为对应的右键菜单?如果理解错误请谅解。

我觉得都直接点击了图标,直接显示出一个弹出菜单列表,然后选择即可,为啥还要再去点击右键才选择呢?
而且右键菜单本来就有各种功能。

或者直接做到ribbon中去更加简单。

x_s_s_1 发表于 2022-3-28 09:27:48

本帖最后由 x_s_s_1 于 2022-3-28 09:29 编辑

AndyWang 发表于 2022-3-28 09:25
支持,楼主厉害了。你那小面板有兴趣,不知是否可以分享下。
一楼已经分享了所有代码了啊,根据自己的需求去改相关文件名称和ini文件就行了,需要个性化设置的地方我都特殊标示了.

x_s_s_1 发表于 2022-3-27 17:39:57

一楼以备不时之需

paulpipi 发表于 2022-3-27 19:55:11

看起来好牛呀,支持

999999 发表于 2022-3-28 08:48:06

顶起,,厉害了大神

AndyWang 发表于 2022-3-28 09:25:59

支持,楼主厉害了。你那小面板有兴趣,不知是否可以分享下。

AndyWang 发表于 2022-3-28 09:32:46

x_s_s_1 发表于 2022-3-28 09:27
一楼已经分享了所有代码了啊,根据自己的需求去改相关文件名称和ini文件就行了,需要个性化设置的地方我 ...

哦,我以为是用opendcl做的,这是用cuix实现的?

趣意人生 发表于 2022-3-28 09:53:09

顶起,,厉害了大神

海盗曹 发表于 2022-3-28 22:48:34

致敬大神,结构大佬~

mokson 发表于 2022-3-29 08:18:43

lisp 处理菜单功能,还是很弱的,没有相关的简便的模块。
页: [1] 2 3
查看完整版本: 【抛砖引玉】关于右键菜单,另类实现工具面板