用API改进ListView显示效果

来源:互联网 发布:大数据和java哪个好 编辑:程序博客网 时间:2024/06/07 04:31
   ListView简介
  ListView控件是VB开发者非常喜爱的控件之一。作为Windows 95 公共控件组(COMCT L32.OCX)的成员,它经常与TreeView、ImageList 等控件联合使用。用 TreeView 显示一个树型结构,而用 ListView 显示选中的节点(Node)对象的记录集,如下图所示: 图1
  这是笔者在开发财务软件项目中的"凭证管理"模块的一个用户界面。屏幕左边是一个TreeView控件,用来显示会计凭证的类别;右边是一个ListView,用来显示对应类别的凭证目录;上方是一个菜单条控件 (MenuBar)和一个工具条控件(ToolBar);下方是一个状态栏控件(Stat usBar),用来显示凭证数和当前日期。
  可见图中所示的界面非常类似于Window 95/98的资源浏览器, Wi ndows的界面风格作为一种标准已为广大用户所接受,而Windows 操作系统的主要优点就是为所有的应用程序提供了公用的界面。掌握了使用基于Windows的应用程序的用户,很容易学会使用其他应用程序。
  这种使用Windows 95公共控件组合的方法能够达到与Windows界面保持一致性,所以在目前VB5.0应用程序的开发中经常使用。
  填充大量结果集的问题
  在实际应用开发中,经常用ListView填充一个数据库结果集(Reco rdset)的内容。即先写一段SQL查询语句,产生一个结果集,然后将结果集的每一条记录用DO...LOOP循环语句中填到ListView中。
  但是当结果集很大时(例如有5000条以上的记录),填充所需要的时间会很长,用户不得不等很长时间完成一个查询,所以在查询的过程中必须允许用户按 Escape键退出。具体做法是在DO...LOOP循环体中加一条DoEvents函数,并写一段中断退出程序代码。
  DoEvents函数的功能是:转让控制权,以便让操作系统处理其他的事件。这样在长时间的查询过程中,如果用户按了Escape键,将退出循环体,结束查询过程。
  但是这样又会引发另外一个问题:由于DoEvents可以让操作系统响应别的事件,循环体中填充每一条ListView项目(ListItem)的过程也会显示出来,所以在填充的过程中屏幕会不停地闪动,这种现象当然不能被用户所接受。如何解决这个问题呢?
  解决方法
  用Windows API函数可以解决这个问题。这里首先对几个用到的A PI函数做一解释和说明。
  1. GetClientRect Lib "user32" (ByVal hwnd As Long, lpRec t As RECT) As Lo ng
  此函数的功能是获得一个指定对象窗口(Window)的矩型框区域(r ectangle)。
  Hwnd为指定对象或窗体的句柄。LpRect为返回矩型框的结构(必须定义为结构类型的变量) 。
  2. ValidateRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Lon
  此函数的功能是使指定的矩型区域生效,通知Windows不必对指定的区域进行重画(R edraw)。
  3. InvalidateRect Lib "user32" (ByVal hwnd As Long, lpRe ct As RECT, ByVa l bErase As Long) As Long
  此函数的功能是使指定的矩型区域无效,通知Windows要对指定的区域进行重画。
  具体实现步骤如下:
  1. 在填充结果集之前先用GetClientRect函数获得ListView的显示区域。
  2. 在增加完一个显示项目(ListItem)后用ValidateRect函数置这一区域为有效。这样Windows就不会显示每一条ListItem,屏幕闪动的现象就会消失。
  3. 在填充结果集之后, 用InvalidateRect函数置这一区域为无效。这样Windows就会重画ListView的内容,结果集被完整地显示出来。
  本文给出笔者在项目开发中的一个程序实例,程序名为FillListV iew。该程序将一个Access数据库(FISCAL.MDB)的凭证表(Table)的内容填写到ListView中。
  首先进入VB5.0,新建一个窗体(Form),名为Form1。
  然后在Form中增加下列控件。
    控件名      Name
    ListView     Lvw
    ImageList    imlList
    Command Button  Command1
  将ImageList 控件中充填一个名为"item"的图像后与ListView控件关联。
  在"工程"菜单命令条中进入"引用"对话框,选择"Microsoft DAO Object Library"。
  在Form的通用模块(Modle)中定义以下变量。
  Private Type RECT
   ' 用来定义一个区域的坐标。
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
  End Type
  ' Windows API 函数的声明。
  Private Declare Function InvalidateRect Lib "user32" (By Val hwnd As Long , lpRect As RECT, ByVal bErase As Long) As Long
  Private Declare Function ValidateRect Lib "user32" (ByVa l hwnd As Long,l pRect As RECT) As Long
  Private Declare Function GetClientRect Lib "user32" (ByV al hwnd As Long, lpRect As RECT) As Long
  Dim mbSearchCancel As Boolean
  ' 用来定义查询中断的标志:True 表示中止查询;False表示正在查询。
  将该Form的KeyPreview属性设为True,以控制窗体接收键盘事件。
  然后在Form的KeyPress事件中写下列代码:
  If KeyAscii = vbKeyEscape Then
  mbSearchCancel = True
  '当用户按Escape键时,置mbSearchCancel变量为True。
  End If ' 表示结束查询。
  在Command Button 的 Click 事件中调用填充子程序:Call Fill ListView。
  编者注:子程序FillListView()的代码发表在本报WWW站点上,地址是:http://www.c omputer world.com.cn/98/skill/default.htm 。欢迎访问!
  按F5执行该程序,用鼠标点击CommandButton,将开始查询并将凭证的内容填写到Lis tView中去。
  关于ListView,本文只是描述了它如何填充大量结果集的方法,它还有很多其他特性(property)和方法(method),利用它们可以达到更完美的显示效果,有兴趣的读者可以进一步研究。不管是开发什么样的应用程序,只有坚持面向用户、方便用户的原则,这样的软件才具有强大的生命力。