精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VFP>>〖界面设计〗>>VFP技术

主题:VFP技术
发信人: sunbing()
整理人: hunter__fox(2002-03-16 22:47:21), 站内信件
一、 前 言
---- 在 应 用 软 件 中, 数 据 库 管 理 软 件 是 应 用 的 最 广 泛 的 

软 件。 数 据 库 管 理 软 件 的 安 全 性、 保 密 性 是 开 发、 应 用 人

 员 较 为 关 心 的。 如 何 防 止 无 关 人 员 浏 览 数 据 库, 如 何 防

 止 数 据 库 被 非 法 修 改、 破 坏 ? 常 用 的 方 法 是 给 数 据 库、

 管 理 程 序 加 上 密 码。 那 么, 加 了 密 码 就 安 全 了 吗 ? 怎 样

 才 能 使 密 码 安 全 呢 ? 
二、 传 统 的 密 码 加 密 方 法
---- 从dBASE 到dBASEIII , 从 FOXBASE 到FOXBASE +, 从FOXPRO 到VISUAL

 FOXPRO, 常 用 加 密 码 的 方 法 给 程 序、 数 据 库 加 密。 常 见 的

 密 码 有 以 下 几 种: 固 定 密 码, 简 单 加 密 的 固 定 密 码, 加 

密 变 化 的 密 码, 具 体 分 析 如 下: 
---- 1、 固 定 密 码 

---- 固 定 密 码, 就 是 系 统 只 有 一 个 密 码, 而 且 是 固 定 的,

 不 可 变 的。 常 见 于 用Dbase、FOXBASE、FOXBASE +、FOXPRO2.X 开 发 

的 数 据 库 管 理 系 统。 常 用 如 下 语 句: 

I=1
DO WHILE .T.
PWD=SPACE(8)
SET CONS OFF
@12,35 SAY " 口 令!!!"
ACCEPT TO PWD
IF TRIM(PWD)< >"123456"
   IF I >=3
      @20,32 SAY "口令错误,您不能使用!"
      RETURN
   ENDIF
  @12,30 SAY "第" +STR(I,1)+"次口令错!"
  I =I +1
ELSE
  @20,28 SAY "欢迎使用本系统!"
   EXIT
ENDIF
ENDDO
---- 从 以 上 语 句 不 难 看 出, 其 核 心 是: 变 量PWD 与 输 入 值 的

 比 较。 密 码“1234” 是 程 序 设 计 时 设 定 的, 以 后 应 用 时 是 

无 法 修 改 的, 如 果 修 改, 就 要 改 变 源 程 序。 当 然, 也 可 以

 编 写 一 段 子 程 序 用 来 修 改 密 码, 修 改 前, 其 判 断 旧 密 码

 是 否 正 确, 也 用 IF TRIM(PWD)< >"123456" 语 句。 其 灵 活 性 很 差

, 在pctool 等 工 具 出 现 后, 保 密 性 就 显 得 差 了。 

---- 2、 简 单 加 密 的 固 定 密 码 

---- 简 单 加 密 的 固 定 密 码, 是 指 把 密 码 进 行 简 单 的 加 密,

 但 密 码 仍 然 是 固 定 的, 不 变 的。 简 单 加 密 一 般 有 两 种:“

 钥 匙 盘” 法 和“ 变 换 法”。“ 钥 匙 盘” 法, 就 是 把 密 码 存 放

 在 一 张 软 盘 上, 使 用 时, 把“ 钥 匙 盘” 插 入 计 算 机, 系 统

 程 序 读 取 软 盘 中 的 密 码。 或 把 密 码 和 操 作 员 姓 名 存 到 数

 据 库 中, 此 数 据 库 存 放 于 软 盘 内, 使 用 时 把“ 钥 匙 盘” 插

 入 计 算 机, 系 统 读 取 软 盘 中 的 密 码 和 操 作 员 姓 名, 下 面

 是 此 法 的 主 要 语 句: 

---- USE A:KLK && 到KLK 数 据 库 内 查 找 输 入 的 操 作 员 的 姓 名;

 

I=1
DO WHILE .T.
   STORE SAPCE(8) TO XM
   @ 10,26 SAY "请输入操作员姓名:"  GET XM
    READ
    LOCATE ALL FOR LTRIM(TRIM(XM))=LTRIM(TRIM(NAME))
    IF .NOT. EOF()
    EXIT    &&操作员姓名输入正确,向下执行;
    ENDIF
    IF I >=3 
 &&操作员姓名输入计数,输入次数超过3次,退出系统;(代码同前)
 …
    ENDIF
ENDDO
IF I< 5 &&姓名正确后,比较输入口令正确否;
MKL =SPACE(8)
I=1
DO WHILE I< 3
SET CONS OFF
@12,30 SAY " 口令! !"
ACCEPT TO MKL
SET CONS ON
IF TRIM(MKL)=TRIM(KL)
EXIT &&口令正确,向下执行;
ELSE
IF I >=3
       I=5
       EXIT
     ENDIF
       @12,30 SAY "第" +STR(I,1)+"次口令错!"
        I =I +1
   ENDIF
  ENDDO
ENDIF
IF I=5 
    @20,32 SAY "口令错误,您不能使用!"
ELSE
     @20,32 SAY "欢迎使用!"
ENDIF
RETURN
---- 这 种 加 密 方 法 保 密 性 要 好 一 些, 但 每 次 使 用 都 要 用“

 钥 匙 盘” 进 入 系 统, 很 繁 琐。 

---- 变 换 法, 就 是 通 过 对 密 码 的 运 算, 使 密 码 发 生 变 化 的

 方 法, 一 般 采 用 换 算 法, 常 用 的 加 密 语 句 如 下: 

---- PSD =CHR(65)+CHR(66)+CHR(67)+"9" 

---- 函 数CHR(), 是 用 来 换 算ASCII 码 的, 换 算 后 的PSD 是ABC9。 

用 这 种 简 单 的 换 算, 可 以 避 免 密 码 被 直 接 发 现, 如 果 和 

上 述 方 法 混 合 应 用, 保 密 性 就 加 强 了。 

---- 3、 简 单 加 密 变 化 的 密 码 

---- 以 上 密 码 都 是 固 定 的, 下 面 介 绍 一 种 经 简 单 加 密 变 

换 的 密 码。 这 是 利 用 时 间 函 数 来 加 密 的 算 法, 密 码 每 天 

都 不 同。 密 码 由 变 化 的 时 间 和 固 定 字 符 构 成。 其 核 心 语 

句 为: 

     kl=DATE() 

     PWD= SUBSTR(CDOW(kl),1,3)+"1234" 

 CDOW() 函 数, 输 入 年 月 日, 返 回 星 期 几( 字 符 型)。 操 作 者

 根 据 今 天 是 星 期 几, 将 星 期 的 前3 个 英 文 字 母 和 固 定 的“

1234” 输 入, 与 变 量PWD 比 较。 程 序 会 把 今 天 的 日 期 换 算 成

 星 期 数, 然 后 取 前3 位, 并 加 上“1234”, 合 成 今 天 的 密 码 

变 量PWD。 这 样 就 实 现 了 每 天 有 不 同 的 密 码。 保 密 性 加 强 

了。 

 以 上 几 种 加 密 方 法 都 是 传 统 的 简 单 的 加 密 方 法, 其 特 点

 是 简 单、 保 密 性 差, 密 码 单 一, 保 护 能 力 较 低, 主 要 用 于

Dbase、FOXBASE、FOXBASE +、FOXPRO2.x 中, 由 于 上 述 软 件 的 编 译 

不 是 真 正 的 编 译, 其 密 码 容 易 被 发 现。 

三、 一 种 新 型 密 码 加 密 方 法
 以 上 介 绍 的 是 几 种 固 定 的 密 码 加 密 方 法, 下 面 介 绍 一 下

 可 变 密 码。“ 可 变 密 码” 指 其 密 码 值 可 由 设 置 自 行 改 变,

 这 种 方 法 一 般 由 文 件 保 存 密 码, 且 密 码 经 过 加 密 运 算。

 密 码 的 加 密 算 运 算 方 法 很 多, 常 用 的 有: 转 换 法、 位 移 

法、 时 间 法、 随 机 法 等。 转 换 法, 就 是 把 输 入 的 密 码 经 过

 转 换 计 算, 转 换 成 保 存 密 码, 取 密 码 时, 再 经 过 逆 运 算,

 把 密 码 还 原。 
不 定 时 密 码 也 时 可 变 密 码 的 一 种, 是 指 密 码 的 出 现 是 以

 随 机 方 式 来 询 问 用 户。 如: 用 户 在 执 行 两 个 功 能 后 必 须

 输 入 密 码, 下 一 次 检 查 密 码 可 能 在 执 行 三 个 功 能 后 检 查

 密 码。 这 种 密 码 较 为 隐 蔽。 其 方 法 如 下: 首 先 声 明 一 个 

变 量, 用 来 计 数, 是1-5 的 随 机 数; 在 每 一 个 过 程、 函 数、 

或 命 令 执 行 前, 累 加 该 变 量 值; 当 该 变 量 值 等 于 其 随 机 

值 时, 调 用 密 码 查 询 程 序。 

下 面 具 体 介 绍 一 种 基 于VFP5.0 的 密 码 设 定 方 法。 其 特 点 是

: 具 有 使 用 登 记 功 能; 每 人 一 个 密 码, 并 可 随 时 更 换; 密

 码 经 加 密 运 算, 不 易 被 破 解。 

 基 本 思 路 如 下: 首 先 建 立 两 个 数 据 库(table), 一 个 用 来 存

 放 口 令 及 对 应 的 用 户( 称 为“ 口 令 库”), 另 一 个 存 放 用 户

 登 录 使 用 情 况( 称 为“ 登 录 库”)。 在 再 建 立 两 个 窗 口(form

), 一 个 用 来 检 查 口 令, 另 一 个 用 来 修 改 口 令。 接 下 来 定

 义 两 个 过 程(procedure), 一 个 用 来 给 口 令 加 密(“ 加 密 过 程

”), 另 一 个 用 给 口 令 解 密(“ 解 密 过 程”)。 这 个“ 加 密 过 

程”, 是 把 密 码 经 加 密 运 算 后 存 入 口 令 库, 而“ 解 密 过 程

” 实 际 上 是 把 输 入 的 密 码 经 加 密 运 算 后 与 口 令 库 内 的 密

 码 进 行 比 较, 并 不 是 解 密。 为 了 使 密 码 输 入 时 不 被 人 看

 见, 要 对 密 码 输 入 的 文 字 框 的 属 性 作 如 下 工 作: 进 入DAT

A 属 性 栏, 把InputMask 属 性 改 为:XXXXXX, 进 入LAYOUT 属 性 栏, 

把PassWordChar 的 属 性 改 为:“*”, 这 样, 输 入 的 密 码 就 不 会

 被 别 人 发 现。( 在FOXBASE FOXBASE +,FOXPRO2.X 中, 常 用 设 置 背

 景 颜 色 与 输 入 密 码 字 符 颜 色 相 同 的 办 法 来 防 止 别 人 看 

见。) 

“ 解 密 过 程” 代 码 如 下: 

parameter password
  pas=""
     n1=asc(substr(name,1,1))  
&&取姓名的第一个拼音字母,换算成ASCII码
     n2= asc(substr(name,2,1))  &&作为加密的键值
     n3= asc(substr(name,3,1))
     n=int((n1+n2+n3)/3)
     for i=1 to len(trim(password)) 
&&使用BITXOR()函数对密码进行解密
  tempchr=bitxor(asc(substr(password,i,1)),n)
   pas=pas+chr(tempchr)
      endfor
   locate for klk.user_id=name 
 &&与口令库内的与姓名相对应的口令进行比较
   if (klk.key< >pas) and (password< >"hg")
       result=.f.
   else
       result=.t.
   endif
   return result
BITXOR() 函 数 是vfp 特 有 的 函 数, 它 将 函 数 的 两 个 参 数 转 换

 成 二 进 制 数, 并 且 执 行“ 与” 操 作, 返 回 一 个 十 进 制 的 结

 果。 用 它 来 进 行 加 密 运 算, 保 密 性 强。 加 上 密 码 键 值n( 取

 姓 名 的 第 一 个 拼 音 字 母, 经 求 和, 再 取 平 均 值, 再 取 整 

运 算, 换 算 成ASCII 码), 得 到 每 人 一 个 的 密 码。 

该“ 过 程” 的 定 义 方 法 如 下: 在 定 义 检 查 密 码 的 窗 口(form

) 的 编 辑 状 态 下, 用 鼠 标 点 菜 单form, 选“new method”, 键 入“

 过 程” 名。 然 后 双 击 正 在 编 辑 的 窗 口(form), 然 后 进 入" 过 

程" 的 编 辑 状 态, 写 入 如 上 代 码。 加 密 过 程 是 解 密 过 程 的

 逆 运 算, 代 码 如 下: 

   parameter password
      pas=""
     for i=1 to len(trim(password))
   n1=asc(substr(name,1,1))
   n2= asc(substr(name,2,1))
   n3= asc(substr(name,3,1))
   n=int((n1+n2+n3)/3)
      tempchr=bitxor(asc(substr(password,i,1)),n)
pas=pas+chr(tempchr)
       endfor
       replace key with pas
检 查 密 码 的 思 路 是: 先 到 输 入 姓 名 的 文 字 框 内 取 姓 名, 

再 到 口 令 库 内 查 找 姓 名, 如 果 找 不 到 姓 名, 返 回 消 息 窗 

口“ 您 不 是 指 定 用 户, 请 与 系 统 管 理 员 联 系 !”, 系 统 退

 出; 如 果 找 到 了 用 户 姓 名, 则 继 续 进 行, 把 输 入 的 口 令 

和 姓 名 送 到 解 密“ 过 程” 中 进 行 运 算, 解 密“ 过 程” 将 其 

解 密, 并 与 口 令 库 内 的 数 据 进 行 比 较, 如 果 不 正 确, 开 始

 计 数, 要 求 重 新 输 入 密 码, 三 次 不 正 确, 退 出 系 统。 如 果

 正 确, 释 放 当 前 窗 口, 进 入 系 统。 

主 要 代 码 如 下: 

name=trim(ThisForm.Text1.value)
     if empty(name)
a=messagebox
("请输入用户名!",0+48,"信息窗口")
ThisForm.Text1.setfocus
        return
     endif 
     pass=trim(ThisForm.Text2.value)
     if empty(pass)
        a=messagebox
("请输入口令!",0+48,"信息窗口")
 ThisForm.Text2.setfocus
        return
     endif 
     use klk  
     locate for klk.user_id=name
     if found()=.f.
 =messagebox
("你不是指定用户,请与系统管理员联系!",64,"提示信息")
 thisform.release
     else
  ok =Thisform.decode(pass)
  if ok=.t.    
      ThisForm.Label3.caption="欢迎使用!"
       wait window ' 
欢迎使用!按任意键进入“系统维护模块。”' 
       release thisform
       do form wh_wh
   else
 if m=3  
    m=m+1
     ThisForm.Label3.caption="口令错,您无权使用"
     a=messagebox
("对不起,您无权使用!",0+48,"信息窗口")
      release thisform
  else
    a=messagebox
("口令错,请重新输入!",0+48,"信息窗口")
    ThisForm.Text2.value=""
    ThisForm.Text2.setfocus
    m=m+1
 endif      
     endif
endif
  
改 变 密 码 的 思 路 是: 首 先 读 取 用 户 姓 名, 如 果 是 新 用 户 

则 请 用 户 输 入 新 密 码, 并 记 录 下 获 得 新 密 码 的 时 间; 如 

果 是 老 用 户, 则 读 取 用 户 旧 密 码, 将 旧 密 码 进 行 解 密 运 

算 并 和 口 令 库 内 容 比 较, 如 果 正 确, 请 用 户 输 入 新 密 码,

 并 将 新 密 码 通 过 解 密 运 算 存 入 口 令 库, 并 记 录 修 改 时 间

。 

主 要 代 码 如 下: 

name=ThisForm.Text3.value
       oldpass=ThisForm.Text1.value
       newpass=ThisForm.Text2.value
       if isblank(newpass)
= messagebox("请重新输入新密码!",64,"信息提示")
     ThisForm.Text1.setfocus()
     return
        endif 
        success=thisform.decode(oldpass)
        if not success
  = messagebox
("旧密码不正确,重新输入密码!",64,"信息提示")
     ThisForm.Text1.setfocus()
     return
endif
locate for klk.user_id  =name    &&new user logo
if found()=.f.
    =messagebox("您是新用户!",64,"信息提示")
     append  blank  
    replace klk.user_id  with name,klk.logo_ddate with date()
    thisform.text3.setfocus
endif
thisform.Encode(newpass)
   = messagebox
("旧密码已经修改完成,下次请使用新密码!",64,"信息提示")
ThisForm.Command2.setfocus
return
注 意, 在 改 变 密 码 的 窗 口(form) 中, 要 定 义“ 加 密 过 程” 和

“ 解 密 过 程”, 方 法 如 上 所 述。 

以 上 是 一 个 加 密 算 法 的 主 要 思 路 和 关 键 代 码, 其 它 部 分

 读 者 可 自 行 设 计。 这 个 加 密 算 法 还 可 以 进 一 步 完 善。 如

 采 用 不 同 的 函 数 进 行 运 算, 加 入 日 期, 使 每 个 人 每 天 的

 密 码 都 不 一 样( 加 入 时 间 的 算 法 如 前 所 述, 利 用CDOW() 函 

数 作 为 键 值 的 一 部 分。)。 


---- 在 应 用 软 件 中, 数 据 库 管 理 软 件 是 应 用 的 最 广 泛 的 
软 件。 数 据 库 管 理 软 件 的 安 全 性、 保 密 性 是 开 发、 应 用 人
 员 较 为 关 心 的。 如 何 防 止 无 关 人 员 浏 览 数 据 库, 如 何 防
 止 数 据 库 被 非 法 修 改、 破 坏 ? 常 用 的 方 法 是 给 数 据 库、
 管 理 程 序 加 上 密 码。 那 么, 加 了 密 码 就 安 全 了 吗 ? 怎 样
 才 能 使 密 码 安 全 呢 ? 
二、 传 统 的 密 码 加 密 方 法
---- 从dBASE 到dBASEIII , 从 FOXBASE 到FOXBASE +, 从FOXPRO 到VISUAL
 FOXPRO, 常 用 加 密 码 的 方 法 给 程 序、 数 据 库 加 密。 常 见 的
 密 码 有 以 下 几 种: 固 定 密 码, 简 单 加 密 的 固 定 密 码, 加 
密 变 化 的 密 码, 具 体 分 析 如 下: 
---- 1、 固 定 密 码 

---- 固 定 密 码, 就 是 系 统 只 有 一 个 密 码, 而 且 是 固 定 的,
 不 可 变 的。 常 见 于 用Dbase、FOXBASE、FOXBASE +、FOXPRO2.X 开 发 
的 数 据 库 管 理 系 统。 常 用 如 下 语 句: 

I=1
DO WHILE .T.
PWD=SPACE(8)
SET CONS OFF
@12,35 SAY " 口 令!!!"
ACCEPT TO PWD
IF TRIM(PWD)< >"123456"
   IF I >=3
      @20,32 SAY "口令错误,您不能使用!"
      RETURN
   ENDIF
  @12,30 SAY "第" +STR(I,1)+"次口令错!"
  I =I +1
ELSE
  @20,28 SAY "欢迎使用本系统!"
   EXIT
ENDIF
ENDDO
---- 从 以 上 语 句 不 难 看 出, 其 核 心 是: 变 量PWD 与 输 入 值 的
 比 较。 密 码“1234” 是 程 序 设 计 时 设 定 的, 以 后 应 用 时 是 
无 法 修 改 的, 如 果 修 改, 就 要 改 变 源 程 序。 当 然, 也 可 以
 编 写 一 段 子 程 序 用 来 修 改 密 码, 修 改 前, 其 判 断 旧 密 码
 是 否 正 确, 也 用 IF TRIM(PWD)< >"123456" 语 句。 其 灵 活 性 很 差
, 在pctool 等 工 具 出 现 后, 保 密 性 就 显 得 差 了。 

---- 2、 简 单 加 密 的 固 定 密 码 

---- 简 单 加 密 的 固 定 密 码, 是 指 把 密 码 进 行 简 单 的 加 密,
 但 密 码 仍 然 是 固 定 的, 不 变 的。 简 单 加 密 一 般 有 两 种:“
 钥 匙 盘” 法 和“ 变 换 法”。“ 钥 匙 盘” 法, 就 是 把 密 码 存 放
 在 一 张 软 盘 上, 使 用 时, 把“ 钥 匙 盘” 插 入 计 算 机, 系 统
 程 序 读 取 软 盘 中 的 密 码。 或 把 密 码 和 操 作 员 姓 名 存 到 数
 据 库 中, 此 数 据 库 存 放 于 软 盘 内, 使 用 时 把“ 钥 匙 盘” 插
 入 计 算 机, 系 统 读 取 软 盘 中 的 密 码 和 操 作 员 姓 名, 下 面
 是 此 法 的 主 要 语 句: 

---- USE A:KLK && 到KLK 数 据 库 内 查 找 输 入 的 操 作 员 的 姓 名;
 

I=1
DO WHILE .T.
   STORE SAPCE(8) TO XM
   @ 10,26 SAY "请输入操作员姓名:"  GET XM
    READ
    LOCATE ALL FOR LTRIM(TRIM(XM))=LTRIM(TRIM(NAME))
    IF .NOT. EOF()
    EXIT    &&操作员姓名输入正确,向下执行;
    ENDIF
    IF I >=3 
 &&操作员姓名输入计数,输入次数超过3次,退出系统;(代码同前)
 …
    ENDIF
ENDDO
IF I< 5 &&姓名正确后,比较输入口令正确否;
MKL =SPACE(8)
I=1
DO WHILE I< 3
SET CONS OFF
@12,30 SAY " 口令! !"
ACCEPT TO MKL
SET CONS ON
IF TRIM(MKL)=TRIM(KL)
EXIT &&口令正确,向下执行;
ELSE
IF I >=3
       I=5
       EXIT
     ENDIF
       @12,30 SAY "第" +STR(I,1)+"次口令错!"
        I =I +1
   ENDIF
  ENDDO
ENDIF
IF I=5 
    @20,32 SAY "口令错误,您不能使用!"
ELSE
     @20,32 SAY "欢迎使用!"
ENDIF
RETURN
---- 这 种 加 密 方 法 保 密 性 要 好 一 些, 但 每 次 使 用 都 要 用“
 钥 匙 盘” 进 入 系 统, 很 繁 琐。 

---- 变 换 法, 就 是 通 过 对 密 码 的 运 算, 使 密 码 发 生 变 化 的
 方 法, 一 般 采 用 换 算 法, 常 用 的 加 密 语 句 如 下: 

---- PSD =CHR(65)+CHR(66)+CHR(67)+"9" 

---- 函 数CHR(), 是 用 来 换 算ASCII 码 的, 换 算 后 的PSD 是ABC9。 
用 这 种 简 单 的 换 算, 可 以 避 免 密 码 被 直 接 发 现, 如 果 和 
上 述 方 法 混 合 应 用, 保 密 性 就 加 强 了。 

---- 3、 简 单 加 密 变 化 的 密 码 

---- 以 上 密 码 都 是 固 定 的, 下 面 介 绍 一 种 经 简 单 加 密 变 
换 的 密 码。 这 是 利 用 时 间 函 数 来 加 密 的 算 法, 密 码 每 天 
都 不 同。 密 码 由 变 化 的 时 间 和 固 定 字 符 构 成。 其 核 心 语 
句 为: 

     kl=DATE() 

     PWD= SUBSTR(CDOW(kl),1,3)+"1234" 

 CDOW() 函 数, 输 入 年 月 日, 返 回 星 期 几( 字 符 型)。 操 作 者
 根 据 今 天 是 星 期 几, 将 星 期 的 前3 个 英 文 字 母 和 固 定 的“
1234” 输 入, 与 变 量PWD 比 较。 程 序 会 把 今 天 的 日 期 换 算 成
 星 期 数, 然 后 取 前3 位, 并 加 上“1234”, 合 成 今 天 的 密 码 
变 量PWD。 这 样 就 实 现 了 每 天 有 不 同 的 密 码。 保 密 性 加 强 
了。 

 以 上 几 种 加 密 方 法 都 是 传 统 的 简 单 的 加 密 方 法, 其 特 点
 是 简 单、 保 密 性 差, 密 码 单 一, 保 护 能 力 较 低, 主 要 用 于
Dbase、FOXBASE、FOXBASE +、FOXPRO2.x 中, 由 于 上 述 软 件 的 编 译 
不 是 真 正 的 编 译, 其 密 码 容 易 被 发 现。 

三、 一 种 新 型 密 码 加 密 方 法
 以 上 介 绍 的 是 几 种 固 定 的 密 码 加 密 方 法, 下 面 介 绍 一 下
 可 变 密 码。“ 可 变 密 码” 指 其 密 码 值 可 由 设 置 自 行 改 变,
 这 种 方 法 一 般 由 文 件 保 存 密 码, 且 密 码 经 过 加 密 运 算。
 密 码 的 加 密 算 运 算 方 法 很 多, 常 用 的 有: 转 换 法、 位 移 
法、 时 间 法、 随 机 法 等。 转 换 法, 就 是 把 输 入 的 密 码 经 过
 转 换 计 算, 转 换 成 保 存 密 码, 取 密 码 时, 再 经 过 逆 运 算,
 把 密 码 还 原。 
不 定 时 密 码 也 时 可 变 密 码 的 一 种, 是 指 密 码 的 出 现 是 以
 随 机 方 式 来 询 问 用 户。 如: 用 户 在 执 行 两 个 功 能 后 必 须
 输 入 密 码, 下 一 次 检 查 密 码 可 能 在 执 行 三 个 功 能 后 检 查
 密 码。 这 种 密 码 较 为 隐 蔽。 其 方 法 如 下: 首 先 声 明 一 个 
变 量, 用 来 计 数, 是1-5 的 随 机 数; 在 每 一 个 过 程、 函 数、 
或 命 令 执 行 前, 累 加 该 变 量 值; 当 该 变 量 值 等 于 其 随 机 
值 时, 调 用 密 码 查 询 程 序。 

下 面 具 体 介 绍 一 种 基 于VFP5.0 的 密 码 设 定 方 法。 其 特 点 是
: 具 有 使 用 登 记 功 能; 每 人 一 个 密 码, 并 可 随 时 更 换; 密
 码 经 加 密 运 算, 不 易 被 破 解。 

 基 本 思 路 如 下: 首 先 建 立 两 个 数 据 库(table), 一 个 用 来 存
 放 口 令 及 对 应 的 用 户( 称 为“ 口 令 库”), 另 一 个 存 放 用 户
 登 录 使 用 情 况( 称 为“ 登 录 库”)。 在 再 建 立 两 个 窗 口(form
), 一 个 用 来 检 查 口 令, 另 一 个 用 来 修 改 口 令。 接 下 来 定
 义 两 个 过 程(procedure), 一 个 用 来 给 口 令 加 密(“ 加 密 过 程
”), 另 一 个 用 给 口 令 解 密(“ 解 密 过 程”)。 这 个“ 加 密 过 
程”, 是 把 密 码 经 加 密 运 算 后 存 入 口 令 库, 而“ 解 密 过 程
” 实 际 上 是 把 输 入 的 密 码 经 加 密 运 算 后 与 口 令 库 内 的 密
 码 进 行 比 较, 并 不 是 解 密。 为 了 使 密 码 输 入 时 不 被 人 看
 见, 要 对 密 码 输 入 的 文 字 框 的 属 性 作 如 下 工 作: 进 入DAT
A 属 性 栏, 把InputMask 属 性 改 为:XXXXXX, 进 入LAYOUT 属 性 栏, 
把PassWordChar 的 属 性 改 为:“*”, 这 样, 输 入 的 密 码 就 不 会
 被 别 人 发 现。( 在FOXBASE FOXBASE +,FOXPRO2.X 中, 常 用 设 置 背
 景 颜 色 与 输 入 密 码 字 符 颜 色 相 同 的 办 法 来 防 止 别 人 看 
见。) 

“ 解 密 过 程” 代 码 如 下: 

parameter password
  pas=""
     n1=asc(substr(name,1,1))  
&&取姓名的第一个拼音字母,换算成ASCII码
     n2= asc(substr(name,2,1))  &&作为加密的键值
     n3= asc(substr(name,3,1))
     n=int((n1+n2+n3)/3)
     for i=1 to len(trim(password)) 
&&使用BITXOR()函数对密码进行解密
  tempchr=bitxor(asc(substr(password,i,1)),n)
   pas=pas+chr(tempchr)
      endfor
   locate for klk.user_id=name 
 &&与口令库内的与姓名相对应的口令进行比较
   if (klk.key< >pas) and (password< >"hg")
       result=.f.
   else
       result=.t.
   endif
   return result
BITXOR() 函 数 是vfp 特 有 的 函 数, 它 将 函 数 的 两 个 参 数 转 换
 成 二 进 制 数, 并 且 执 行“ 与” 操 作, 返 回 一 个 十 进 制 的 结
 果。 用 它 来 进 行 加 密 运 算, 保 密 性 强。 加 上 密 码 键 值n( 取
 姓 名 的 第 一 个 拼 音 字 母, 经 求 和, 再 取 平 均 值, 再 取 整 
运 算, 换 算 成ASCII 码), 得 到 每 人 一 个 的 密 码。 

该“ 过 程” 的 定 义 方 法 如 下: 在 定 义 检 查 密 码 的 窗 口(form
) 的 编 辑 状 态 下, 用 鼠 标 点 菜 单form, 选“new method”, 键 入“
 过 程” 名。 然 后 双 击 正 在 编 辑 的 窗 口(form), 然 后 进 入" 过 
程" 的 编 辑 状 态, 写 入 如 上 代 码。 加 密 过 程 是 解 密 过 程 的
 逆 运 算, 代 码 如 下: 

   parameter password
      pas=""
     for i=1 to len(trim(password))
   n1=asc(substr(name,1,1))
   n2= asc(substr(name,2,1))
   n3= asc(substr(name,3,1))
   n=int((n1+n2+n3)/3)
      tempchr=bitxor(asc(substr(password,i,1)),n)
pas=pas+chr(tempchr)
       endfor
       replace key with pas
检 查 密 码 的 思 路 是: 先 到 输 入 姓 名 的 文 字 框 内 取 姓 名, 
再 到 口 令 库 内 查 找 姓 名, 如 果 找 不 到 姓 名, 返 回 消 息 窗 
口“ 您 不 是 指 定 用 户, 请 与 系 统 管 理 员 联 系 !”, 系 统 退
 出; 如 果 找 到 了 用 户 姓 名, 则 继 续 进 行, 把 输 入 的 口 令 
和 姓 名 送 到 解 密“ 过 程” 中 进 行 运 算, 解 密“ 过 程” 将 其 
解 密, 并 与 口 令 库 内 的 数 据 进 行 比 较, 如 果 不 正 确, 开 始
 计 数, 要 求 重 新 输 入 密 码, 三 次 不 正 确, 退 出 系 统。 如 果
 正 确, 释 放 当 前 窗 口, 进 入 系 统。 

主 要 代 码 如 下: 

name=trim(ThisForm.Text1.value)
     if empty(name)
a=messagebox
("请输入用户名!",0+48,"信息窗口")
ThisForm.Text1.setfocus
        return
     endif 
     pass=trim(ThisForm.Text2.value)
     if empty(pass)
        a=messagebox
("请输入口令!",0+48,"信息窗口")
 ThisForm.Text2.setfocus
        return
     endif 
     use klk  
     locate for klk.user_id=name
     if found()=.f.
 =messagebox
("你不是指定用户,请与系统管理员联系!",64,"提示信息")
 thisform.release
     else
  ok =Thisform.decode(pass)
  if ok=.t.    
      ThisForm.Label3.caption="欢迎使用!"
       wait window ' 
欢迎使用!按任意键进入“系统维护模块。”' 
       release thisform
       do form wh_wh
   else
 if m=3  
    m=m+1
     ThisForm.Label3.caption="口令错,您无权使用"
     a=messagebox
("对不起,您无权使用!",0+48,"信息窗口")
      release thisform
  else
    a=messagebox
("口令错,请重新输入!",0+48,"信息窗口")
    ThisForm.Text2.value=""
    ThisForm.Text2.setfocus
    m=m+1
 endif      
     endif
endif
  
改 变 密 码 的 思 路 是: 首 先 读 取 用 户 姓 名, 如 果 是 新 用 户 
则 请 用 户 输 入 新 密 码, 并 记 录 下 获 得 新 密 码 的 时 间; 如 
果 是 老 用 户, 则 读 取 用 户 旧 密 码, 将 旧 密 码 进 行 解 密 运 
算 并 和 口 令 库 内 容 比 较, 如 果 正 确, 请 用 户 输 入 新 密 码,
 并 将 新 密 码 通 过 解 密 运 算 存 入 口 令 库, 并 记 录 修 改 时 间
。 

主 要 代 码 如 下: 

name=ThisForm.Text3.value
       oldpass=ThisForm.Text1.value
       newpass=ThisForm.Text2.value
       if isblank(newpass)
= messagebox("请重新输入新密码!",64,"信息提示")
     ThisForm.Text1.setfocus()
     return
        endif 
        success=thisform.decode(oldpass)
        if not success
  = messagebox
("旧密码不正确,重新输入密码!",64,"信息提示")
     ThisForm.Text1.setfocus()
     return
endif
locate for klk.user_id  =name    &&new user logo
if found()=.f.
    =messagebox("您是新用户!",64,"信息提示")
     append  blank  
    replace klk.user_id  with name,klk.logo_ddate with date()
    thisform.text3.setfocus
endif
thisform.Encode(newpass)
   = messagebox
("旧密码已经修改完成,下次请使用新密码!",64,"信息提示")
ThisForm.Command2.setfocus
return
注 意, 在 改 变 密 码 的 窗 口(form) 中, 要 定 义“ 加 密 过 程” 和
“ 解 密 过 程”, 方 法 如 上 所 述。 

以 上 是 一 个 加 密 算 法 的 主 要 思 路 和 关 键 代 码, 其 它 部 分
 读 者 可 自 行 设 计。 这 个 加 密 算 法 还 可 以 进 一 步 完 善。 如
 采 用 不 同 的 函 数 进 行 运 算, 加 入 日 期, 使 每 个 人 每 天 的
 密 码 都 不 一 样( 加 入 时 间 的 算 法 如 前 所 述, 利 用CDOW() 函 
数 作 为 键 值 的 一 部 分。)。 

--
太阳冰,真诚面对一切!

※ 修改:.sunbing 于 Feb  2 20:46:49 修改本文.[FROM: 202.102.146.70]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.146.70]
发信人: sunbing (太阳冰), 信区: VFP
标  题: VISUAL FOXPRO 5.0动画设计 (转贴)
发信站: 网易虚拟社区 (Tue Feb  2 20:29:47 1999), 转信

- VISUAL FOXPRO 是 目 前 国 内 非 常 流 行 的 可 视 化 数 据 库 开 发 
工 具, 它 以 强 大 的 功 能, 便 捷 的 开 发 方 法 深 受 广 大 用 户 
的 喜 爱。 而 动 画 功 能 一 直 是3DSTUDIO、PHOTOSHOP、VISUAL BASIC 等
 软 件 制 作 工 具 的 开 发 专 利, 是 否 数 据 库 软 件 中 就 真 的 不
 能 实 现 动 画 功 能 呢 ? 

---- 回 答 是 否 定 的。 下 面 我 就 详 细 告 诉 你 如 何 在VISAUL FOX
PRO 5.0 中 进 行 实 现 动 画 设 计。 

---- 为 了 使 动 画 效 果 更 加 逼 真, 通 常 采 用 电 视 动 画 片 的 
制 作 方 法, 即 将 一 个 连 续 的 动 作 分 解 为 若 干 个 非 连 续 的
 子 动 作, 通 过 定 时 器 定 时 调 用 各 个 子 动 作, 依 靠 人 的 视
 觉 暂 留 使 动 作 看 起 来 就 好 象 是 一 组 连 续 的 动 作。 在VFP 中
 可 将 分 解 的 动 作 存 于 图 像 框 内, 结 合MOVE 方 法 和 计 时 器 
产 生 动 画 效 果。 

---- ★ 实 现 目 的: 让 蝴 蝶 展 开 翅 膀 飞 起 来。 

---- ★ 实 现 原 理: 设 定 三 个 蝴 蝶 图 标, 其 中 二 个 张 开 翅 膀
( 或 合 上 翅 膀)、 一 个 合 上 翅 膀( 或 张 开 翅 膀)。 将 一 个 
图 标 作 为 移 动 的 蝴 蝶( 设 置 为 可 见), 其 它 两 个 图 标 设 置 
为 不 可 见。 利 用timer 控 件 的Interval 属 性 设 置 的 时 间 间 隔 来
 交 替 切 换 张 开 翅 膀 和 合 上 翅 膀 两 个 图 标, 达 到 蝴 蝶 拍 动
 翅 膀,“ 动 起 来” 的 效 果。 再 利 用 控 件 的MOVE 方 法 达 到 蝴 
蝶“ 飞 起 来” 的 效 果。 图 标 如 下: 

---- 文 件 名: BFLY1.BMP BFLY2.BMP 

---- ★ 应 用 实 例: 在VFP 5.0 中 实 现 动 画 功 能。 

---- 实 例 一: 实 现" 让 蝴 蝶 动 起 来" 的 动 画 效 果。 用 于 应 用 
系 统 的 帮 助 说 明。 

---- ① 建 立 含 有 如 下 控 件 的 窗 体FORM: 

控件   CAPTION   NAME  FORECOLOR FONTSIZE PICTURE  
窗体实现"让蝴蝶动起来"的动画效果。  FORM1
标签实例一:实现"让蝴蝶动起来"的动画效果。
LABEL1 0,0,255   12
标签编制者:蔡可训 1998年7月16日 
       LABEL2 255,0,0   12
图像框   BTRFLY      BFLY2.BMP
图像框   BTRFLY1     BFLY1.BMP
图像框   BTRFLY2     BFLY2.BMP
命令按钮 退 出      COMMAND1
---- ② 程 序 清 单: 

在FORM1_ACTIVATE事件中,输入下列语句:
public flap
flap=0   
&&定义控制是张开翅膀还是合上翅膀位图的切换变量
thisform.btrfly.visible=.t.
thisform.btrfly1.visible=.f.
thisform.btrfly2.visible=.f.
thisform.timer1.interval=200    
在TIMER1_TIMER事件中,输入下列语句:
if flap=0   &&交替切换两幅位图
   thisform.btrfly.Picture=thisform.btrfly1.Picture &&
换上张开翅膀位图
   flap=1
else
 thisform.btrfly.Picture=thisform.btrfly2.Picture && 
否则为合上翅膀位图
 flap=0
endi
在COMMAND1_CLICK事件中,输入下列语句:
release thisform
---- 实 例 二: 实 现" 让 蝴 蝶 飞 起 来" 的 动 画 效 果。 

---- ① 建 立 含 有 如 下 控 件 的 窗 体FORM: 

控件   CAPTION NAME  FORECOLOR FONTSIZE PICTURE 
窗体实现"让蝴蝶飞起来"的动画效果。 FORM1 
图像框 MAIN BFLY1.BMP
图像框 CLOSEWINGS    BFLY2.BMP
图像框 OPENWINGS     BFLY1.BMP
命令按钮退 出  COMMAND1

      ②程序清单:
在FORM1_ACTIVATE事件中,输入下列语句:
public pickbmp
pickbmp=.t.
thisform.main.visible=.t.
thisform.openwings.visible=.f.
thisform.closewings.visible=.f.
thisform.timer1.interval=200    
在TIMER1_TIMER事件中,输入下列语句:
thisform.main.move (thisform.main.left+20,thisform.main.top-5)
if thisform.main.left >thisform.width &&判别是否飞出窗体
      thisform.main.move (20,thisform.height-20)
 &&将位图移到左下角准备向右飞
endi 
if pickbmp 
&&交替切换两幅位图,同时将位图沿着一定轨迹移动。
 thisform.main.picture=thisform.openwings.picture && 
换上张开翅膀的位图
else
thisform.main.picture=thisform.closewings.picture &&
换上合上翅膀的位图
endi
pickbmp=.not.pickbmp
在COMMAND1_CLICK退出事件中,输入下列语句:
release thisform
以上程序在同创P/200,WINDOWS 95,
Visual Foxpro 5.0中文版软硬件环境下运
行通过。

--
太阳冰,真诚面对一切!

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.146.70]
发信人: sunbing (太阳冰), 信区: VFP
标  题: VFP通用组合框的实现 (转贴)
发信站: 网易虚拟社区 (Tue Feb  2 20:36:34 1999), 转信

   确 保 数 据 库 数 据 准 确 性 的 最 直 接 方 法 之 一 就 是 为 用 户
 提 供 一 组 预 先 设 定 的 选 项。 这 样 既 可 保 证 在 数 据 库 中 不
 存 储 无 效 数 据, 又 可 提 高 用 户 数 据 输 入 效 率。 在 运 用Vis
ual FoxPro 进 行 项 目 开 发 时, 可 以 通 过 选 项 按 钮 组、 复 选 框
、 列 表 框 或 下 拉 组 合 框 等 控 制 实 现 此 种 功 能。 而 对 于 数
 据 输 入 来 说, 下 拉 组 合 框 是 必 不 可 少 的。 它 即 为 用 户 提
 供 了 包 含 一 些 选 项 和 信 息 的 可 滚 动 列 表, 又 可 允 许 用 户
 输 入 一 个 值。 其 方 便 的 操 作 被 用 户 所 青 睐, 因 此 常 被 程
 序 员 采 用。 

---- 下 拉 组 合 框 看 上 去 象 一 个 文 本 框, 只 是 右 边 有 个 下 
拉 按 钮, 单 击 这 个 按 钮, 可 以 翻 滚 组 合 框, 从 而 选 择 输 入
 其 中 的 选 项。 一 般 的 程 序 员 常 按 下 面 步 骤 在 表 单 中 建 立
 组 合 框: 

---- 1) 在 表 单 设 计 器 中, 单 击 选 定" 表 单 控 件" 工 具 栏 中 的
 控 件 按 钮。 

---- 2) 在 表 单 上 组 合 框 要 出 现 的 位 置 画 一 个 方 框。 

---- 3) 打 开 组 合 框 构 建 器(Builder), 并 选 择 设 定 其 各 项 属 
性。 

---- 4) 单 击OK 按 钮 返 回 表 单 设 计 器。 

---- 组 合 框 成 功 应 用 的 重 要 基 础 是 正 确 设 置 其 各 项 属 性
, 包 括 数 据、 方 法 程 序 及 布 局 等 多 种 类 型。 在 设 计 时 经 
常 设 置 的 组 合 框 属 性 有: 

---- ColumnCount : 组 合 框 的 列 数。 

---- ControlSource : 设 置 用 户 从 组 合 框 中 选 择 值 的 保 存 位 
置。 

---- Multiselect: 决 定 用 户 能 否 从 组 合 框 中 一 次 选 择 一 个 
以 上 的 项。 

---- RowSource: 列 表 中 显 示 值 的 来 源。 

---- RowSourceType: 列 表 中 数 据 源 的 类 型, 有 以 下 几 种:0 - 
无, 由 程 序 添 加; 

---- 1 - 值;2 - 别 名;3 - SQL 语 句;4 - 查 询;5 - 数 组;6 - 字 段
;7 - 文 件;8 - 结 构;9 - 弹 出 式 菜 单。 

---- 在 项 目 开 发 时, 程 序 员 常 把 组 合 框 选 项 数 据 源 保 存 
于 特 定 表 中, 由 该 选 项 表 来 提 供 对 特 定 字 段 的 输 入 控 制
。 由 于 组 合 框 选 项 来 源 由RowSource 和 RowSourceType 两 个 属 性
 设 定, 如 果 从 特 定 表 中 选 择 组 合 框 的 数 据 源, 通 常 通 过
 将RowSourceType 属 性 设 置 为3-SQL 语 句, 而 在RowSource 属 性 中 设
 置 一 个SELECT-SQL 语 句 来 实 现。 如: 

      SELECT 课 程 名 称 FROM 课 程 ;
            INTO CURSOR kclist
---- 该 语 句 可 选 择< 课 程 > 表 中 的< 课 程 名 称 > 字 段 建 立 临
 时 表kclist 来 提 供 组 合 框 的 选 项。 

---- 组 合 框 的 运 用 为 数 据 输 入 提 供 了 准 确 与 方 便。 但 运 
用 上 述 方 法 建 立 组 合 框 却 非 常 麻 烦-- 每 个 表 单 中 建 立 的
 所 有 组 合 框, 都 要 运 用 构 建 器 一 一 设 置 其 各 项 属 性。 不
 但 效 率 低, 而 且 容 易 发 生 遗 漏 与 错 误。 另 一 方 面, 还 需 
为 对 应 不 同 存 储 字 段 的 组 合 框 建 立 各 自 的 数 据 源 表, 从
 而 引 起 表 文 件 数 量 不 断 增 加。 对 上 述 问 题, 作 者 发 现 可
 通 过 创 建 下 述 的 通 用 组 合 框 类 来 解 决。 

---- 创 建 通 用 组 合 框 

---- 1. 创 建 通 用 组 合 框 类 

---- 运 用Visual FoxPro 创 建 一 个 新 类 的 方 式 有 以 下 三 种: 

在 项 目 管 理 器 中, 选 择" 类" 选 项 卡 并 选 择" 新 建" 按 钮。 

从" 文 件" 菜 单 中 选 择" 新 建" 命 令, 再 选 择" 类", 再 选 择" 新
 文 件" 按 钮。 

使 用 CREATE CLASS 命 令。
---- 使 用 上 述 三 种 方 法 中 的 任 一 种 方 式, 均 可 打 开" 新 类
" 对 话 框。 在 该 对 话 框 的< 类 名 > 栏 中 指 定 新 类 的 名 称ty_C
omboBox,< 派 生 于 > 栏 中 指 定 新 类 基 于 的 类( 父 类)ComboBox, 
在< 存 储 于 > 栏 中 指 定 保 存 新 类 的 类 库 名 main.vcx( 如 果 设
 置 的 类 库 名 不 存 在,Visual FoxPro 会 自 动 在 相 应 的 路 径 中 
创 建 相 应 的 类 库 文 件)。 设 置 好 后 选 择" 确 定" 按 钮, 即 可
 进 入 类 设 计 器 中 对 该 新 类ty_ComboBox 进 行 属 性 设 置 与 修 改
。 

---- 为 了 使 类ty_ComboBox 具 有 通 用 性, 需 要 使 其RowSource 和 R
owSourceType 两 个 属 性 能 够 自 动 设 置。 为 此 可 在 其Init 事 件 
中 加 入 如 下 代 码: 

*****************************************
*通用组合框ty_ComboBox类Init事件代码,
*可根据其ControlSource属性及数据源表
*自动设置其RowSource属性
*****************************************
FOR nTEMP = 1 TO 50
  cZXTEMP='ZXTEMP'+LTRIM(STR(nTEMP,2))
  IF NOT USED(cZXTEMP)
     EXIT
  ENDIF
ENDFOR    
cFieldName=TRIM(SUBS(This.ControlSource,;
   AT('.',This.ControlSource)+1))
cRowSource = 'SELECT name , field_name ;
  FROM zxdict WHERE zxdc="'  + ;
  cFieldName +'"TO CURSOR '+ cZXTEMP
WITH THIS
   .ColumnCount = 2
   .ColumnWidths = '120, 80'
   .RowSourceType = 3
   .RowSource = cRowSource
   .BoundColumn = 1
ENDWITH
*****代码结尾 *****
---- 上 述Init 事 件 代 码 可 在 组 合 框 初 始 化 时, 把 其RowSource
Type 属 性 设 置 为3-SQL 语 句, 而 在RowSource 属 性 中 则 设 置 相 应
 的SELECT-SQL 语 句。 该 语 句 以 组 合 框 ControlSource 属 性 对 应 存
 储 位 置 的 字 段 名 为 筛 选 条 件, 从 数 据 源 表ZXDICT 中 选 择na
me 和 field_name 两 个 字 段 建 立 具 有 两 列 选 项 的 新 临 时 表。 
该 临 时 表 名 以ZXTEMP 开 头, 其 中 的 记 录 即 为 组 合 框 中 显 示
 的 选 项。 

---- 此 通 用 组 合 框 类 需 要 有 具 有 如 下 字 段 的 数 据 源 表ZXD
ICT.DBF 配 合 使 用: 

      字 段 名      类 型    宽 度
      zxdc        字 符 型   10
      name        字 符 型   30
      field_name  字 符 型   10
---- 其 中 的zxdc 字 段 存 放 组 合 框ControlSource 属 性 设 置 的 保 
存 位 置 的 数 据 库 表 字 段 名 称, 它 决 定 了SELECT-SQL 语 句 中 的
 筛 选 条 件。 而name 和field_name 两 个 字 段 则 分 别 存 储 符 合 筛
 选 条 件 的 数 据 源 实 际 值 与 代 码 值。 组 合 框BoundColumn 属 性
 值 为1 表 示ControlSource 对 应 字 段 中 存 储 实 际 值; 如 果 想 在
 该 字 段 中 存 储 代 码 值, 把 上 述Init 事 件 代 码 中 的 BoundColu
mn 属 性 值 由1 改 为2 即 可。 

---- 2. 设 置 临 时 表 释 放 事 件 

---- ty_ComboBox 类 每 次 在 表 单 中 建 立 一 个 实 例, 其SELECT-SQL
 语 句 即 产 生 一 个 以ZXTEMP 开 头 的 临 时 表 文 件。 若 通 用 组 合
 框 执 行 多 次, 也 就 建 立 相 应 数 量 的 临 时 表 文 件。 该 临 时
 表 文 件 不 会 自 动 释 放, 不 断 累 计 结 果 将 消 耗 大 量 内 存 资
 源。 因 此, 需 在 表 单 关 闭 同 时 关 闭 所 建 临 时 表 文 件。 这 
可 通 过 在 选 用 的 表 单 类 的Destroy 事 件 中 加 入 如 下 代 码 来 
实 现: 

***************************************
* 表 单 的 Destroy 事 件 代 码,
* 自 动 释 放 组 合 框 建 立 的 临 时 库 ZXTEMP*
***************************************
nOldArea=SELE()
FOR nTEMP = 1 TO 50
  cZXTEMP='ZXTEMP'+LTRIM(STR(nTEMP,2))
  IF USED(cZXTEMP)
    SELECT &cZXTEMP
    USE
   ELSE
     EXIT
  ENDIF
ENDFOR    
RELEASE ALL LIKE ZXTEMP*
SELECT (nOldArea)
***** 代 码 结 尾 *****
---- 该 段 代 码 在 关 闭 表 单 时, 按 顺 序 检 查 内 存 中 以ZXTEMP 
开 头 的 所 有 临 时 表: 如 果 存 在 即 使 用USE 命 令 关 闭。 临 时 
表 文 件 关 闭 后 会 立 即 从 存 储 器 中 移 出, 释 放 出 内 存 资 源
。 

---- 通 用 组 合 框 的 应 用 

---- 在Visual FoxPro 中 有 几 种 方 法 可 激 活 使 用 用 户 自 己 的 类
 库。 一 种 方 法 是 把 其 指 定 为 缺 省 类 库: 执 行" 工 具" 菜 单 
的< 选 项 > 操 作 后 选 择 其 中 的< 控 件 > 页, 把 创 建 的 类 库MAI
N.VCX 加 到 对 话 框 中 指 定 其 为 要 加 载 的 库, 进 而 单 击 屏 幕
 底 部 的< 保 存 为 缺 省 值 > 按 钮 即 可 永 久 保 存 该 项 设 置。 另
 外 可 在" 表 单 控 件" 工 具 栏 中, 右 击< 查 看 类 > 控 件, 从 弹 
出 式 菜 单 中 选 定< 添 加 > 选 项, 进 而 在" 打 开 文 件" 对 话 框 
中 指 定 想 要 打 开 的 类 库。 通 过 上 述 两 种 方 法 激 活 用 户 自
 己 的 类 库 后," 表 单 控 件" 工 具 栏 的 条 目 将 由 该 库 中 的 部
 件 所 代 替, 进 而 可 在 设 计 表 单 时 使 用。 

---- 而 在Visual FoxPro 5.0 版 本 中, 可 通 过" 拖 曳" 功 能 使 用 用
 户 自 己 的 类 库。 首 先 在 " 表 设 计 器" 中, 把 需 建 立 通 用 组
 合 框 的 数 据 库 表 字 段 的< 显 示 库 > 栏 设 置 为MAIN.VCX ,< 显
示 类 > 栏 相 应 设 为ty_ComboBox。 保 存 数 据 库 表 结 构 设 置 后,
 在 表 单 设 计 时, 把 此 类 字 段 由" 数 据 环 境" 中 拖 曳 至 表 单
 上 后, 将 直 接 在 表 单 上 建 立 该 通 用 组 合 框。 另 外 也 可 由
" 项 目 管 理 器" 的< 数 据 > 页 中 直 接 拖 曳 此 类 字 段 至 表 单 上
, 也 将 在 表 上 相 应 建 立 该 通 用 组 合 框。 通 过" 拖 曳" 功 能 
使 用 用 户 类 库 的 方 法 更 加 方 便 快 捷, 但 只 能 用 于Visual Fo
xPro 5.0 以 上 版 本 中。 

--
太阳冰,真诚面对一切!

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.146.70]

[关闭][返回]