- 在VFP中如何历遍所有文件夹和文件
在VFP中,能象一些杀毒软件那样,找遍磁盘的所有文件夹和文件吗? 答案是肯定的,而且很简单: *利用VFP的Create Cursor -SQL命令建立有5个字段的临时库 *结合前面提到的ADIR()函数便可完成。 下面是具体代码:
dqml='C:' &&需扫描的盘符 use Create Cursor mylsdbf (wjmc c(120),wjcd n(10),wjrq d,wjshj c(10),wjsx c(6)) xGS=1 xCD=0 append BLANK REPL wjmc WITH dqml do while !eof() nRecn=Recn() dqml=allt(wjmc)+'\' x=adir(Mysz,(dqml+'*.*'),'rashd') if x<>0 for I=3 to x Mysz(I,1)=dqml+Mysz(I,1) xGS=xGS+1 xCD=xCD+Mysz(I,2) endf append from array Mysz for allt(wjmc)<>'.' AND allt(wjmc)<>'..' and 'D'$wjsx endi go nRecn skip endd use
这里有以上例子的源代码实例下载
- 在VFP如何利用低级文件操作函数读取*.INI文件
VFP为我们提供了16个低级文件操作函数,充分利用这些函数,几乎可对所有文件进行本来只有汇编、C等语言才能进行的操作。 *.INI文件其实也是ASCII码文本文件,只不过有其特定的规律而已。 下面以读取system.INI中[boot.description]关键字里的mouse.drv标识符中的值为例来说明:
nPath_ls=fullpath('command.com',2) nPath=strtran(nPath_ls,'COMMAND.COM','system\') &&取得Windows\system\的目录名 dkwjm=nPath+'system.ini' &&需打开文件的路径和文件名 Fp=Foren(dkwjm,0) &&以只读(默认方式0可以不用)打开文件 if Fp<0 wait wind '打不开您指定的文件' retu endi do while !Feof(Fp) wjnr=Fgets(Fp) &&从打开的文件中读取一行 if atc('mouse.drv',wjnr)=1 exit endi endd =Fclose(Fp) &&关闭打开的文件 x=atc('=',wjnr) nQdz=iif(x>1,suns(wjnr,x+1),'') &&nQdz='标准鼠标'字符串 retu
我只不过是说明如何运用VFP提供的这些函数,至于如何建立和改写文件,为何用Fgets()来读取数据而不用Fread()来读取数据等,可以查阅VFP帮助。VFP3.0的帮助是一本很好的中文教科书。
- 如何改变文件的最后修改日期和时间
在WINDOW 9X下我们没办法来改变一个文件的日期和时间,那在VFP能办到吗? 在WINDOW 9X下文件的日期和时间有创建、修改和访问三种,在通常情况下我们所说的文件日期和时间指的是修改这一项。 那在VFP下如何改文件日期和时间呢: Fp=Foren('需打开的文件',2) &&以读写方式打开文件 if Fp<0 wait wind '打不开您指定的文件' retu endi wjnr=Fread(fp,1) &&从打开的文件头中读一个字节到wjnr =Fseek(Fp,0,0) &&将文件指针移到文件头(回到原来的位置) =Fwrite(Fp,wjnr,1) &&向打开的文件头中写入一个字节 =Fclose(Fp) &&关闭打开的文件
即把读取的那个字节原封不动的再写入文件,从而达到了将当前系统 的日期和时间来改写文件的日期和时间目的。
如何在程序的开始检测权限和根据权限操作
-
在一个程序的开始部分,如何根据不同的口令字来区分不同的登权限,各自的 口令字和权限设置又如何加以保密,以防止非法查看和修改? 我们辛辛苦苦编制的程序又如何根据每台机器的硬件来加以判断用户的合法 与非法,以防止非法拷贝? 针对以上问题,我编制了一个简单的程序实例供有兴趣的朋友参考。
该实例并非十分完美,也很简单,意在提供一种思路,大家可根据自己的情 况,加以完善。 实例共有一个数据表和四个模块组成,分别是: 一、KLK.DAT 这是经过vfpjmdbf.vcx加密后的数据表,解密后的表结构如下: ======================================================== 表文件名: KLK.DBF 数据记录数: 3 最近更新的时间: 10/17/1999 代码页: 936 字段 字段名 中文含义 类型 宽度 小数位 索引 排序 1 BH 编号 字符型 2 2 XM 姓名 字符型 8 3 PASSKL 口令字 字符型 12 4 QX 权限 数值型 1 5 VARJB 硬盘卷标 数值型 12 ** 总计 ** 36 =========================================================
二、Main.prg 系统初始化主程序,大家在调试时务必首先运行它,否则后面的模块无法运行。 它很简单: set stat off set scor off set date ansi set century on set hours to 24 set escape off set dele on set safe off SET STATUS BAR OFF SET SYSMENU TO SET SYSMENU AUTOMATIC on shutdown quit debug0=.t. &&为后面的模块提供检测菜单是否运行的条件 Dqml=sys(5)+sys(2003)+'\' &&取当前目录,调试时请您改为本程序所在目录 do (Dqml+'菜单1.mpr') &&打开菜单文件 do form (Dqml+'pass') &&打开效验口令字表单 read even on shutdown rele debug0 set sysmenu on set sysmenu to defa on error
三、pass.scx 表单。 功能:口令字效验、取出KLK中保存的硬盘卷标、判断当前硬盘卷标是否 合法、 取出KLK中的权限。 在表单及对象的方法或事件中,各自的代码是: 1.this.ini if type('debug0')='U' &&如果未通过Main.prg而调式,则: wait wind '请您从执行Main.PRG开始,进行调式......' this.release retu endi ******以下为解密klk.dat文件************************************** thisform.Vfpjmdbf1.pass_kl='12345678' &&设置加解密口令 thisform.Vfpjmdbf1.path_ml=dqml &&设定klk.dat文件所在目录 thisform.Vfpjmdbf1.jiEmi_file='klk.dat' &&存放密码的资料库文件名 thisform.Vfpjmdbf1.jiEmi &&解密klk.dat文件,并打开以'klk'为别名的工作区 thisform.Vfpjmdbf1.Visible=.f. &&隐藏 Vfpjmdbf1 Go top ******************以下为取磁盘卷标的WIN32API调用******************* Stor 0 to C_var,C_cd,C_qf C_disk='c:\' &&指定磁盘 DECLARE INTEGER GetVolumeInformation IN Win32API STRING @, STRING @,; INTEGER,; INTEGER @, INTEGER @, INTEGER @, STRING @, INTEGER xx=GetVolumeInformation(C_disk,"",20,@C_var,@C_cd,@C_qf,0,0) CLEAR DLLS * C_var=指定磁盘的卷标,是个十进制的数值。 if varjb=0 &&klk.varjb=0 表明是第一次运行本软件 repl varjb with C_var &&将磁盘卷标写入klk.varjb字段 thisform.Vfpjmdbf1.jiAmi_file='' thisform.Vfpjmdbf1.jiAmi &&先关闭,以保存修改 *要保存修改必须经Vfpjmdbf1.jiAmi来关闭库才行, thisform.Vfpjmdbf1.jiEmi_file='klk.dat' &&存放密码的资料库 thisform.Vfpjmdbf1.jiEmi &&再打开 else &&否则是已运行过本软件 if varjb<>C_var &&判断klk.varjb是否等于当前磁盘卷标(C_var) =Messagebox("对不起!您现在运行的软件未经过作者确认,不能运行... ",; 0+48+0,"警告") quit endi endi
2.this.unload if type('debug0')='U' do Case &&根据klk.qx字段决定菜单的屏蔽操作 case qx=1 set skip of bar 1 of 权限F .t. set skip of bar 2 of 权限F .t. case qx=2 set skip of bar 1 of 权限F .t. set skip of bar 2 of 权限F .t. set skip of bar 3 of 权限F .t. endc use &&关闭klk endi
3.thisform.text1.keypress if nKeyCode#13 retu endi loca for allt(this.value)==allt(Passkl) &&查找相符的口令字 if !foun() =Messagebox("对不起!您的口令有误,不能运行...... ",; 0+48+0,"警告") thisform.release quit &&退出系统,为了简单,口令效验我只设了一次。 endi thisform.release
四、查看和修改KLK的表单,这里就不具体写代码了。 五、菜单1.MPR 主菜单,这里就不具体写代码了。
实例中的权限密码是:0=全权 口令=aaaaaa 1=可修改自己的密码 口令=666666 2=不能作任何修改 口令=888888
需要以上程序源代码实例的,这里下载
从以上代码中可以看出,里面没有什么新的东西,所用的工具或资料,在我网上都 可找到,我只不过是把它们拼凑一下而已。您可把这个实例编译成EXE文件(VFP5.0的 朋友可能无法把共享版的Vfpjmdbf.vcx编进去),先在您的机器上运行一下,然后再 把它们直接拷贝到另外一台机器上一试,您看看还能运行否? 当然,别人只要用REFOX7.06把里面的Main.prg反编译出来,去掉: “ do form (Dqml+'pass')”这一句,还是可以非法拷贝的,那怎么办? 最好的办法是加密您的EXE文件,这样您的软件就比较保险了,最起码Refox等现成 的反编译工具是不可能反编译的。 在我网上有加密VFP&EXE的工具下载,您可下载一试。 需要说明的是:在我网上下载的vfpjmdbf.vcx和Vfp&Exe.exe都是共享版,功能和 使用次数都有一定的限制,如果您觉得还可以,请您花很少一点钱来注册这两个工具, 注册后,我将提供正式版和今后的免费升级。(最新Vfp&Exe.exe可以设置您自己的图表了)
如何把数字转换为汉字大写金额代码分析
-
[编程心得]又和您见面了,这次所写的是:怎样才能合理利 用 VFP本身所提供的命令和函数来组织代码、编制程序,以提高 运行效率。为了能说明问题,我以数字转换为大写为例,通过对 三组代码的对比来谈谈我个人对此问题的认识。 每种语言提供给我们的命令或函数,可以说最能体现这种语 言的本质,而每个程序员如何运用和组织这些命令或函数,则可 以直接反映这个程序员对这种语言的理解和掌握程度。现在虽然 更多的是强调如何学习和掌握面向对象的编程方法,以及如何灵 活运用这些对象中的事件和方法来组织代码,但我们切不可忽视 对这些最基本的语言命令或函数的学习、理解和灵活掌握。 下面我们以数字转换为大写为例来加以说明: 对于如何把数字转换为汉字大写金额的编程,我在网上看到 了许多种写法,代码最多的一种写法,其代码竟多达 100多行, 让人看了眼花缭乱,很难理解,而代码最少的却连10行都不到, 而其运行结果却是完全相同,可见理解和合理组织编程语言所提 供的命令和函数是何等的重要。 考虑到版面的原因,那近百行的代码我就不具体举例了,下 面的这些代码是我自行组织编写的,如有雷同,则纯属巧合: 代码一、 FUNCTION Rmbzh 1. PARA nDhsj 2. rmbxx=allt(str(nDhsj,12,2)) 3. lszs=allt(str(int(nDhsj))) 4. cd0=len(lszs) 5. dws0='元拾佰千万拾佰千亿' 6. sh0='壹贰叁肆伍陆柒捌玖零' 7. rmbdx='' 8. cd1=cd0 9. for I=1 to cd0 10. lspd=right(lszs,cd1) 11. if val(lspd)=0 12. rmbdx=rmbdx+iif(cd1>4,'万元','元') 13. exit 14. endi 15. ss=int(val(subs(lszs,I,1))) 16. if ss#0 17. rem0=SUBSTRC(sh0,ss,1)+SUBSTRC(dws0,cd1,1) 18. else 19. rem0=iif(I#cd0,'零','元') 20. endi 21. rmbdx=rmbdx+rem0 22. cd1=cd1-1 23. endf 24. do while atc('零零',rmbdx)>0 25. cc=10-atc('零零',rmbdx) 26. rmbdx=strtr(rmbdx,'零零',SUBSTRC(dws0,cc,1),1,1) 27. rmbdx=strtr(rmbdx,'零零','零',1,1) 28. rmbdx=strtr(rmbdx,'零零','',1,1) 29. endd 30. lsxs=allt(str(nDhsj,12,2)) 31. lsxs=right(lsxs,2) 32. if val(lsxs)#0 33. ss=int(val(subs(lsxs,1,1))) 34. rem0=SUBSTRC(sh0,ss,1)+'角' 35. rmbdx=rmbdx+rem0 36. ss=int(val(subs(lsxs,2,1))) 37. rem0=iif(ss=0,'整',SUBSTRC(sh0,ss,1)+'分') 38. rmbdx=rmbdx+rem0 39. else 40. rmbdx=rmbdx+'整' 41. endi 42. Retu rmbdx 这组代码是从纯数字的角度去考虑如何转换的,所以显得不 够简洁, 比如第3行和第31行,分别把整数部分和小数部分加以 分开,各自进行转换,就显的没有这个必要,但它也有可取之处, 比如: 1.充分利用了系统提供的函数,尤其是SUBSTRC()这个双字节 函数。 2.它运行的结果可以达到完全口语化的汉语金额,如: 12300.00元,其运行的结果是:壹万贰千叁佰元整,完全符合支 票类填写方式。但却不符合填充类方式。
代码二、 FUNCTION Rmbzh 1. PARA nDhsj, nDW &&nDW如果等于1,表示要金额单位 2. nDzs=strt(allt(str(nDhsj,15,2)),".","") &&把小数点去掉 3. hzdx="零壹贰叁肆伍陆柒捌玖" 4. cDW="分角元拾佰仟万拾佰仟亿拾佰仟" 5. rmbdx="" 6. nCd=len(nDzs) 7. for i=1 to len(nDzs) 8. NumS=substrc(hzdx,int(val(subs(nDzs,i,1))+1),1) 9. nDWs=iif(nDW=1,substrc(cDW,nCd,1),spac(2)) 10. rmbdx=rmbdx+NumS+nDwS 11. nCd=nCd-1 12. endfor 13. Retu rmbdx 这个代码就是在我网上提供下载的那个实例,可以看出它非常简洁, 编程线路清醒,第7行和第8行分别是数字转换和单位转换,不仅简单 明了,而且还可根据需要选择是否需要金额单位,但也有缺点,就是 不能象上例那样做到完全口语化,我之所以把它作为实例供下载,原 因就在于其清晰的思路和简洁的代码组织形式。 那么这组代码还可以“精简”(其实应该叫合并)吗?答案是: 当然可以。
代码三、 FUNCTION Rmbzh 1. PARA nDhsj, nDW &&nDW如果等于1,表示要金额单位 2. nDzs=strt(allt(str(nDhsj,15,2)),".","") 3. hzdx="零壹贰叁肆伍陆柒捌玖分角元拾佰仟万拾佰仟亿拾佰仟" 4. rmbdx="" 5. for i=len(nDzs) to 1 step -1 6. NumS=substrc(hzdx,2*val(subs(nDzs,len(nDzs)-i+1,1))+1,1) 7. nDws=iif(nDW=1,substrc(hzdx,i+10,1),space(2)) 8. rmbdx=rmbdx+NumS+nDwS 9. endfor 10. Retu rmbdx 可以看出这组代码又比上一组少了三行代码,而其最终运行的结果 是一样的,但它所带来的副作用是:代码不直观明了,不细细查看, 一时难以明白,尤其是第6行和第7行中substrc()中的参数需经过多 次运算方可得知,这对今后的维护带来了不便,我一般不采用这种写 法。如果硬是要再合并的话,那这组代码还可以继续合并,比如可以 把6-8行的代码合并为1行。
从上面的这几这几组代码我们不难看出,同一种运行目的,可以 有各种不同的代码组成和表现形式,也可以体现每个程序员各自不同 的编程风格,但不管如何,提高程序的运行效率是每 [1] [2] [3] 下一页 |