王朝网络
分享
 
 
 

用API函数改进ListView控件的显示效果

王朝厨房·作者佚名  2007-01-04
宽屏版  字体: |||超大  

王建兵

ListView使用简介

ListView控件是VB开发者非常喜爱的控件之一。作为Windows95公共控件组(COMCTL32.OCX) 的成员,它经常与经常与TreeView、ImageList等控件联合使用。即用TreeView显示一个的树 型结构,而用ListView显示选中的节点(Node)对象的记录

集。

这是笔者在开发财务软件项目中的$#@60;$#@60;凭证管理$#@62;$#@62;模块的一个用户界 面。屏幕左边是一个TreeView控件,用来显示会计凭证的类别;右边是一个istView,用来显示 对应类别的凭证目录;上方是一个菜单条控件(MenuBar)和一个工具条控件(ToolBar);下方是 一个状态栏控件(StatusBar),用来显示凭证数个当前日期。

大家可以看到图中所 示的界面非常类似于Window95/98的资源浏览器,Windows的界面风格做为一种标准已为广大 用户所接受。而Windows操作系统的主要的优点就是为所有的应用程序提供了公用的界面。知道 如何使用基于Windows的应用程序的用户,很容易学会使用其他应用程序。

这种使 用Windows95公共控件组合的方法能够达到与Windows界面的一致性,所以在目前VB5.0应用 程序的开发中经常使用。

二、填充大量结果集所遇到的问题

在实际应用开发中,经常用ListView填充一个数据库结果集(Recordset)的内容。即先写 一段SQL查询语句,产生一个结果集,然后将结果集的每一条记录用DO...LOOP循环语句中填到ListView 中。

但是当结果集很大时(例如有5000条以上的记录),填充所需要的时间会很长。 用户不得不等很长时间完成一个查询。所以在查询的过程中必须允许用户按Escape键退出。具 体做法是在DO...LOOP循环体中加一条DoEvents函数,并写一段中断退出程序代码。

DoEvents函数的功能是:转让控制权,以便让操作系统处理其它的事件。这样在长时间的查询 过程中,如果用户按了Escape键,将退出循环体,结束查询过程。

但是这样又会引 发另外一个问题:由于DoEvents可以让操作系统响应别的事件,循环体中填充每一条ListView 项目(ListItem)的过程也会显示出来,所以在填充的过程中屏幕会不停的闪动,这种现象当然 不能被用户所接受。如何解决这个问题呢?

三、解决方案

用WindowsAPI函数可以解决这个问题。首先对几个用到的API函数做一解释和说明。

1.GetClientRectLib"user32"(ByValhwndAsLong,lpRectAsRECT)As Long

此函数的功能是获得一个指定对象窗 Window)的矩型框区域(rectangle)。

Hwnd为指定对象或窗体的句柄。LpRect为返回矩型框的结构(必须定义为结构类型的变量)。

2.ValidateRectLib"user32"(ByValhwndAsLong,lpRectAsRECT)As Long

此函数的功能是使指定的矩型区域生效。这样会通知Windows不必对指定 的区域进行重画(Redraw)。

3.InvalidateRectLib"user32"(ByVal hwndAsLong,lpRectAsRECT,ByValbEraseAsLong)AsLong

此函数的 功能是使指定的矩型区域无效。这样会通知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

ListViewLvw

ImagelistimlList

CommandButton。Command1

将ImageList控件中充填一个名为“item”的图象后与ListView控件关联。

在$#@60;$#@60;工程$#@62;$#@62;菜单命令条中进入“引用”对话框,选择“MicrosoftDAOObjectLibrary”

在Form的通用模块(Modle)中定义以下变量。

PrivateTypeRECT用来定义一个区域的坐标。

LeftAsLong

TopAsLong

Right AsLong

BottomAsLong

EndType

--

Windows API函数的声明。

PrivateDeclareFunctionInvalidateRectLib"user32"

(ByVal hwndAsLong,lpRectAsRECT,ByValbEraseAsLong)AsLong

PrivateDeclare FunctionValidateRectLib"user32"

(ByValhwndAsLong,lpRect AsRECT)AsLong

PrivateDeclareFunctionGetClientRectLib"user32"

(ByVal hwndAsLong,lpRectAsRECT)AsLong

DimmbSearchCancelAsBoolean

用来定义查询中断的标志。

True表示中止查询;False表示正在查询。

将该Form的KeyPreview属性设为True,以控制窗体接收键盘事件。

然后在Form 的KeyPress事件中写下列代码:

IfKeyAscii=vbKeyEscapeThen

mbSearchCancel=True

当用户按Escape 键时,置mbSearchCancel变量为True。

EndIf

表示结束查询。

在Command Button的Click事件中调用填充子程序:CallFillListView。

子程序的代码 为:

PrivateSubFillListView()

DimitmXAsListItem定义一 个ListView的显示项目。

DimsSQLAsString查询字串变量。

Dim rcAsRECTListView的显示区域。

DimwrkJetAsWorkspace数据库工作空间。

Dim dbFISCALAsDatabase数据库对象。

DimRSAsRecordset数据结果集。

On ErrorGoToErrFillListView

Screen.MousePointer=vbHourglass

lvw.ListItems.Clear: 清除ListView的内容。

定义ListView的列头的名称。

With lvw.ColumnHeaders

.Add,,"凭证编号",800

.Add,," 凭证日期",1000

.Add,,"凭证字号",1000

.Add,," 凭证类别",800

.Add,,"首行摘要",1440

.Add,," 借方金额合计",1000,lvwColumnRight

EndWith

- --

产生查询语句。

sSQL="selectvoucher_id,voucher_number,voucher_date,

voucher_type_shortname,"

sSQL=sSQL&"voucher_type_name,voucher_memo,voucher_amount fromVOUCHER"

sSQL=sSQL&"orderbyvoucher_number"

---

打开一个数据库结果集。

SetwrkJet=CreateWorkspace("NewJetWorkspace", "admin","",

dbUseJet)

SetdbFISCAL=wrkJet.OpenDatabase("FISCAL.mdb")

Set RS=.dbFISCAL.OpensSQL,dbOpenForwardOnly

获得listview 的显示区域。

CallGetClientRect(lvw.hwnd,rc)

DoWhileNotRS.EOF()

DoEvents

If mbSearchCancelThen

中断退出

RS.Close:SetRS=Nothing关闭、清 除结果集。

mbSearchCancel=False

Screen.MousePointer=vbDefault

--

刷新ListView的内容,显示已经查出的记录数。

CallInvalidateRect(lvw.hwnd, rc,True)

ExitSub

EndIf

---

增加一个显示 项目ListItem。

Withlvw.ListItems

SetitmX=.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

EndWith

--

避免显示区域的闪动现象。

Call ValidateRect(lvw.hwnd,rc)

RS.MoveNext

Loop

- 刷新ListView的内容。显示所有查出的记录数。

CallInvalidateRect(lvw.hwnd,rc, True)

-

关闭、清除结果集。

RS.Close:SetRS=Nothing

creen.MousePointer =vbDefault

ExitSub

ErrFillListView:

Screen.MousePointer= vbDefault

MsgBoxErr&":"&Error,vbInformation,Me.Caption

Exit Sub

EndSub

编写完毕后按F5执行该程序,用鼠标点击CommandButton,将 开始查询并填写凭证的内容到ListView中去。

关于ListView本文只是描述了它 如何填充大量结果集的方法,它还有很多特性(property)和方法(method),利用它们可以达到 更完美的显示效果,有兴趣的读者可以进一步研究。不管是开发什么样的应用程序,只有坚持 面向用户、方便用户的原则,这样的软件才具有强大的生命力。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有