PowerBuilder编程俱乐部

大家好!PowerBuilder(以下简称PB)编程俱乐部又与大家见面了,各位可到俱乐部主页http://kjx.126.com或http://pb70.yeah.net的BBS讨论区去提交或解答问题。如遇主页访问故障,可以直接访问论坛:http://kukoc.abc.yesite.com,俱乐部欢迎你的到来!
一、请问用PB如何调用Windows的API函数,即具体要在哪几个地方写些代码?最好能给出实例。
  答:调用 API 函数步骤为:
  1.在适当的位置声明函数,如窗口内、Application内、UserObject内,定义在Local External Function或Global External Function中。如播放声音的API函数:
  Function boolean sndPlaySoundA (string SoundName,uint Flags) Library ″WINMM.DLL″
  Function uint waveOutGetNumDevs () Library ″WINMM.DLL″
  也可以创建一个UserObject,集中声明常用的API及函数本地化,如定义用户对象u_external_function:
  Declare Local External Function(定义外部函数):
  Function boolean sndPlaySoundA (string SoundName,uint Flags) Library ″WINMM.DLL″
  Function uint waveOutGetNumDevs () Library ″WINMM.DLL″
  Declare User Object Function(定义用户对象函数):
   uf_play_sound(string as_wave_name,integer ai_option)
  函数内容如下:
   //参数:as_wave_name :wav文件名
   //ai_option:同步或异步(I/0)
   uint lui_numdevs
   lui_numdevs = WaveOutGetNumDevs()
   if lui_numdevs > 0 Then
   sndPlaySoundA(as_wave_name,ai_option)
   return 1
   else
   return -1
   end If
  2.调用时在程序中定义一个实体并调用其函数:
   u_external_function iu_external_function
   iu_external_function = create u_external_function
   iu_external_function.uf_play_sound(′c:\windows\media\ding.wav′,1)
  试试看,如果有声卡,就会听到“叮”的一声。
  其它API函数也是如此处理。关于如何声明,在俱乐部的主页上有一个帮助,在我的主页PB手记http://liulee.yeah.net 的“源码天地”下也有一个集成了常用API函数的用户对象,你可以下载回去参考。(此题由流方回答)
二、如何在PB应用程序中创建目录?
  答:可以用API函数CreateDirectoryA实现,定义:
  function boolean CreateDirectoryA(ref string pathname,int sa) Library ″Kernel32.dll″
  调用代码:
   boolean rtn
   string ls_dir
   ls_dir = ″c:\newdir″ //要创建的目录名称
   rtn = CreateDirectoryA(ls_dir,0)
   if rtn then
   Messagebox(″Succeed″,″Succeed!″)
   else
   Messagebox(″Failed″,″Failed!″)
   End if
三、我编的系统中用了OCX控件,当系统编译后发行时必须带上该OCX控件,但在用户的机子上必须注册该OCX控件才能使用,否则程序运行会出错,请问用什么方法注册该OCX控件?
  答:提供以下几种方法供参考:
  1.在Windows命令行或DOS下运行:regsvr32 ocxname.OCX
  2.用Install Shield 做安装程序时,在里面选“Self-Registered”,安装程序将自动注册。
  3.在PB程序中调用regsvr32实现,安装程序只需负责将OCX拷贝到相应路径下,这个路径PB程序必须可以得到,建议拷贝到Windows系统目录或者与执行文件同目录下。
  具体代码:
  //首先定义API函数,如果OCX控件在与执行文件同目录下,使用GetCurrentDirectory函数;如果OCX控件放在系统目录下,使用GetSystemDirectory函数。
  Function ulong GetCurrentDirectory(ulong nBufferLength,ref string lpBuffer) Library ″kernel32.dll″ Alias for ″GetCurrentDirectoryA″
  Function uint GetSystemDirectory(ref string lpBuffer,uint uSize) Library ″kernel32.dll″ Alias for ″GetSystemDirectoryA″
  //假设OCX文件在Windows系统目录下,在PB应用(Application)的Open事件中编写如下代码
  string ls_PathName,ls_Command
   ulong ll_RequiredBufferSize
   ls_PathName = Space(255)
   ll_RequiredBufferSize = GetSystemDirectory(ls_PathName,255)
   IF ll_RequiredBufferSize=0 or ll_RequiredBufferSize>255 THEN
   //报错信息
   else
   ls_Command = ″Regsvr32 /s ″ + ″~″″ + ls_PathName + ″\Myocx.ocx″ + ″~″″
  Run (ls_Command)
   …
   end if
   Regsvr32后面的″/s″执行参数是为了隐藏注册成功消息框。(此方法由张涛提供)
4.在PB应用程序中注册:
   函数声明:
   Function long DllRegisterServer() Library ″ocxname.OCX″
   调用:
   LONG ll_RC
   ll_RC = DllRegisterServer()
四、如何带参数执行SQL的系统储存过程?我想在script中执行系统存储过程Sp_DropUser删除MS SQL Server 7某用户。我是这样写的:execute Sp_DropUser(Sp_DropUser语法),编译提示Sp_DropUser为未定义的系统存储过程。
  答:代码如下:
   string ls_name
   ls_name = ′username′ //要删除的用户名
   //定义存储过程
   dECLARE dropUser_proc PROCEDURE FOR Sp_DropUser
   @name_in_db =:ls_name;
   SQLca.AutoCommit = TRUE
   EXECUTE dropUser_proc ; //执行
   SQLca.AutoCommit = false