明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 72799|回复: 172

[【高飞鸟】] 越飞越高讲堂(2)CAD的API编程指南(上)--DynamicWrapperX

    [复制链接]
发表于 2011-3-11 11:46:52 | 显示全部楼层 |阅读模式
本帖最后由 highflybir 于 2011-11-20 09:46 编辑

越飞越高讲堂(2)

CAD中如何利用API 编程呢?
对于arx来说,这点根本就不是问题,直接用api函数,因为它已经成了C++的内部函数了。对于VBA来说,也不太成问题。利用VBIDE中插入模块,申明API函数,就可以用了。对于VLISP来说,就需要借助其他工具了,譬如调用编译好的dll, 或者调用其他的例如EXCELVBA,或者调用CADVBA,都需要用读写文件的方式或者暂时写入VBIDE的方式,这方面的研究nonsmallaroom等都发表了帖子,研究得很详细了。下面我要用另外一种方式来实现它。

(上部)DynWrapX和VLISP中的API

首先申明:
此文属于首创,如需转载请说明来源和作者!
不用OpenDCL,不用VB和VBA,不用ARX,下面的一些你能做到吗?
你想使得你的对话框(我这里特指DCL)添加菜单吗?你想在你的DCL中添加真彩色图片或者做成各种特效,譬如渐变的背景?你想运用各种API函数为你的程序锦上添花吗?甚至完成以前不敢想象的事情?你想函数对参数传址使用么?你想得到比grread还强大的效果吗?你想创建一个非模态的DCL吗?甚至你想在LISP中嵌入汇编语言吗?等等。

如果你有了DynamicWrapperX这个插件,你什么都可以做了。

DynamicWrapperX 是一个ActiveX部件,它允许调用DLL库里面的函数,特别是API 的函数。可用于 Jscript和VBscript。它由汇编语言写成。短小精悍,才 13Kb,压缩后才5kb,比OpenDCL.arx甚至自己做的.dll文件都小很多,你甚至可以将它打包到vlx文件中。虽然它很小,但是很给力。
它可以极大程度地扩展LISP的编程范围,赋予DCL和VLISP更多功能。它可以适应不同的CAD版本,兼容windows98~windows 7。

首先给出这个插件的英文帮助和下载地址:
http://www.script-coding.com/dynwrapx_eng.html

我这里另贴上:
DynWrapX.dll 文件这个是DynamicWrapperX 插件
Win32API.txt  文件这个不是必需的,是api 函数的查看文件,api viewer用的WIN32API.TXT -- Win32 API Declarations for Visual Basic


如何在系统中注册:
在windows下有两种方法:
1.运行 regsvr32.exe  插件路径\dynwrapx.dll, 注册给所有用户;
2.运行 regsvr32.exe  /i  插件路径\dynwrapx.dll, 注册给当前用户;
如果你把它拷贝到system32目录下,直接运行 regsvr32.exe  dynwrapx.dll就可了。
反注册用 regsvr32.exe /u插件路径\dynwrapx.dllregsvr32.exe /u /i 插件路径\dynwrapx.dll
在windows 7 下,读者应该注意这点:需要以管理员身份注册运行。建议拷贝到其他目录注册运行。
http://support.microsoft.com/kb/827659

内部函数简介:
1.        Register( DllName, FuncName [, i=ParamTypes] [, r=RetValType] )
注册一个DLL中的函数,dllName,dll文件名,funcName,dll里面的函数名,i参数类型,r返回值类型。
2.        RegisterCallback( FuncRef [, i=ParamTypes] [, r=RetValType] )
注册一个回调函数,FuncRef按址引用的函数名,i参数类型,r返回值类型。
3.        NumGet( Address [, Offset] [, Type] )
得到某个指针的内容,Address指针地址,Offset偏移值,Type数值类型。
4.        NumPut( Var, Address [, Offset] [, Type] )
改变某个指针的内容,Var,要赋值的变量,Address指针地址,Offset偏移值,Type数值类型。
5.        StrPtr( Var [, Type] )
得到一个字符串的指针(实际也是创见一个指针的方法),var 字符串,type是类型
6.        StrGet( Address [, Type] )
读取某个指针的值,Address地址,type类型。
7.        Space( Count [, Char] )
创建指定长度和指定字符的字符串。Count,字符串长度,char指定的字符

创建、释放和注册函数:
创建:(setq wrap (vlax-create-object "DynamicWrapperX"))
释放:(vlax-release-object  wrap)
注册函数: (vlax-invoke  wrap  'Register  "user32.dll"  "MessageBoxW"  "i=hwwu" "r=l")
可以看出,这个甚至比VB中API函数的引用更简单。
;; 关于MessgeBox函数参见 http://baike.baidu.com/view/927800.htm

先创建几个下面用得着的对象
  1.   (setq *APP (vlax-get-acad-object))
  2.   (setq *DOC (vla-get-ActiveDocument *APP))
  3.   (setq hCAD (vla-get-hwnd *APP))
  4.   (setq hDOC (vla-get-hwnd *DOC))
  5.   (setq wrap (vlax-create-object "DynamicWrapperX"))


几个简单的例子:
  1.   ;; 例如一个简单的消息框
  2.   (vlax-invoke wrap 'Register "user32.dll" "MessageBoxW" "i=hwwu" "r=l")
  3.   ;; 'Register 注册;
  4.   ;; "User32.dll",可以省略为"USER32",也可以是自己的dll,例如"MyLib.dll";
  5.   ;; "MessageBoxW" ,API函数名字,功能是弹出一个消息框;
  6.   ;; "i=hwwu",是参数列表,见函数原型:
  7.   ;; int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT UType);
  8.   ;; h,父窗口句柄,w,宽字符,消息内容,w宽字符,标题文字,u,无符号整数,指的是消息框的类型
  9.   ;; "r=l"代表返回数值是整数。
  10.   (vlax-invoke wrap 'MessageBoxW hCAD "Hello,DynWrap" "Test for API" 2)
  11.   ;; 返回值代表如下:
  12.   ;; IDOK 1                    按下"OK"
  13.   ;; IDCANCEL 2                按下"取消"
  14.   ;; IDABORT 3          按下"放弃"
  15.   ;; IDRETRY 4           按下"重试"
  16.   ;; IDIGNORE 5           按下"忽略"
  17.   ;; IDYES 6                按下"是"
  18.   ;; IDNO 7           按下"否"
  19.   ;; IDCLOSE 8          按下"关闭"
  20.   ;; IDHELP 9                按下"帮助"

  21.   ;; 获得当前进程的命令行
  22.   (vlax-invoke wrap 'Register "kernel32" "GetCommandLine" "r=s")
  23.   ;; 这个函数没有参数,故而没有"i="
  24.   (vlax-invoke wrap 'GetCommandLine)
  25.   ;; 譬如返回:"C:\\Program Files\\AutoCAD 2006\\acad.exe\" 这样,我们就知道程序的所在目录和名称。

  26.   ;; 发出蜂鸣声
  27.   (vlax-invoke wrap 'Register "kernel32" "Beep" "i=uu")             ;蜂鸣声有返回值但可以不需要.
  28.   (vlax-invoke wrap 'Beep 800 1000)                              ;通过喇叭发出声音.


参数符号代表的类型:
l -  32位整数 - LONG, INT, LPARAM, LRESULT, etc, 范围: -2147483648 ... 2147483647;
u - 无符号32位整数 - ULONG, UINT, DWORD, WPARAM, ... , 范围: 0 ... 4294967295;
注意,在lisp中,无符号的整数如果超出2147483647 会溢出,例如(+ 2147483647 1)
返回-2147483648
h - 句柄 - HANDLE, HWND, HMODULE, HINSTANCE, HICON, ... , 范围: -2147483648 ... 4294967295;
p - 指针; 就是一个数值,对象或者字符串的地址。
n - 16位整数- 短整数, 范围: -32768 ... 32767;
t - 无符号16位整数- USHORT, WORD, WCHAR, OLECHAR, ... , 范围: 0 ... 65535;
c - 8位整数- CHAR, 范围: -128 ... 127;
b - 无符号8位整数- UCHAR, BYTE, ... , 范围: 0 ... 255;
f – 浮点数 - FLOAT;
d – 双精度数 - DOUBLE;
w - Unicode 字符串 - BSTR, LPWSTR, LPOLESTR, OLECHAR *, WCHAR *, ...;
s - ANSI/Windows 字符 (默认代码页) - LPSTR, LPCSTR, CHAR *, ...;
z - OEM/DOS字符(默认代码页) - LPSTR, LPCSTR, CHAR *, ...

返回值也是如此。但是我们在lisp中用到最多的是l数值型,可以代表指针,也可以代表长整数,短整数,甚至布尔值等等。
关于字符串的宽字符和ASCII字符,请读者自行参考相关资料。

RegisterCallBack方法:
鉴于LISP对于函数的地址取得的方式和对参数的保护模式,所以这个函数对LISP意义不大,略去。

其他方法:
NumGet( Address [, Offset] [, Type] )
从一个地址中获取数值。Address,基址,Offset偏移量,能用于循环读写一系列的数值。Type,数值类型,默认”l”,即长整数,只能小写字母。返回值就是这个地址中的内容。
NumPut( Var, Address [, Offset] [, Type] )
写入数值到内存中。Var,要写入的变量,剩下的几个参数跟NumGet相同。返回值是写入的字节数。
上面两个函数,允许你在基址占用的内存中存取数据(结构,数组等)。
StrPtr( Var [, Type] )
创建一个字符串指针,然后你可以在这个字符串占用的内存中存取数据(结构,数组等)。Var,是字符串变量或者常量,type是字符串类型,可以是”w”(默认方式),”s”,”z”。返回一个指针(即一个长整数)。
StrGet( Address [, Type] )
从指定地址中,读取字符串,并返回其拷贝。Address可以是数值变量的地址,也可以是字符串的首址,type 同StrPtr。
Space( Count [, Char] )
创建指定长度指定字符的字符串。Count,数量,Char,指定字符,如果没这个参数,指定字符就是空格。

下面是其用法例子:
  1.   ;; 取得某个地址的内容,例如读取字符串的ASCII代码
  2.   ;; 其实就是(vl-string->list "Hello, world! It's me.")
  3.   ;l 举这个例子仅仅是说明其用法。
  4.   (setq str "Hello, world! It's me.")
  5.   (setq sLen (strlen str))
  6.   (setq codes "")
  7.   (setq i 0)
  8.   (repeat sLen
  9.     (setq code (vlax-invoke wrap 'NumGet Str (* i 2) "t"))        ;乘以2是因为偏移必须是两个字节"t"
  10.     (setq codes (strcat codes (itoa code) " "))
  11.     (setq i (1+ i))
  12.   )
  13.   (alert codes)                                
  14.                                           
  15.    
  16.   ;; 读取并写入内存,例如反转字符串.
  17.   ;; 这个例子就是反转字符串。
  18.   ;; 对中文字符串要复杂些

  19.   (setq buf (vlax-invoke wrap 'Space sLen))                        
  20.   (setq pBuf (vlax-invoke wrap 'StrPtr Buf "s"))                ;获得缓冲区地址,用来读写
  21.   (setq i 0)
  22.   (setq j (1- sLen))                                                ;最后一个下标要字符串长度减1
  23.   (repeat sLen
  24.     (setq code (vlax-invoke wrap 'NumGet Str (* i 2) "t"))        ;从左到右读
  25.     (vlax-invoke wrap 'NumPut code pBuf (* j 2) "t")            ;从右到左写入缓冲区
  26.     (setq j (1- j))                                                ;偏移地址增加
  27.     (setq i (1+ i))                                                ;偏移地址减少
  28.   )        
  29.   (alert (vlax-invoke wrap 'StrGet pBuf))                        ;最后读取缓冲区内容


运用上面方法也可以用来通过改变地址内容改变变量值,即对函数参数的传址使用。

更精彩的在后面:

具体运用和实例剖析:
请见下面的完整的例子:其中已经有注释,包含了详细的解释。


在此特别感谢nonsmall,在编写这个程序过程中得到了他的很多帮助及其建议。

另外一些关于用LISP调用API的链接:

http://bbs.mjtd.com/forum.php?mod=viewthread&tid=72145&highlight=API
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=74063&highlight=API
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=60155&highlight=API
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=60884&highlight=API
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=84651&highlight=API

提醒:因为用到了API,可能会对内存有读写,所以编程前应保存工程。注意对内存的释放和存取可操作性。

多谢Caiqs的建议,"如果你有了DynamicWrapperX这个插件,你什么都可以做了。"这句话我夸大其词了,具体有哪些不能做的,请参考70楼。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

点评

楼主 DynamicWrapperX 在win7以上 64位系统注册用不了,另外如果在这样的系统下安装的cad2006(只有32位)和2012以上(64位的)这样好像也没有办法 32位和64位的cad都能用,是否有什么好办法呢?  发表于 2015-4-13 14:44
楼主:DynamicWrapperX 这个在win7 64位系统很难注册,你是否有什么好版本或好方法呢?  发表于 2015-4-10 11:48

评分

参与人数 8威望 +2 明经币 +7 金钱 +206 收起 理由
自贡黄明儒 + 1 + 30 很给力!
飞诗(fsxm) + 1 + 3 + 30 很给力!
alwtyp + 20
long9841 + 6
zark + 20
chlh_jd + 20 我从您这篇文章学起
redcat + 50 精品文章
Gu_xl + 1 + 3 + 30 highflybir 版主每回出手都不同凡响!精品!.

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

发表于 2011-9-2 11:05:57 | 显示全部楼层
本帖最后由 highflybird 于 2011-9-2 21:46 编辑
caiqs 发表于 2011-9-2 07:39
你甚至可以将它打包到vlx文件中,,乎悠,接着乎悠

不用OpenDCL,不用VB和VBA,不用ARX,

呵呵,忽悠,你言重了。所有关于这个插件的说明,我已经在帖子中说明了。
我并非要比较OpenDCL ,VB,VBA,和这个DynamicWrapperX 它们之间究竟谁强谁弱。
他们各有优劣,取长补短,才是编程的正确做法。
说实在话,这个控件是汇编加VC++,所以才显得功能强大而精悍。楼上可以看看它的源代码。但VBA,OpenDCL ,哪一个又不是由VC++编译形成的软件呢?
LISP如果不用ActiveX组件,不知道要少了多少功能。我极力赞成LISP中融汇其他语言,这样能极大程度地扩展LISP语言的功能。
有一点可能我说的夸张了:我说它什么都能做了。其实也不对。
它不能引用Arx或者C++的其他的类,不能设置ARX那样的回调函数,只能通过脚本来设置,而且有一定限制和不健壮。
它可以操作内存,但是不是所有的函数安全的。存在一定的风险。
它不能实现真正的多线程。
它的灵活性也欠缺,另外,效率不可能像C++或者VB 那样。因为它是通过ActiveX来引用的。
它不支持64位系统。
它必须要以管理员身份注册。等等这些都是它的缺点。
欢迎 Caiqs多提建议!


点评

你和神经病计较什么?  发表于 2023-5-29 21:55
回复 支持 1 反对 0

使用道具 举报

发表于 2011-9-3 00:03:55 | 显示全部楼层
本帖最后由 highflybird 于 2011-9-3 00:10 编辑
xshrimp 发表于 2011-9-2 23:59
其实把文件转换为二进制文本,用lsp打包 。问题早就讨论过了啊

我记得我最早是在nonsmall 托盘气泡提示程 ...


嗯,这个方法我也跟nonsmall讨论过,有一定局限性,特别对于cad2010-2012来说,支持得不是很好有兴趣的不妨实验一下:
如果各位非得要深究我的那个vlx 究竟怎么打包的,请看我下面的附件:
这种方法速度更快,文件可以更大,支持得更广。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 1 反对 0

使用道具 举报

发表于 2017-10-15 03:57:25 | 显示全部楼层
highflybird 发表于 2011-9-3 00:03
嗯,这个方法我也跟nonsmall讨论过,有一定局限性,特别对于cad2010-2012来说,支持得不是很好有兴趣的 ...

win7 64 下 无法创建  "ScriptControl"
(setq wsObj (vlax-create-object "ScriptControl"))
这一句返回的是nil
发表于 2011-3-11 13:36:21 | 显示全部楼层
高手又来了!支持!
 楼主| 发表于 2011-3-11 15:05:10 | 显示全部楼层
本帖最后由 highflybir 于 2011-3-13 00:32 编辑

颜色拾取对话框
例如,创建一个颜色拾取对话框,并得到返回值.
  1.   (setq str (vlax-invoke wrap 'space 36))   
  2.   (setq pBuf (vlax-invoke wrap 'StrPtr str))
  3.   (vlax-invoke wrap 'Register "comdlg32.dll" "ChooseColorA" "i=p" "r=l")
  4.           ;注册函数
  5.   (setq str (vlax-invoke wrap 'space 64))
  6.   (setq pColor (vlax-invoke wrap 'StrPtr str))   ;创建一个初始化颜色簇指针
  7.   (setq i 0)
  8.   (repeat 16
  9.     (vlax-invoke wrap 'NumPut 16777215 pColor i)
  10.     (setq i (+ i 4))
  11.   )
  12.   
  13.   (vlax-invoke wrap 'NumPut 36 pBuf)       ;lStructSize
  14.   (vlax-invoke wrap 'NumPut hCAD  pBuf 4)   ;hwndOwner
  15.   (vlax-invoke wrap 'NumPut 0  pBuf 8)    ;hInstance
  16.   (vlax-invoke wrap 'NumPut 0  pBuf 12)       ;rgbResult     默认黑色
  17.   (vlax-invoke wrap 'NumPut pColor  pBuf 16)   ;*lpCustColors 全部初始化为白色
  18.   (vlax-invoke wrap 'NumPut 387 pBuf 20)   ;Flags;
  19.   (vlax-invoke wrap 'ChooseColorA pBuf)    ;打开颜色拾取对话框
  20.   (setq colorNum (vlax-invoke wrap 'NumGet pBuf 12))  ;得到颜色号
  21.   (setq colorRGB (number->rgb colorIndex))   ;转换成RGB
  22.   ;;;RGB函数跟CAD的rgb是相反的
  23.   (defun RGB (R G B)
  24.     (+ (lsh B 16) (lsh G 8) R)
  25.   )
  26.   (defun Number->RGB (C)
  27.     (list (lsh (lsh C 24) -24)
  28.           (lsh (lsh C 16) -24)
  29.    (lsh C -16)  
  30.     )
  31.   )


播放音乐
  1.   ;;播放mp3音乐
  2.   ;;这个是引用winmm.dll的例子,用来播放mp3音乐相当简单
  3.   (vlax-invoke wrap 'Register "winmm.dll" "mciSendString" "i=ssll" "r=l")
  4.   (vlax-invoke wrap 'mciSendString "close temp_alias" "" 0 0)
  5.   (vlax-invoke wrap 'mciSendString "open C:\\TEMP\\Test.mp3 alias temp_alias" "" 0 0)
  6.   (vlax-invoke wrap 'mciSendString "play temp_alias" "" 0 0)


获取系统信息
  1.   ;;获取系统信息,比脚本更简单
  2.   (setq str (vlax-invoke wrap 'space 36))   
  3.   (setq pBuf (vlax-invoke wrap 'StrPtr str))
  4.   (vlax-invoke wrap 'Register "kernel32" "GetSystemInfo" "i=l")
  5.   (vlax-invoke wrap 'GetSystemInfo pBuf)
  6.   (vlax-invoke wrap 'NumGet pBuf 20)    ;获取CPU个数
  7.   (vlax-invoke wrap 'NumGet pBuf 24)    ;获取CPU型号


网页有关   
  1. ;;下载网页或者图片
  2.   ;;有了这个函数,使得下载变得很简单
  3.   (vlax-invoke wrap 'Register "urlmon" "URLDownloadToFile" "i=lssll" "r=l")
  4.   (setq nUrl http://bbs.mjtd.com)
  5.   (setq fName "c:\\2.html")     ;下载网页
  6.   (vlax-invoke wrap 'URLDownloadToFile 0 nUrl fName 0 0)        
  7.   (setq nUrl http://www.baidu.com/img/baidu_logo.gif)
  8.   (setq fName "c:\\1.gif")     ;下载图片
  9.   (vlax-invoke wrap 'URLDownloadToFile 0 nUrl fName 0 0)

取得对话框或者窗口尺寸
  1. (vl-load-com)
  2. (defun c:ttt (/ WRAP)
  3.   (setq wrap (vlax-create-object "DynamicWrapperX"))   ;Create a DynamicWrapperX object instance
  4.   ;;Register API functions
  5.   (vlax-invoke wrap 'Register "USER32" "FindWindowW" "i=ww" "r=l")
  6.   (vlax-invoke wrap 'Register "USER32" "GetWindow" "i=ll" "r=l")
  7.   (vlax-invoke wrap 'Register "USER32" "GetWindowRect" "i=lp" "r=l")
  8.   (vlax-invoke wrap 'Register "USER32" "GetClientRect" "i=lp" "r=l")
  9.   ;;Load the DCL
  10.   (vl-catch-all-apply 'DCL_Load (list wrap))
  11.   (vlax-release-object wrap)
  12.   (princ)
  13. )
  14. ;;;Main procedure
  15. (defun DCL_Load (wrap / DCL_FILE DCL_ID DIALOG_RETURN HWND BWND)  
  16.   (setq dcl_id (load_dialog (setq Dcl_File (Write_Dcl))))   ;Load dialogue
  17.   (vl-file-delete Dcl_File)      ;then delete the temporary .dcl
  18.   (setq Dialog_Return 2)
  19.   (while (> Dialog_Return 1)      ;if it is not ended
  20.     (new_dialog "DCL" dcl_id)      ;then create a new dialogue by DCL_ID
  21.     (setq hwnd
  22.     (vlax-invoke wrap
  23.       'FindWindowW "adesk_dlg0000" "DynWrapX 对话框"))  ;the handle of dialogue
  24.     (setq bwnd (vlax-invoke wrap 'GetWindow hwnd 5))   ;the handle of button
  25.     (action_tile "A" "(GetWindowSize 'GetWindowRect bwnd wrap))") ;action of "GetButtonSize" button
  26.     (action_tile "B" "(GetWindowSize 'GetWindowRect hwnd wrap))") ;action of "GetWindowSize" button
  27.     (action_tile "C" "(GetWindowSize 'GetClientRect hwnd wrap))") ;action of "GetClientSize" button
  28.     (setq Dialog_Return (start_dialog))     ;show dialog
  29.     (princ)
  30.   )
  31.   (unload_dialog dcl_id)      ;unload dialog
  32.   (princ)        ;silent quit
  33. )
  34. ;;;get the size of window
  35. (defun GetWindowSize (symbol hwnd wrap / str ptr Ret left top right bottom)
  36.   (setq str    (vlax-invoke wrap 'Space 16))
  37.   (setq ptr    (vlax-invoke wrap 'StrPtr str))
  38.   (setq ret    (vlax-invoke wrap symbol hwnd ptr))
  39.   (setq left   (vlax-invoke wrap 'NumGet ptr))
  40.   (setq top    (vlax-invoke wrap 'NumGet Ptr 4))
  41.   (setq Right  (vlax-invoke wrap 'NumGet Ptr 8))
  42.   (setq bottom (vlax-invoke wrap 'NumGet Ptr 12))
  43.   (alert (vl-princ-to-string (list (- right left) (- bottom top))))
  44. )
  45. ;;;make a .DCL file,and get its name
  46. (defun Write_Dcl (/ Dcl_File file str)
  47.   (setq Dcl_File (vl-filename-mktemp nil nil ".Dcl"))
  48.   (setq file (open Dcl_File "W"))
  49.   (foreach str '("DCL:dialog"
  50.    "{"
  51.    " label = "DynWrapX 对话框";"
  52.    " spacer_1;"
  53.    " :button"
  54.    " {"
  55.    "   key = "A" ;"
  56.    "   label = "取得此按钮尺寸" ;"
  57.    " }"
  58.    " :button"
  59.    " {"
  60.    "   key = "B" ;"
  61.    "   label = "取得对话框尺寸" ;"
  62.    " }"
  63.    " :button"
  64.    " {"
  65.    "   key = "C" ;"
  66.    "   label = "取得客户区尺寸" ;"
  67.    " }"
  68.    " width = 30;"
  69.    " height = 10;"
  70.    " spacer_1;"
  71.    " ok_cancel_help;"
  72.    " spacer_1;"
  73.    "}"
  74.   )
  75.     (write-line str file)
  76.   )
  77.   (close file)
  78.   Dcl_File
  79. )





发表于 2011-3-11 15:59:48 | 显示全部楼层
要储备一些VB知识
发表于 2011-3-11 21:09:01 | 显示全部楼层
大哥,偶太佩服你了...如黄河之水啊...  
真的是人品水平双百分
向你高超的水平更向你博大的胸怀致敬!
发表于 2011-3-11 21:22:50 | 显示全部楼层
每次都是石破天惊之作
发表于 2011-3-11 21:53:18 | 显示全部楼层
Highflybird兄,真佩服你~
发表于 2011-3-12 08:22:37 | 显示全部楼层
楼主真让我们长知识了!THKS!
发表于 2011-3-12 13:45:05 | 显示全部楼层
果然是highflybir出马,一个顶两
发表于 2011-3-12 13:59:37 | 显示全部楼层
如果稳定的话,那真是VisualDCL了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-16 20:54 , Processed in 0.205952 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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