发信人: 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]
  | 
 
 
 |