1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AutoLISP で MsgBox や InputBox もどきを使う

Last updated at Posted at 2023-03-27

AutoCAD の LISP でダイアログの UI を作るのは面倒

AutoCAD で簡単なツールを作るのに便利なのが AutoLISP ですが、ユーザとの入出力は、作図領域かコマンドライン領域で行う事が殆どです。
一応、ファイル選択ダイアログは用意されていますし、簡単なメッセージなら、(alert "出来た!") とかアラートダイアログで表示できます。
しかし、

  • メッセージを表示して、ユーザーに「OK」か「Cancel」を選択させる (VBA で言う MsgBox)
  • メッセージを表示して、ユーザーに文字を入力させる (VBA で言う InputBox)

という、ごく単純なダイアログが欲しい時があります。

LISP でダイアログを表示するには、DCL を使う

LISP でダイアログを表示するには、DCL (ダイアログ・コントロール・ランゲージ) で記述されたファイルを用意し、それを LISP からロードして使います。
しかし、MsgBox や InputBox を使うためだけに、都度 DCL ファイルを用意するのは馬鹿らしいわけです。

別途 DCL ファイルを用意せずに、MsgBox や InputBox を使えるようにする

というわけで、関数内で DCL を生成し、目的を果たしたら DCL を消すような関数を作ればよいわけです。

MsgBox もどき

MsgBox もどき
;;;***************************************************
;;;
;;;  MsgBox関数
;;;
;;;***************************************************
(defun msg_box(
  str_label
  /
  dcl_file
  dcl_fnum
  ret_val
  ret_num
  )

  ;dclファイル名生成
  (setq ret_val "" dcl_file (vl-filename-mktemp "input_box.dcl"))
  ;dclファイル作成
  (setq dcl_fnum (open dcl_file "w"))
  (foreach str_tmp
    (list
      "inputbox : dialog"
      "{"
      "  label = \"InputBox\";"
      "  : text {"
      (strcat "    label = \"" str_label "\";")
      "  }"
      "  ok_cancel;"
      "}"
    );list
    (write-line str_tmp dcl_fnum)
  );foreach
  (close dcl_fnum)
  ;ダイアログをロードする
  (setq dcl_fnum (load_dialog dcl_file))
  (if (new_dialog "inputbox" dcl_fnum)
    (progn
      (action_tile "accept" "(done_dialog 1)")
      (action_tile "cancel" "(done_dialog 0)")
      (setq ret_num (start_dialog))
      (unload_dialog dcl_fnum)
      (if (zerop ret_num)
        (setq ret_val nil)
        (setq ret_val T)
      );if
    );progn
  );if
  ;dclファイルの削除
  (vl-file-delete dcl_file)
  (progn ret_val)

);defun

MsgBox 表示の用の DCL ファイルを作成・ロードし、引数で渡したメッセージを表示します。
「OK」が押されたら真、「Cancel」が押されたら偽が返ります。
注意点は、引数の文字列には\nの改行は使えません

InputBox もどき

InputBox もどき
;;;***************************************************
;;;
;;;  InputBox関数
;;;
;;;***************************************************
(defun input_box(
  str_label
  str_edit
  /
  dcl_file
  dcl_fnum
  str_tmp
  ret_val
  ret_num
  )

  ;dclファイル名生成
  (setq ret_val "" dcl_file (vl-filename-mktemp "input_box.dcl"))
  ;dclファイル作成
  (setq dcl_fnum (open dcl_file "w"))
  (foreach str_tmp
    (list
      "inputbox : dialog"
      "{"
      "  label = \"InputBox\";"
      "  : text {"
      (strcat "    label = \"" str_label "\";")
      "  }"
      "  : edit_box {"
      "    key = \"input_text\";"
      "    edit_width = 50;"
      "  }"
      "  ok_cancel;"
      "}"
    );list
    (write-line str_tmp dcl_fnum)
  );foreach
  (close dcl_fnum)
  ;ダイアログをロードする
  (setq dcl_fnum (load_dialog dcl_file))
  (if (new_dialog "inputbox" dcl_fnum)
    (progn
      (action_tile "accept" "(setq ret_val (get_tile \"input_text\"))(done_dialog 1)")
      (action_tile "cancel" "(done_dialog 0)")
      (set_tile "input_text" str_edit)
      (setq ret_num (start_dialog))
      (unload_dialog dcl_fnum)
      (if (zerop (* ret_num (strlen ret_val)))
        (setq ret_val nil)
      );if
    );progn
  );if
  ;dclファイルの削除
  (vl-file-delete dcl_file)
  (progn ret_val)

);defun

InputBox 表示の用の DCL ファイルを作成・ロードし、ダイアログを表示します。
引数の内容は下記の通り。

  • 第一引数は、TextBox の上部に表示されるメッセージ(\n不可)
  • 第二引数は、TexyBox 内に記入される文字(\n不可)

「OK」を押下時に TextBox 内に文字が記載されていれば、その文字が返ります。
「Cancel」が押されるか、「OK」押下時に TextBox の内容が空なら、偽が返ります。
コマンドラインへの入力に対して、この InputBox を用いる利点は、"\を直接入力できることです。
コマンドラインに記載するときは、\"\\と記載しなければならないのですが、それを考慮しなくてよくなります。

マルチテキスト(MTEXT) の書式コード付き文字を直接編集する

AutoCAD のマルチテキストオブジェクトは、一つの文字オブジェクト内で改行したり、文字の大きさを変えたり、文字に色を付けたりと、文字の書式を変更できるのが便利なのですが、プロパティを見ると分かる通り、文字に付与された書式情報は書式コード文字列として付与される形になっています。
モノとして近いのは、Rich Text Format でしょうか? { } で囲う所とか、仕様も近いと思われます。
マルチテキストの標準エディタ「マルチテキストエディタ」で編集する際には、書式コードが見えない状態での編集になりますが、マルチテキストのエディタを外部エディタに変更すると、この書式コードを直接編集できます。
しかし、書式コードは可読性は低いため、普段は標準の「マルチテキストエディタ」を使用したいけど、細かい調整時に直接書式コードを編集したい場合は、その都度エディタの切り替えを行うのも面倒です。
そこで、先刻の InputBox ルーチンを使用して、MTEXT の書式コード付き文字列を直接編集するコマンドを作成してみましょう。

MTEXT の書式コード付き文字を直接編集するコマンド
;マルチテキストの装飾文字付文字列を、そのまま充てるコマンド(要 input_box)
(defun C:EDIT_MTEXT_VALUE (
  /
  ename
  elist
  str_text
  ret_val
  )

  (if
    (and
      (setq ename (entsel "MTEXTオブジェクトを選択"))
      (setq ename (car ename))
      (setq elist (entget ename))
      (equal "MTEXT" (cdr (assoc 0 elist)))
    );and
    (progn
      (setq str_text (cdr (assoc 1 elist)))
      (setq ret_val (input_box "MTEXTの文字を編集" str_text))
      (if ret_val
        (entmod (subst (cons 1 ret_val) (assoc 1 elist) elist))
      );if
    );progn
  );if
  (princ)

);defun

マルチテキストの「文字内容」は、何故プロパティから編集できない?

Autodesk は、何故プロパティの「文字内容」を直接編集できないようにしたんでしょうか?
矛盾した書式コードを記載する事で、データが破損する可能性があるからでしょうか?
しかし、下記の Autodesk のヘルプの様に、外部エディタで書式コードを直接記入する事を、拒んでいるわけではなさそうです。

データ破損の件で言えば、TrustedDWG の話を思い出します。
Autodesk 社以外のアプリが作成したDWG ファイルには、TrustedDWG のフラグが立っていない為、Autodesk 社のアプリで開くと警告が出るようになっています。
Autodesk 曰く非TrustedDWG はファイルとしての互換性が保証されないので、最悪破損してしまう可能性もあるとの事ですが、TrustedDWG のフラグが出来る前のバージョンの AutoCAD アプリケーション(確か 2004) で、LISP 等のツールを使用せずに、通常オペレーションだけで作成した DWG ファイルが、AutoCAD から開けなくなり、ダメもとで互換 CAD で開いて保存し直したら、再び AutoCAD から開けるようになった経験がある私としては、Autodesk 社のアプリが作る DWG だから大丈夫とは、とても言えないんじゃないかなぁ、と思ってしまう訳です。
しらんけど。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?