2014年4月15日 星期二

Visual Lisp 輸入 呼叫對話盒



Visual Lisp 程式有個視窗介面是很體面的,事實上程式規模發展到一個階段,也不可能只靠命令列的問答來輸入,Visual Lisp 也提供視窗介面,在 Windows 程式中這種程式分類為 FORM (表單),基本上 VB (VBA) 也是,另外一種就是類似 AutoCAD 或是 WORD 以工作空間為主,搭配選單、工具列、狀態列等等。
如何使用視窗介面,這話說來就長了,首先當然要有對話盒的定義,在 Visual Lisp 中定義會儲存在副檔名為 DCL 檔案中,先不提,先來看看在 VL 中如何呼叫對話盒。

需要幾個函數組合,還是拿型鋼剖面函數作例子

(setq dcl_ID (load_dialog "HSteelR3.dcl"))
(if( not (new_dialog "HSteelR3" dcl_ID))
(exit)
)

上面程式中將 HSteelR3.dcl 這個檔案載入,並取得對話盒識別代碼 dcl_ID,再來將 HSteelR3.dcl 中定義 HSteelR3 對話盒建立 (換句話一個 DCL 檔可以定義好幾個對話盒),當然如果載入失敗,程式便終止,如果要人性化一點,在執行 (exit) 前可加一句警告,用 (alert) 就可以了。

      中間有很多動作,如設定初始值,設定對話盒的反應動作,例如最簡單的,當使用者按下取消,則程式要進行結束動作,這些以後再談。

再來
(start_dialog)
(unload_dialog dcl_ID)

執行到 (start_dialog) 對話盒便出現在 AutoCAD 程式中與使用者互動,最後 (unload_dialog dcl_ID) 釋放對話盒定義。
程式可一層一層呼叫對話盒,沒記錯可以有八層,不過太多層對話盒會混亂,二至三層對話盒呼叫應該是合理的。

至於 DCL 檔案如何製作,有個不幸的消息,它也跟 Visual Lisp 一樣是用鍵盤敲進去的 (VLIDE ),我用過 VC++, Matlab, VBA,通通是視覺化操作,拉一拉對話盒就完成了,只能說 XX 比雞腿,對岸有人在搞視覺化這檔事,可惜我拿不到手,不過我要說的是,比起在編寫程式所花的時間,寫寫對話盒定義占的比例並不大。

2014年4月14日 星期一

Visual Lisp 輸入 讀寫資料檔

VL 的文字檔案讀寫,基本上與其他程式差距不大 (C, Fortran, ...)

步驟如下

1. 取得檔案檔名跟路徑 (可以用對話盒選取,非必要)
        使用對話盒選取路徑及檔名使用 (getfiled) 函數,可以開啟標準檔案選取對話盒   
     函數定義 (getfiled title default ext flags)
             title 是對話盒標題
             default 是預設路徑或檔案名稱
             ext 是延伸檔案名稱
             flags 控制對話盒行為之旗標
 
    例如在我的程式集中型鋼剖面程式程式碼是
        (setq file (getfiled "儲存檔案" path "hst" 1))
    執行後之對話盒如下
 
     注意變數 path 是已經儲存的路徑,否則每次都從根目錄
開始找檔案,會累死人的,這個變數的儲存地點是在 AutoCAD
 的 acad*.cfg 檔中,是使用(setcfg) 及 (getcfg) 兩個函數進行
操作, 它可以將變數獨立儲存於程式之外,當然,如果只是要
路徑,那麼檔名需除去 。
file 變數自然是儲存傳回之路徑及檔名,注意,如果的程式
路徑檔名是用程式內建,路徑斜線用兩次 如 D:\\ 或是 D:/
2. 進行案開啟動作,傳回檔案旗標
    (open file "r") (open file "w") (open file "a")
    r : read
    w : write
    a : append
   三個參數應該不用解釋太多
   注意要設定一個變數,例如 f 接收傳回值,有兩個目的
       一是判定檔案是否被選取,若沒有 f 為 nil,避免繼續執行讀寫動作
        二、讀寫函數需要此參數作為執行依據


3. 進行讀或寫動作
   (setq var (read-line f))
   (setq var (read-char f))
   (write-line var  f)
   (write-char var  f)
   寫入時注意變數 var 必須為字串,若是整數,實數則要轉換成文字,(rtos) (itoa) 為轉換函數,同樣的,讀取傳回也是字串,若需要轉換也需要 (atof) (atoi) 函數。

4. 關閉檔案
    (close f)

2014年4月10日 星期四

型鋼剖面程式

    這程式大概已經有十幾年的歷史,也沒啥大變動 (第 3 版),原理也很簡單,用 PLINE 指令一筆畫完,使用方法選取型鋼,按確定就完成了。





    程式可以畫剖面線加勁版及標示型鋼編號,也可以自訂型鋼斷面存檔以處理未列入 POP LIST 中的型鋼,如 W 或 BH 型鋼。

    當然,繪製角或槽鋼兄弟程式自然也有,大同小異罷了。


2014年4月7日 星期一

Visual Lisp 輸入 getkword 函數

       說 (getkword) 是一行函數,事實上是錯的,因為它通常和的搭檔 (initget) 一起出現,實務常常在使用者與程式互動需要限定使用者回覆限訂之訊息,例如程式要求使用者確認,於發出

 ARE YOU SURE?

的訊息於命令列上,但是你能確定使用者是按下 Y y N n 四個鍵嗎? 要如何做 ,先用 (initget)設定使用者所能輸入之字串

(initget "Y N")

再呼叫
(getkword "\nARE YOU SURE : (Y/N)")

程式執行至此,命令列上便出現

ARE YOU SURE : (Y/N)

    等待使者者輸入 Y y N n 四個字元,若是輸入別的字元,則會一直重複要求輸入,直到獲得限定字元後才會繼續向下執行。

    VL 程式內可利用 (getkword "\nARE YOU SURE : (Y/N)") 所傳回字元進行判斷使用者之意圖

    還有一個問題,事實上執行時若使用者只按下 ENTER,(getkword) 仍會接收到 nil 後向下執行,這不是函數設計之 BUG,事實上在 (initget) 函數可以設定防止按下 ENTER 選項,那這項 "失誤" 目的為何?

    我們使用程式時,有的選項幾乎佔大多數,最直覺的反應就是按下 ENTER 或 SPACE 鍵,換句話說 (getkword) 的預設選項可以設計成 ENTER,於是我們改寫如下

(getkword "\nARE YOU SURE : N / <Y>")

使用者看到的提示就成了

ARE YOU SURE : N / <Y>

    很自然的,知道按下 ENTER 就是 "Y" 的意思,而不用到處找 Y 鍵,那 (getkword) 收到 nil 怎麼辦,加個 (or) 函數就好了,下面的函數完整將前面的內容再整合一遍

(defun C:TEST( / s)
    (initget "Y N")
    (setq s (getkword "\nARE YOU SURE:N/<Y>"))
    (if (or (= s nil) (= s "Y"))
        (alert "Yes")
        (alert "No")   
    )        
)

2014年4月6日 星期日

Visual Lisp 輸入 getpoint 函數

    (getpoint) 函數明顯望文生義求使用者輸入一座標點  GET
 + POINT,執行它則要求使用者輸入一個點,可以從命令列
輸入座標點或是滑鼠左鍵點選。
 
再加上例如 (setq pt (getpoint)) 程式碼後,便可以儲存於 pt 
變數中。
 
 AutoCAD 輔助說明可知 getpoint 函數完整形式如下
 
    (getpoint [pt] [msg])
 
    後面有兩個方括號 [pt], [msg] 是選擇性輸入之參數,[msg]
為呈現在命令列給用者之提示,例如 "Input the Point :\n" 
 "點選放置點\n" (: \n 為跳行控制)
 
    [pt] 這個參數比較有意思,他會由 pt (當然必須有意義之點)
拉一條橡皮筋,在使用者輸入第二點前隨著滑鼠到處跑,講的
好像很玄,其實你用 COPY, MOVE 指令就可以看到這條橡皮
筋,它可以給使用者兩個點相對位置之提示。
 
最後提一個技巧,使用者可能在執行程式時,未輸入點位便按
 ENTER 或按了滑鼠右鍵 (也是 ENTER),則輸入便會失敗
,程式可改寫如下
 
(while (= nil (setq pt (getpoint "Input A Point :\n")))
    (princ "Incorrect, Please ")
)

加個 while 迴圈,第一次執行時會要求使用者輸入一個點

指令: Input A Point:
 
若使用者輸入點,則迴圈跳出繼續往下執行
若使用者按下 ENTER,則 pt 會被設定為 nil,符合 while 
件進入下一行執行,此時 (princ) 函數在命令列輸出
 
指令: Incorrect, Please
 
再跳回 while 迴圈執行 (getpoint "Input A Point :\n"),此時命
令列補上 Input A Point : (基本上你不會發現這個間隙),於是
使用者看到
 
指令: Incorrect, Please Input A Point :
 
再度要求使用者輸入一個點,直到 pt 有值為止,當然其他
(getstring) (getint) (getreal) (getkword) ... 家族函數均可如法炮製。

2014年4月4日 星期五

AutoCAD 的輸入

AutoCAD 輸入方式有那幾種?

    鍵盤滑鼠數位版 (What is this?,想起以前 MicroStation 時代,這可是必備良藥)

    在這裡不是談這個,畢竟這裡不是 CAD 繪圖訓練教室,來談談 Visual Lisp (VL) 程式如何得到使用者輸入資訊,想一想應該有以下幾種方式

  • 鍵盤
  • 滑鼠
  • 對話盒
  • 資料檔
  • 應用程式 (EXCEL)

鍵盤
   AutoCAD  高手喜歡用鍵盤下指令,標準動作是右手拿滑鼠,左手按鍵盤,滑鼠按鈕跟選單太慢,如果再改改 pgp 檔就更炫了,VL 中有一個 (getXXX) 家族,例如 (getreal) 就是get + real ,自然就要求使用者輸入一個實數。
    當然鍵盤上它的鍵也能偵測到,可以賦予其他功能。
  

滑鼠
   滑鼠有兩個功能,一個是 WINDOWS 跟 AutoCAD 系統的操作,像是選單、對話盒點選
     另一個是繪圖區的輸入,包括點座標的取得,VL 以 (getpoint) 函數要求使用者在螢幕上選取點位,滑鼠還有另一個輸入功能為選取圖元,所有編輯指令都要有這著動作。

對話盒
   
   VL  提供 DCL  檔案 (同樣在 AutoCAD 的 VLIDE 中編輯),在 VL 中呼叫,在我的程式集中有很多對話盒的例子,就使用者的觀點,對話盒溝通性較多也較廣,鍵盤輸入資料僅限於小規模或簡單溝通的程式,資料一多鍵盤使用就變的困難。

 
資料檔 
    VL 可以開啟文字檔,讀取文字資料,基本上也是 (open) 檔案和 (read-line) 函數運作,當然寫入資料檔也沒問題。

 應用程式 
    這裡講的就是 EXCEL,搞工程的跟 EXCEL 應該都是一輩子的糾纏,AutoCAD 能跟 EXCEL 連結應該都是工程師(或是老板)的夢想。VL 中除了傳統的函數,vla 函數 (vlax-xxx) 開啟了這條溝通之路,老實說 vl 函數我並不在行,但有熱心的人願意花時間寫些小工具開放給大家使用,也算是功德無量。


     寫到這裡,想不到 Visual Lisp 輸入的題目這麼大,以後我會用  VL輸入 DCL 兩個標籤來提供些經驗。


2014年4月1日 星期二

IDE 中除錯

話說,誰寫程式能一次 OK
軟體工程師常來說明入錯行的例子就是沒日沒夜的除錯生涯

既然 AutoCAD 提供整合開發環境,自然就有包含除錯功能
LISP  是直譯式語言,不需編譯
載入時最多檢查一下括弧配對一些基本語法
要如何操作除錯呢?

土法煉鋼法

用 (princ "變數") 或是 (alert "變數") 在程式執行時輸出,(alert) 函數還能中斷程式執行,因為要按確定才會繼續,注意"變數"型式為字串(string)。

名門正派法 (自然有請 HELLO WORLD 出場示範)

1 . 在預定暫停處按 F9 可設定截斷點 (圖中紅色方塊處,再按一次可取消)


2 . 載入它


3. 跳回 AutoCAD 執行,此程式要輸入 HW (注意不要用選單或按鈕 (load "HW.LSP")函數去載入 )

4. 程式執行至截斷點處會暫停,程式碼會反白


5. 如果要看變數 s 的值,將游標光棒移到 s 處,按滑鼠右鍵出現浮動選單,選擇加入觀看(W)...


6. 出現觀看視窗,此時因為中斷點在 (setq s "HELLO WORLD")  左括號變數 s 還未設定值所以 S = nil (註LISP 變數不分大小寫,nil 即是 null)


7. 若按下 F8 則執行下一行 (setq s "HELLO WORLD"),此時變數 s 有設定值 S = "HELLO WORLD"




IDE 除錯控制流程之按鈕在此 (除錯模式下才會亮顯)


看圖識字一下應可了解各種功能,若要中斷程式執行按紅框內最右邊鈕即可。