PowerBuilder开发应用系列讲座(20)
使用PowerBuilder另外500个函数(中)
上期我们介绍了调用WindowsAPI函数的方法,本期继续介绍几个常用的API函数。
文件拷贝例程
Windows操作系统在像文件操作一类的低级函数调用方面相当灵活,而在PowerBuilder中为了实现这一些低级操作,开发者们必须用第三方开发库(如:FUNCky
for PowerBuilder库)或用C语言之类的语言开发自己的库,这种方法我们将在后面的章节中讨论。在这里,我们首先介绍如何调用WindowsAPI函数实现简单而又常用的低级操作:文件拷贝。
使用WindowsAPI而不用第三方开发库的主要好处是:如果这是所要做的唯一低级操作,在发布应用时就不需要同时将额外的库打包进去。但如果还需使用第三方开发库提供的其它服务,为简单起见,使用第三方开发库所提供的例程可能要更方便些。
实现
首先声明下列local external函数:
Function long LZOpenFile(string FileName, REF ws_ofstruct FileStructu
re, uint style)
Library "lzexpand.dll"
Function long CopyLZFile(uint SourceHandle, uint DestHandle) Library"lzexpand.dll"Function
long LZClose (uint FileHandle) Library "lzexpand.dll"
ws_ofstruct的窗口级结构如下:

键入下面的窗口级函数:
wf_copy
//返回: boolean
//参数:
//string as_source
//string as_dest
long ll_SourceFileHandle, ll_DestFileHandle, ll_result
ws_ofstruct lstr_SourceFileStructure, lstr_DestFileStructure
//打开源文件
ll_SourceFileHandle = LZOpenFile ( as_source, lstr_SourceFileStructure,
0)
IF ll_SourceFileHandle = -1 THEN
MessageBox ( "程序错误", "无法打开文件: " + as_source
)
Return FALSE
END IF
//打开目标文件
ll_DestFileHandle = LZOpenFile ( as_dest, lstr_DestFileStructure, 4096
)
IF ll_DestFileHandle = -1 THEN
MessageBox ( "程序错误", "无法创建文件: " + as_dest
)
LZClose ( ll_SourceFileHandle )
Return FALSE
END IF
//拷贝
ll_result = CopyLZFile ( ll_SourceFileHandle, ll_DestFileHandle )
IF li_result < 0 THEN
MessageBox ("程序错误","无法拷贝文件: " + as_source
+ " to file: " + as_dest )
LZClose ( ll_SourceFileHandle )
LZClose ( ll_DestFileHandle )
Return FALSE
END IF
//关闭文件
LZClose ( ll_SourceFileHandle )
LZClose ( ll_DestFileHandle )
Return TRUE
工作原理
Windows所带的COMPRESS.EXE是一个可执行程序,用于处理采用Lempel-ziv算法压缩的文件。此外Windows内部还包含了几个处理这一算法的函数,其中LzCopy函数可以用来生成解压缩文件。同时LzCopy函数的文档中还有如下说明:"如果原文件未被压缩,该函数复制原文件。"于是LzCopy函数也可以用作一个快速的文件拷贝函数。
LzCopy函数有两个参数:原文件和目标文件的句柄。但不幸的是,PowerBuilder提供的FileOpen函数返回的文件句柄并不是LzCopy所需要的那个句柄。因此,如果调用WindowsAPI中的LzCopy函数,我们必须同时使用LzOpenFile和LzClose函数,以确保获得所需要的文件句柄。
LzFileOpen函数有三个参数。第一个参数是要打开的文件名。第二个参数是一个结构,这个结构将在函数调用时填入有关这个文件的信息。与PowerBuilder的FileOpen函数一样,LzFileOpen函数可以创建或打开一个文件。该函数的第三个参数指明该函数是被用来以只读方式打开文件(0),还是以只写方式创建文件(4096)。
当我们打开了源文件和目标文件后,我们只要简单地将返回的这两个文件的句柄传递给LzCopy函数,就可实现文件拷贝。最后,在退出之前调用LzClose函数来关闭这两个文件。
判断另一应用是否正在运行
实现
首先声明下列local external函数
Function uint GetModuleHandle(string ModuleName) Library "kernel"
Function uint GetModuleUsage(uint ModuleName) Library "kernel"
Function uint FindExecutable(string FileName, REF string Directory,
REF string Result) Library "shell"键入下面的窗口级函数:
fw_check_app_status
//返回: boolean
//参数:
// string as_filename
// string as_directory
integer li_size = 144, li_result
string ls_executable = Space ( li_size )
integer li_module_usage
uint li_module_handle
li_result = FindExecutable ( as_filename, as_directory, ls_executable
)
IF li_result < 32 THEN Return FALSE
//如可执行文件已载入,获取这个执行文件的句柄
li_module_handle = GetModuleHandle ( ls_executable )
IF li_module_handle < 1 THEN
//没有载入
Return FALSE
ELSE
//获取有多少个实例被载入
li_module_usage = GetModuleUsage ( li_module_handle )
Return TRUE
END IF
工作原理
这段程序可以获取某个应用是否正在运行。
我们用WindowsAPI中的GetModuleHandle函数来判定是否有另一个应用正在运行。为了做到这一点,我们需要知道文件的全路径名(包括驱动器名和路径)。我们可以将它包含在应用的.INI文件中,也可以通过写入源代码的方法将它嵌入可执行程序。这里向大家推荐的是采用前一种方法,这样做可使应用具有更大的灵活性。在上面的窗口级函数中,我们首先在用户的Windows目录中查找WIN.INI文件。因为进行查询的应用与特定扩展名的文档之间的关联被记录在WIN.INI文件中。于是我们所要做的第一件事就是在WIN.INI文档中查找这一关联,以知道我们所要寻找的应用是通过哪个软件装入的。我们可以自己搜索WIN.INI文件,或者调用WindowsAPI中的FindExecutable函数来得到这一信息。这里,我们使用了第二种方法。只要将与希望寻找的可执行程序相关联的文件的名称与路径传递给FindExecutable函数,就会得到该可执行程序的全路径名。我们有时需要判断某可执行程序是否在运行,如果没有就启动它。在这种情况下,以上方法是很有用的。
一旦获得了可执行程序的全路径名,我们将它传递给GetModuleHandle函数。如果应用正在运行,则该函数返回应用的句柄。如果返回0,说明应用并没有装入,此时退出函数。如果应用正在运行,我们将获得的应用的句柄传递给GetModuleUsage函数。这个函数的返回值会告诉我们这个应用有几个不同的实例。在我们的例子中,如果查询的应用是Microsoft
Word,该应用不允许多个实例同时运行,但像NotePad这样的应用,可多个实例同时运行。这些信息对还是非常有用的。