PowerBuilder编程俱乐部

Author: 柯建勋 Date: 1999年 第43期 13版


  大家好!PowerBuilder编程俱乐部自第一期推出以来,受到广大PB爱好者的热烈欢迎,每天都有大量的读者来信,在这里版主真诚感谢朋友们的关心和支持,PB编程俱乐部将一如既往地为大家服务。各位可到俱乐部主页http://kjx.126.com或http://pb70.yeah.net的BBS讨论区去提交问题或解答问题,如你平时编程有何经验与心得,也可拿出来与大家共享,俱乐部的原信箱同时开放。你的支持和参与就是我们前进的动力!
  不少网友来信询问有哪些学习PowerBuilder编程的好站点,今后PB编程俱乐部将不定期的向大家推荐一些国内优秀的PowerBuilder网站。今天向大家介绍的是“PB能量建造者”http://pb7.126.com,站长:潘亚、鹿寒。一个非常出色的PB个人主页,新建不久但内容详实,而且更新很快。有PB专题、技巧、文摘、下载和讨论区等栏目,收录优秀的PB专题文章、讲座、教材, 有包括Datawidow、API调用、数据库等在内的大量编程技巧,并且提供文档、数据库驱动和PB例程下载。该站还定期举办PB网友网上聚会,网友见面认识,交流心得,疑难问题嘉宾现场交流解答,是PB爱好者学习、交流的好地方。
  一、问:我想做一个数据窗口的组合条件查询,要得到数据窗口中的所有列名及其text的文字说明,请问怎样才能取得?
  答:Describe()函数可以得到数据窗口的多项属性值,用它实现如下:
  long   ll_column_count
  long   ll_i
  string  ls_column[]  //列名
  string  ls_column_text[]  //text的名字
  //得到数据窗口的总列数
  ll_column_count = long(dw_1.Describe(″DataWindow.Column.Count″)) 
  //循环依次读取
  for ll_i = 1 to ll_column_count 
  ls_column[ll_i] = dw_1.Describe(″#″+string(ll_i)+″.Name″)
  ls_column_text[ll_i] = dw_1.Describe(ls_column[ll_i] + ″_t.text″)
  next
  说明:数组ls_column[]保存当前数据窗中所有列名
  数组ls_column_text[]保存当前数据窗中列对应的text的文字说明。
  注:数据窗口dw_1的对象(DataObject)中text命名须用默认值,即列名+ _t的形式,如列名为“name”,则其对应text应取名为“name_t”,否则返回值不正确。
  二、问:在应用程序运行时,数据库Sysbase SQL Anywhere 5.0启动后在系统状态条上会有图标,有时用户会不小心将其关闭,造成系统出错。请问如何隐藏Sysbase SQL Anywhere 5.0在系统状态条上的的图标?
  答:可以通过更改系统注册表来实现。以Powersoft Demo DB V6 为例:
  运行注册程序regedit,找到注册表中HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\Powersoft Demo DB V6中名为Start的项目,如其原值为“C:\Program Files\Sybase\SQL Anywhere 5.0\Win32\dbeng50.exe”,在其后加上参数 -Q,改为“C:\Program Files\Sybase\SQL Anywhere 5.0\Win32\dbeng50.exe -Q”即可。 
  对于自己创建的其它Sysbase SQL Anywhere 5.0数据库可用同样方法实现。
  三、问:一般用鼠标单击窗口右上角的“X”时,窗口立即关闭,但有的程序在退出时会弹出一个确认窗口供用户确认,这是如何实现的?
  答:可以利用窗口的CloseQuery事件在用户关闭窗口时进行确认。在CloseQuery事件中加入脚本:
  long ll_return
  ll_return = MessageBox(″提示信息″,″确认退出吗?″, Question! , YesNo! , 1 )
  if ll_return = 2 then 
  Return 1 //不关闭窗口
  else
  Return 0 //关闭窗口
  end if
  四、问:怎样得到程序运行时的路径?
  答:用API函数GetModuleFileNameA()可实现。
  在global external functions声明:
  Function uLong GetModuleFileNameA(long hinstModule, Ref String lpszPath, uLong cchPath) Library ″kernel32.dll″
  使用:
  string   ls_AppPath
  int li_ret
  ls_AppPath = Space (128) 
  li_ret = GetModuleFileNameA (Handle (GetApplication ()), ls_apppath, 128) 
  说明:要编译成可执行文件.exe才可用,否则得到的是Powerbuilder的pb60.exe或PB050.exe的路径。程序路径保存在变量ls_AppPath中。
  五、问:我编写的脚本忘了在哪个窗口了,怎么办?总不能让我把几十个窗口逐个打开,每个事件中来查找吧。
  答:同时选中这几十个窗口,点Entry菜单,再点击Serach菜单项,输入你要查找的脚本内容,点确定即可。系统将列出所有符合要求的窗口、控件、事件及脚本所在的行数。
  查找同样适用于函数、菜单、用户对象等。
  六、问:请问怎样限制应用程序只运行一次?
  答:提供两种实现方法(用于32位操作系统):
  1.首先在global external functions声明外部函数如下: 
  FUNCTION long FindWindowA( ulong Winhandle, string wintitle ) Library ″user32″ 
  然后在application的 Open 事件中加入如下代码: 
  ulong l_handle, lu_class
  string ls_name
  ls_name = ″我的系统″ // 此处ls_name为系统主窗口的标题Title
  l_handle = FindWindowA(lu_class, ls_name)
  if l_handle > 0 then
  MessageBox(″提示信息″, ″应用程序″ + This.AppName + ″已经运行,不能多次启动!″)
  Halt Close
  else
  open(w_main) // 此处为系统主窗口
  end if
  这种方法是PowerBuilder联机帮助中的一个例子,是以系统主窗口的标题Title作为判别依据,若有其它与此Title同名应用程序在运行,再想启动此程序也会报应用程序已经运行。你可以将Title设为“计算器”,然后启动Windows附件中计算器程序,再运行你的PB应用程序试试。
  2.声明外部函数:
  function ulong CreateMutexA (ulong lpMutexAttributes, int bInitialOwner,  ref string lpName) library ″kernel32.dll″ 
  function ulong GetLastError () library ″kernel32.dll″ 
  然后在application的 Open 事件中加入如下代码: 
  ulong ll_mutex, ll_err 
  string ls_mutex_name 
  if handle (GetApplication (), false) <> 0 then 
  ls_mutex_name = this.AppName + char (0) 
  ll_mutex = CreateMutexA (0, 0, ls_mutex_name) 
  ll_err = GetLastError () 
  if ll_err = 183 then 
  // 程序已经运行
  MessageBox (″提示信息″, ″程序已经运行了!″) 
  Halt close 
  else 
  // 程序未运行
  open(w_main)
  end if 
  else //开发模式
  open(w_main)
  end if 
  这种方法必须在应用程序编译成可执行文件.exe后才有效。