来自Craig Boyd很棒的工具

发布日期: FoxTalk 2.0 四月
 
来自 Craig Boyd 很棒的工具
作者: Doug Hennig 翻译: Sunny
Craig Boyd (克雷格 . 博伊德)为 VFP 开发人员创作一些很棒的工具。这个月, Doug Hennig 分析 Craig 加密函数库及分割条和进度条控件。
Craig Boyd VFP 组别中最突出的一位新的微软最有价值专家。他有一个非常有趣的博客 (www.sweetpotatosoftware.com/SPSBlog), ,是 SednaX 的发起人和其中一位管理人员, SednaX ( www.gotdotnet.com/codegallery/codegallery.aspx?id=0826d7a6-1dab-4a71-8e70-f2170c3c1661) ,是一个专注于扩展 VFP 的社会区网站,给 VFP 开发人员发布了许多很棒的程序。使我不变地惊讶的不但是他创作程序的数量并慷慨地向大家发表了,而且创造性地实现了他的想法。这篇文章标记我身为 FoxTalk 作家的 10 周年纪念,开始新的一个系列,看看 Craig 已经创作了的一些工具。
加密函数库
在我在 2006 年一月份 FoxTalk 2.0 的文章“基于角色安全,第二部份”我简要地讨论了 Craig VFPEncryption.FLL ,一个向 VFP 开发人员提供了加密和解密函数的库文件。这个月,我们将更靠近一点的看它。你可以在 www.sweetpotatosoftware.com/files/vfpencryption.zip 下载这个库文件。(译者注: VFPEncryption.FLL 是有两个版本的, http://www.sweetpotatosoftware.com/files/vfpencryption.zip 是用 Visual Studio 2005 编译,需要 C++ 8.0 运行时 MSVCR80.DLL http://www.sweetpotatosoftware.com/files/vfpencryption71.zip 是用 Visual Studio 2003 编译,需要 C++ 7.1 运行时 MSVCR71.DLL VFP9 带有 MSVCR71.DLL 。)
VFPEncryption.FLL 是很简易使用的: SET LIBRARY TO VFPEncryption.FLL ,和调用它的五个函数中的一个。
Encrypt(cString, cKey[, nType[, nMode]]) 加密指定的字符串。我会在后面详述各个参数。
Decrypt(cString, cKey[, nType[, nMode]]) 解密指定的字符串。
EncryptFile(cSourceFileName, cTargetFileName, cKey[, nType[, nMode]]) 加密指定文件,创建目标文件的结果为函数返回值。(两个文件名要指完整的路径)
DecryptFile(cSourceFileName, cTargetFileName, cKey[, nType[, nMode]]) 解密指定的文件到目标文件。
Hash(cString[, nHashType]) 获得指定的字符串的 hash 值。 Hash 是单向加密程序,没有方法解密的。它是经常用于密码,储存初始密码的 hash ,然后当用户登录时,输入的密码的 hash 值和储存的 hash 值进行比较。 Hash 的值的好处是不同于其他(加密)机制,没有能够被泄密的私人密匙。
如下是参数的说明:
cKey 是用加密和解密的密匙。很明显,解密时,你必须提供用来加密字符串或文件相同的密匙。密匙根据不同的加密类型需要特定的长度。
nType 加密的类型。 VFPEncryption.FLL 支持 6 种加密类型。 0 AES128 ,要求 16 个字符的密匙, 1 AES192, 要求 24 个字符的密匙, 2 (默认) AES256 ,要求 32 个字符的密匙, 4 Blowfish ,要求 56 个字符的密匙, 8 TEA ,要求语 16 个字符的密匙,或者 1024 RC4 ,这种情况密匙可以任意长度。
nMode 加密的模式,指定 0 (默认)电子源码书( ECB )(网摘:密码块操作的一种模式,其主要特点为每一种可能存在的纯文本内容都拥有固定的密文与之相对应,而且反之亦然。换言之,相同的纯文本内容总会被转化成相同的密文), 1 是密码块连接 (CBC) (网摘:密码块运算的一种模式,密码块中一系列的二进制代码利用整个数据块中的密钥加密成单元或数据块。密码块链接使用了广为人知的固定长度的初始微量),还有 2 是密文反馈 (CFB) (网摘:一种密码块操作模式。与密码块链接模式相对,它对一定数位大小的密码块纯文本进行一次性加密,有时候需要对一些纯文本数据值进行逐一加密并传输,这时密文反馈就是一种有效的方法。)如果使用 RC4 加密,就会忽略该参数据的值。
nHashType 使用 hash 函数的类型,指定 1 SHA1 (也叫做 SHA160 ), 2 SHA256 3 SHA384 4 (默认)是 SHA512 5 MD5 6 RIPEMD128 ,或者 7 RIPEMD256
如果你不懂得不同的加密类型和模式,不用担心,我真的没有关于这一方面的一个线索,这是我喜欢 VFPEncryption.FLL 的主要原因。 TestVFPEncryption.PRG 是一个示范使用这个函数库的小程序。
set library to VFPEncryption.FLL
* Test encrypting and decrypting a string.
lcString    = 'This is pretty cool stuff!'
lcKey       = padr('This is a secret key phrase.', 32)
 && padded to the length needed by the default
 && encryption type
lcEncrypted = Encrypt(lcString, lcKey)
wait window lcEncrypted
wait window Decrypt(lcEncrypted, lcKey)
* Test encrypting and decrypting a file.
EncryptFile(fullpath('TestVFPEncryption.prg'), ;
 fullpath('EncryptedFile.prg'), lcKey)
modify file EncryptedFile.prg
DecryptFile(fullpath('EncryptedFile.prg'), ;
 fullpath('DecryptedFile.prg'), lcKey)
modify file DecryptedFile.prg
* Test hashing a string.
wait window Hash(lcString)
分割控件
分割条是很有趣的控件:它们本身真的没有可视的界面,却能让你们在两个或更多其他控件之间通过调节一个的尺寸,而改变其他控件的相关尺寸。分割条在 Windows 应用系统的许多地方里出现,在 Windows 的资源管理器,能使用分割条调节左右窗格的尺寸。分割条可以是水平的(左右调整对象)或垂直的(上下调整对象),和可以在同一个视窗(表单)使用分割条的两种类型。
1999 7 FoxTalk 我的专栏中,“ Splitting Up is Hard to Do ”,我介绍的一个 VFP 分割条类, SFSplitter ,和具体的子类用于水平( SFSplitterH )和垂直( SFSplitterV )的分割。它们是相当的复杂类:它们自动地添加另外一个类, SFSpliterCover ,到它们的父对象和使用 OLE 拖放实现分割条的移动。添加一个分割条到表单要拖放适当的分割条类到表单和设置相同的属性,表明了控件的名受移动的分割条影响。虽然这个类十分困难地去创建,但我已经成功在许多项目使用和不但心存在的复杂性。
去年夏天, Craig 在他的博客中发布一个不同实现方法的分割条类,我必须承认我是怀疑的。在 Splitter.VCX 里仅仅只有一个单独的 Splitter 类,它只有一个属性用来设置垂直,指定分割条是否是垂直的或水平的 - 而且不是很多的代码。它是假设每个可视控制是左右(垂直分割的情况)或上下(水平分割的情况)的,当移动分割条时,分割条被影响,(这是)一个合理的假设,尽管你可以放置字符串“ DoN't_MoVe_SpLiT ”入 Tag 的任何控件的会被忽略。
我们去看看它是如何工作的,然后钻研它的代码。从 Craig 的网站下载 www.sweetpotatosoftware.com/files/splitter.zip ,解压到一个目录,并执行 do form splitter 。这是示例的表单,如图 1 所示,有三个编辑框和两个分割条,一个水平和另一个垂直。上下移动水平分割条和留意三个编辑框被适当地改变尺寸。左右移垂直分割条,下面两个编辑必然被调整了。
1
现在编辑这个表单,注意除了适当直改变尺寸和定位外,只是常规地改变两个分割条控件的属性分别是 Anchor (因些它们响应表单的尺寸变化)和 Vertical (指示如何分割的动作)。
MousePointer 属性设成“ 9-Size WE ”,但在 Init 方法中,如果 Vertical .f. 把它改为“ 7-Size NS ”,因此,移动鼠标到控件上时将指针转换成适当的形状,明显使用户知道它是分割条控件。 MouseDown 事件记录鼠标当前的 X Y 坐标(依赖 Vertical 的设置记录 X 还是 Y )到 MouseDownAt 自定义属性。 MouseUp MouseLeave 都设置这个属性为 0
实际的工作是在 MouseMove Move 里,由于版面原因我不在这里展示这些代码,但会详细说明它们。
MouseMove ,当鼠标被移到在控件上面时激发,激发时确保鼠标左键是按下和 MouseDownAt 是大于 0 ,如果鼠标在另一个控件上按下然后移到分割条的上面,这就要阻止任何事发生。如果鼠标移动(它当前的 X Y 坐标不与 MouseDownAt 不相同),只要它不是太靠近表单的边缘时,程序就计算它被移动了多少,(是否太靠近表单的边缘)取决于自定义属性 MinimumSize MouseMove 调用 Move 方法去做实正的移动和重置 MouseDownAt 到新的位置。 MinimumSize 默认是 40 所以控件不能变得如此小,使用你说见不到它们或使用它们,但有必要时可以把它设置一个不同的值。
Move 方法是做受分割条影响的而移动所有控件和分割条本身的卑劣( dirty )行为。它是从判断 MouseDownAt 不是 0 才开始,然后锁定屏幕,那么对象的移动在全部被移动完之前 , 不表现出来,计算鼠标移动的距离,和遍历它父容器中的控件,忽略任何 Tag 属性为“ DoN't_MoVe_SpLiT ”的控件,因为是非可视控件。代码首先保存控件的 Anchor 属性值后设为 0 ,这是必需的否则这个控件在下次表单被改变尺寸时不能无完全显示。如果分割条是垂直的,控件是在分割条的左边或右边,如果是在分割条的右边,代码会调整控件宽度和 Left 属性。如果分割条是水平的,代码做控制它的上面和下面做类似处理。然后恢复控件的 Anchor 属性。在处理父容器的所有控件后,保存分割条的 Anchor 属性,然后把分割条移到它的新位置,再恢复它 Anchor 。最后解锁屏幕。
如果你想以编程方式移动分割条,设置 MouseDownAt 为一个非零值和调用 Move 方法。它能这样使用的,例如,恢复分割条到上次运行地表单的位置。例如,你可以在表单 Init 中用像一下面的代码, lnTop 的值用作水平分割条的 Top 属性。
with This.Splitter
   .MouseDownAt = .Top
   .Move(.Left, lnTop, .Width, .Height)
endwith
它就是这样,正如我前面说的,在这类里没有太多的代码,它比几年前介绍的分割条类简单的多,和更容易使用。然而,我是个过分讲究的人,我决定创建它子类去改变它的一个处理。 Splitter 假设两边的控件最小尺寸相同。可是,有很多时候是一边必须比另一边大的,例如当在变得十分窄小的边上有一个列表框,但在另一边上的标签的容器和文本框,那样应该不是吧。
SFSplitter.VCX SFSplitter 是分割条的子类,它带有两个新属性: nMinimumSize1 ,它包含了分割条左边或上面的控件的最小尺寸,和 nMinimumSize2 ,它包含了分割条右边或下面的控件的最小尺寸。如果在它们默认值 0 离开它们时 Init 设置它们为适当的值。我然后覆盖 MouseMove 去使用这些属性并非 MinimumSize Do form SFSplitter ,看我的子类是如何处理的。留意分割条在它们移动里不是对称,在边上的组件能够比另一个大,因为我设置了 nMinimumSize1 nMinimumSize2 为不同的值。这个表单在 Init 里也改变了水平分割条的初始位置用来展示如何工作的。

进度条控件


进度条控件有时会调用温度计控件,当运行时间长的时候给用户提供反馈运行情况。 Visual FoxPro 已经长期含了一个 ActiveX 控件,微软的 ProgressBar 控件,可以添加到一个表单来提供这类型的反馈。可是,这个控件呈现下降趋势,它不得不要发布和注册 MSCONCTL.OCX 。同时,因为它是的旧控件,你会在其他应用中见到它没有现代外观而象典型的进度条。
在发布分割条控件仅一个星期后, Craig 发布了他的进度条控件, ProgressBarEx.VCX 里的 ProgressBar 。它是百分这一百 VFP 代码,所以没有 ActiveX 发布的担心。你也可以在图 2 里看到,它看起来象一个标准的 Windows Xp 的进度条,完全由色彩的梯度和一个可选的百份比标签。
 
2
 
下载 www.sweetpotatosoftware.com/files/progressbarex.zip 获得 Craig 的进度条控件。运行(压缩包)中的 Example 表单,在微调器中输入一个百份数值,看一下它是如何工作的。这三条进度条展示了它能表现的不同方式。
让我们来看一下 Craig 是如何实现他的进度条的。在 ProgressBarEx.VCX 里有两个类: PBBar ,它是表现在进度条中单独的色块,和 ProgressBar 进度条的本身。
ProgressBar 有几个决定它外观的属性:
BarColor 进度条的颜色,当选择 1 是红色, 2 (默认)是绿色,和平是蓝色。
Bars 进度条的色块数。数值越大,色块就越细。
Min 进度条的最小值,默认是 0
Max 进度条的最大值,默认是 100
Percentage 当前完成的百份比。
ShowPercentage 当是 .t. 时,在进度条中显示百份数。
SolidBar–.t. 时显示实心, .f. 时(默认)显示为一个个的色块。
Value 进度条的当前值,你不必要指定百份比数值。例如,如果你的程序是处理 1249 条记录,就设置 Max 1249 Value 就是正在处理的记录号。
ProgressBar Init 方法实例化 Bars 属性指定数量的 PBBar 实例,但没有设置它们的 Visible 属性设为 .t. ,所以它们最初是没有显示的。如果 ShowPercentage .t. 它也会添加一个标签到控件。 Value 属性有个 Assign 方法,用来计算有多少色块要显示,并设置那些色块对象的 Visible 属性为 .t. ,如果 ShowPercentage .t. 也要更新标签的标题。 Percentage 属性有一个 Access 方法,根据 Min Max ,和 Value 的值计算完成的百份比。
做出这个象 Winows XP 控件的进度条真不可思议的是 PBBar 类。它的 Init 接受逐个色块的颜色,宽度和高度三个参数(通过 ProgressBar 传递,当它实例化这些对象时)。为了显示一个色块, Init 实例化了一系列 Line 对象,一个 Line 对像对应进度条的高度的一个像素。这些线用不同的颜色画,从中间的深色调到上下的较浅色调,做出一个过度的效果。同时, PBBar 设置线的 DrawMode 属性为“ 14-Merge Pen Not ”。这才让百份比的标签用正确的颜色显示出来,即使它部份地或者完全地覆盖了色块。
要使用 Craig ProgressBar 类,简单地把它拖到表单上,根据需要设置属性,和在处理循环里设 Value 为一个合理值。然而,你可能想在与从开始处理过程的同一个表单中显示进度,并非使用单独的表单显示一些事情的进度。例如,我喜欢用一些类型表单的状态栏,它会在状态栏的一个面板中很好地显示进度条。我用的是 Rick Strahl wwStatusBar 控件而不是 ActiveX 微软的 StatusBar 控件,同样原因, Craig 的进度条比 ActiveX 控件更好的,看看 www.west-wind.com/presentations/wwstatusbar/wwstatusbar.asp ,这是描述这个类的文章和下载源代码的链接。
ProgressBar 有一个小小的问题,它要在 Init 中做所有的设置。这种方式的问题是它要求属性在属性窗口里设置好需要的值。如果你用编程方式实例化了这个类, Init 事件在你有机会设置属性之前激发。所以,我创建了一个 ProgressBar 的子类, SFProgressBar.VCX 中的 SFProgressBar 。我把 ProgressBar Init 里的代码复制到一个叫做 SetupProgressBar 的新方法里,并在 Init 里加了一个注释,所以当这个类实例化时没有事情发生。因为我懒和更合适地避免必须要手动调用 SetupProgressBar ,所以我添加了一个叫 lSetup 的自定义属性,默认值为 .f. ,和在 SetupProgressBar 的结尾设它为 .t. 。然后,我用下面的代码覆盖 Value_Assign
lparameters tuNewVal
* Set up the progress bar if it hasn't been done.
if not This.lSetup
 This.SetupProgressBar()
endif not This.lSetup
* If the value is 0, let's be invisible. Otherwise,
* ensure we can be seen.
This.Visible = tuNewVal <> 0
dodefault(tuNewVal)
这保证了 Value 第一次获得设置时,进度条被完全地设置。我确定当 Value 0 时进度条不可见,其他值才可见,所以这段代码是这样处理的。
我也建了一个 wwStatusBar http://www.west-wind.com/presentations/wwStatusBar/wwStatusBar.zip )的子类,在 SFStatusBar.VCX 里叫 SFStatusBar 。这个类的 Init 方法实例化 SFProgressBar 为表单的 ProgressBar 属性,增加它一个 Panel 自定义属性,用指明的进度条在状态的那个面板显示,和用了 BINDEVENT() ,所以当这个属性被改变时,新方法 PutProgressBarInPanel 被激发。我也加了调用 Resize 用来克服 wwStatusBar 的一个问题,当表单第一次显示时,由于它的 Resize 方法,它不能完整显示,这样设置是绑定到表单的 Resize 事件。如表单没有改变尺寸,状态栏适当地没被调整尺寸。
This.NewObject('ProgressBar', 'SFProgressBar', ;
 'SFProgressBar.vcx')
addproperty(This.ProgressBar, 'Panel', 1)
bindevent(This.ProgressBar, 'Panel', This, ;
 'PutProgressBarInPanel', 1)
dodefault()
This.Resize()
看在运行中的 SFStatusBar ,执行 SFProgress 表单我单击“ Start Process ”按钮,如图 3 所示,进度条显示在状态栏的第二个面板里。
3
这个表单在 Init 里有下面的代码,在状态栏里创建一对面板和把进度条放入面板 2 里。
with This.oStatus
 .AddPanel('Ready', 300, .T., 0)
 .AddPanel('', 200, .F., 1)
 .RenderPanels()
 .ProgressBar.Panel = 2
endwith
按钮的 Click 方法里用一个伪循环来示范这个进度条。
* Have status panel 1 indicate what we're doing.
Thisform.oStatus.UpdatePanel(1, 'Processing...')
* Perform a loop and show the progress.
for lnI = 1 to 100
 Thisform.oStatus.ProgressBar.Value = lnI
 inkey(0.02, 'H')
next lnI
* Reset the progress bar back to 0 and update status
* panel 1.
Thisform.oStatus.ProgressBar.Value = 0
Thisform.oStatus.UpdatePanel(1, 'Ready')
总结
这个月,我们看了 Craig Boyd 慷慨捐赠给 VFP 社区的三个工具:一个加密函数库及分割条和进度条控件。下个月,我们将看的控件是基于 VFP 的日历,滚动条和任务面板。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值