文章探索:   分类:    关键字:  
  + 栏目导航
  + 相关文章
文本框中光标位置的获得
用VB导入导出你的IE收藏夹
VB应用程序访问SQL Server方法探讨
VB访问SQL Server数据库技术全揭密
自动上网抓数据的机器人
自己的IE——用VB制作浏览器
VB中如何保存Webbrowser中的整个页面..
在VB中该如何控制其它程序的弹出窗口..
保存webbrowser中的HTML内容
破译动网验证码的简单方法
轻松获取QQ密码
VB.NET获取硬盘序列号的方法
WEBBROWSER 技巧一(收藏)
VB自动登陆网络站点详解(二):Inet..
获取webbrowser控件网页的源码
WebBrowser控件说明
关于用VB做更漂亮的窗体的思考
VB中访问存储过程的几种办法
VB6中改变屏幕的分辨率和刷新频率
VB编写一个能显示百分比的自定义进度..
公农历转换VB类
VB.NET窗口渐淡关闭
使用VB实现邮箱自动注册(二):修改..
VB.NET轻松实现任务栏程序
VB.NET启动外部程序
利用vb实现图片上传
VB实现局域网内的文件传输
VB 一个Function传回多个值
在VB中实现多线程
VB 手机号码编码程序


技术教程 -> VB教程 ->  
用API函数改进ListView控件的显示效果
来源:转载   人气:889   录入时间:2007-11-8
    一、ListView使用简介
     ListView控件是VB开发者非常喜爱的控件之一。作 为Windows95公共控件组(COMCTL32.OCX)的成员,它经常与经常与TreeView、ImageList等控 件联合使用。即用TreeView显示一个的树型结构,而用ListView显示选中的节点(Node)对 象的记录集。
     这是笔者在开发财务软件项目中的<<凭证管理>> 模块的一个用户界面。屏幕左边是一个TreeView控件,用来显示会计凭证的类别;右边是一 个ListView,用来显示对应类别的凭证目录;上方是一个菜单条控件(MenuBar)和一个工具 条控件(ToolBar);下方是一个状态栏控件(StatusBar),用来显示凭证数个当前日期。
   
     大家可以看到图中所示的界面非常类似于Window95/98 的资源浏览器,Windows的界面风格做为一种标准已为广大用户所接受。而Windows操作系 统的主要的优点就是为所有的应用程序提供了公用的界面。知道如何使用基于Windows的 应用程序的用户,很容易学会使用其他应用程序。
   
     这种使用Windows95公共控件组合的方法能够达 到与Windows界面的一致性,所以在目前VB5.0应用程序的开发中经常使用。
   
   二、填充大量结果集所遇到的问题
     在实际应用开发中,经常用ListView填充一个数据库 结果集(Record set)的内容。即先写一段SQL查询语句,产生一个结果集,然后将结果集的每一 条记录用DO...LOOP循环语句中填到ListView中。
     但是当结果集很大时(例如有5000条以上的记录) ,填充所需要的时间会很长。用户不得不等很长时间完成一个查询。所以在查询的过程中 必须允许用户按Escape键退出。具体做法是在DO...LOOP循环体中加一条DoEvents函数,并 写一段中断退出程序代码。
   
     DoEvents函数的功能是:转让控制权,以便让操 作系统处理其它的事件。这样在长时间的查询过程中,如果用户按了Escape键,将退出循环 体,结束查询过程。
   
     但是这样又会引发另外一个问题:由于DoEvents 可以让操作系统响应别的事件,循环体中填充每一条ListView项目(ListItem)的过程也会显示出来,所以在填充的过程中屏幕会不停的闪动,这种现象当然不能被用户所接受。如何 解决这个问题呢?
   
   三、解决方案
     用WindowsAPI函数可以解决这个问题。首先对几个 用到的API函数做一解释和说明。
     1.GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
   
     此函数的功能是获得一个指定对象窗口(Window) 的矩型框区域(rectangle)。
   
     Hwnd为指定对象或窗体的句柄。LpRect为返回矩 型框的结构(必须定义为结构类型的变量)。
   
     2.ValidateRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
   
     此函数的功能是使指定的矩型区域生效。这样会 通知Windows不必对指定的区域进行重画(Redraw)。
   
     3.InvalidateRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT, ByVal bErase As Long) As Long
   
     此函数的功能是使指定的矩型区域无效。这样会 通知Windows要对指定的区域进行重画。
   
     具体实现的步骤如下:
   
     1.在填充结果集之前先用GetClientRect函数获 得ListView的显示区域。
   
     2.在增加完一个显示项目(ListItem)后用ValidateRect 函数置这一区域为有效。这样Windows就不会显示每一条ListItem,屏幕闪动的现象就会消 失。
   
     3.在填充结果集之后,用InvalidateRect函数置 这一区域为无效。这样Windows就会重画ListView的内容,结果集被完整的显示出来。
   
     下面是笔者在项目开发中的一个程序实例。程序 名为FillListView。该程序将填写一个Access数据库(FISCAL.MDB)的凭证表(Table)的内 容到ListView中。
   
     首先进入VB5.0,新建一个窗体(Form),名为Form1。
   
     然后在Form中增加下列控件。
   
   
    控 件 名 Name
   
   ListView Lvw
   
   Imagelist imlList
   
   Command Button。 Command1
   
   
     将ImageList控件中充填一个名为“item”的图象后 与ListView控件关联。
   
     在<<工程>>菜单命令条中进入“引用”对话框,选 择“MicrosoftDAOObjectLibrary”
   
     在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"
   
    (ByVal hwnd As Long, lpRect As RECT, ByVal bErase As Long) As Long
   
   Private Declare Function ValidateRect Lib "user32"
   
   (ByVal hwnd As Long, lpRect As RECT) As Long
   
   Private Declare Function GetClientRect Lib "user32"
   
   (ByVal 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 FillListView。
   
   
   
    子 程 序 的 代 码 为:
   
   Private Sub FillListView()
   
   '
   
   Dim itmX As ListItem ' 定 义 一 个ListView 的 显 示 项 目。
   
   Dim sSQL As String ' 查 询 字 串 变 量 。
   
   '
   
   Dim rc As RECT ' ListView 的 显 示 区 域。
   
   Dim wrkJet As Workspace ' 数 据 库 工 作 空 间。
   
   Dim dbFISCAL As Database ' 数 据 库 对 象。
   
   Dim RS As Recordset ' 数 据 结 果 集。
   
   
   
   On Error GoTo ErrFillListView
   
   
   
    Screen.MousePointer = vbHourglass
   
   lvw.ListItems.Clear: ' 清 除ListView 的 内 容。
   
   '     
   
   ' 定 义ListView 的 列 头 的 名 称。
   
   With lvw.ColumnHeaders
   
    .Add , , " 凭 证 编 号", 800
   
    .Add , , " 凭 证 日 期", 1000
   
    .Add , , " 凭 证 字 号", 1000
   
    .Add , , " 凭 证 类 别", 800
   
    .Add , , " 首 行 摘 要", 1440
   
    .Add , , " 借 方 金 额 合 计", 1000, lvwColumnRight
   
   End With
   
   
   
    '   - - -
   
    ' 产 生 查 询 语 句。
   
   sSQL = "select voucher_id,voucher_number,voucher_date,voucher_type_shortname,"
   
   sSQL=sSQL&"voucher_type_name,voucher_memo,voucher_amount from VOUCHER"
   
    sSQL = sSQL & "order by voucher_number"
   
   ' '   - - -
   
    ' 打 开 一 个 数 据 库 结 果 集。
   
    Set wrkJet = CreateWorkspace("NewJetWorkspace", "admin", "", dbUseJet)
   
    Set dbFISCAL = wrkJet.OpenDatabase("FISCAL.mdb")
   
    Set RS=. dbFISCAL .Open sSQL,dbOpenForwardOnly
   
    '     
   
    ' 获 得listview 的 显 示 区 域。
   
    Call GetClientRect(lvw.hwnd, rc)
   
   
   
    Do While Not RS.EOF()
   
    DoEvents
   
    If mbSearchCancel Then
   
   ' 中 断 退 出
   
    RS.Close: Set RS = Nothing ' 关 闭、 清 除 结 果 集。
   
    mbSearchCancel = False
   
    Screen.MousePointer = vbDefault
   
    '   - -
   
    ' 刷 新ListView 的 内 容, 显 示 已 经 查 出 的 记 录 数。
   
    Call InvalidateRect(lvw.hwnd, rc, True)
   
    Exit Sub
   
    End If
   
    '   - - -
   
    ' 增 加 一 个 显 示 项 目ListItem。
   
    With lvw.ListItems
   
    Set itmX = .Add(, , "" & RS!voucher_number, "item", "item")
   
    ' 凭 证 编 号
   
    itmX.SubItems(1) = Format$("" & RS!voucher_date, "yyyy/mm/dd")
   
    ' 凭 证 日 期
   
    itmX.SubItems(2) = "" & RS!voucher_type_shortname & "-" —
   
    ' 凭 证 字 号
   
   & "" & RS!voucher_number
   
   
   
    itmX.SubItems(3)="" & RS!voucher_type_name
   
    ' 凭 证 类 别
   
    itmX.SubItems(4)=""&RS!voucher_memo
   
    ' 首 行 摘 要
   
    itmX.SubItems(5)= Format$("" & RS!voucher_amount, "#,###.00")
   
    ' 借 方 合 计 金 额
   
    itmX.Tag = "" & RS!voucher_id
   
    End With
   
    '   - -
   
    ' 避 免 显 示 区 域 的 闪 动 现 象。
   
    Call ValidateRect(lvw.hwnd, rc)
   
    RS.MoveNext
   
   Loop
    
   
   '- 刷 新ListView 的 内 容。 显 示 所 有 查 出 的 记 录 数。
   
    Call InvalidateRect(lvw.hwnd, rc, True)
   
   '   -
   
   ' 关 闭、 清 除 结 果 集。
   
    RS.Close: Set RS = Nothing
   
    creen.MousePointer = vbDefault
   
    Exit Sub
   
   ErrFillListView:
   
    Screen.MousePointer = vbDefault
   
    MsgBox Err & ":" & Error, vbInformation, Me.Caption
   
    Exit Sub
   
   End Sub
   
   
      编 写 完 毕 后 按F5 执 行 该 程 序, 用 鼠 标 点 击CommandButton, 将 开 始 查 询 并 填 写 凭 证 的 内 容 到ListView 中 去。
   
      关 于ListView 本 文 只 是 描 述 了 它 如 何 填 充 大 量 结 果 集 的 方 法, 它 还 有 很 多 特 性(property) 和 方 法(method), 利 用 它 们 可 以 达 到 更 完 美 的 显 示 效 果, 有 兴 趣 的 读 者 可 以 进 一 步 研 究。 不 管 是 开 发 什 么 样 的 应 用 程 序, 只 有 坚 持 面 向 用 户、 方 便 用 户 的 原 则, 这 样 的 软 件 才 具 有 强 大 的 生 命 力。
   
   
   




Copyright(C)2007-2024 广州市佳沛数码科技有限公司 版权所有
公司地址: 广州市荔湾区东漖北路560号511室
电话:020-81803473 传真:020-81544987