最近在用Delphi编写程序时发现当ListBox(列表框)中的文本超过显示范围时就看不到文本的完整内容这很不方便于是决定动手解决这个问题让鼠标指到哪里就显示哪里的全部文本内容 一分析问题 我们知道ListBox的Items对象中有一个Strings函数通过指定索引可获取该索引所对应的文本那么我们只要在OnMouseMove事件中获取当前鼠标所指的索引即可获取该索引的文本并使用Hint显示出来因此重点就在获取鼠标所指的索引通过查看帮助文件发现ListBox控件中有一个ItemAtPos函数可返回鼠标所指向的索引找到了这个函数解决问题就容易多了 二解决问题 在窗体中加入一个ListBox控件将ShowHint属性设置为True再添加一个CommandButton控件Caption属性设置为填充ListBox 双击Button控件写入下面的代码 procedure TFormButtonClick(SenderTObject) //用显示System目录中的文件来填充ListBox var SearchRec TSearchRec nResult Integer const szFilePath = d\\windows\\system\\** begin //填充ListBox ListBoxClear nResult=FindFirst(szFilePathfaAnyFileSearchRec) //查找第一个文件 while nResult = do //如果返回值为表示找到文件 begin //将找到的文件添加到ListBox中ExtractFilepath函数用于提取文件路径 ListBoxItemsAdd(ExtractFilePath(szFilePath) + SearchRecName) nResult=FindNext(SearchRec) //继续查找下一个文件至到返回值不为时 end end 下面编写关键的部分代码在ListBox的OnMouseMove事件中加入下面的代码 procedure TFormListBoxMouseMove(SenderTObject ShiftTShiftState XYInteger) var nPosTPoint //将nPos声明为TPoint类型 nIndexInteger begin //填充nPos结构 //由于ItemAtPos是利用鼠标在ListBox中的坐标计算出所指位置的因此我们需要获取鼠标在ListBox中的坐标在OnMouseMove事件中已经为我们提供了鼠标在ListBox中的坐标XY只需将XY赋给nPos的xy即可 nPosx=X nPosy=Y //使用ItemAtPos函数返回鼠标所在ListBox中的位置 nIndex=ListBoxItemAtPos(nPosTrue) if nIndex > then ListBoxHint=ListBoxItemsStrings[nIndex] //显示当前位置的文本 end 将上面的代码完成后就可以实现将鼠标指向ListBox中任何一个Item时就显示出内容来但是程序还有一个Bug每次鼠标移动到ListBox中时只能显示一次这个问题与显示Hint有关程序默认重复显示Hint的时间为毫秒因此只能显示一次Hint只要我们修改重复显示Hint的时间即可解决这个问题在窗体中加入一个ApplicationEvents控件在OnShowHint事件中加入下面的代码 procedure TFormApplicationEventsShowHint(var HintStrString var CanShowBoolean var HintInfoTHintInfo) begin HintInfoReshowTimeout= //设置重显时间这里设为毫秒比较合适 end 修改Hint的重显时间后这个功能就非常的完美了可以看出真正实现这个功能的代码是很少很简单的用一个ItemAtPos函数就可以轻松搞定这就是Delphi可爱的地方不过作为程序员不应该就此满足的如果你有兴趣了解ItemAtPos是怎样获取鼠标所指范围在ListBox中索引的那么请继续向下看 三深入了解 要查看ItemAtPos函数在Delphi中是怎样编写的很简单只要按下Ctrl键不放再用鼠标点击ItemAtPos函数就会自动定位到这个函数的所在位置(用这样的方法我们可以查看Delphi中大多数函数及过程的源代码分析一下这些源代码对我们编写程序是很有帮助的而且也可以很好地了解这些函数是如何工作的) 源码如下 function TCustomListBoxItemAtPos(PosTPoint ExistingBoolean)Integer var CountInteger //记录ListBox中Item的个数 ItemRectTRect //记录Item的范围 begin if PtInRect(ClientRectPos) then //PtInRect是一个API函数用于检测Pos所指的范围是否在ListBox当中ClientRect这里是begin ListBox的范围 Result= TopIndex //将返回值设为ListBox第一个Item的索引值TopIndex为 Count = ItemsCount //计算总数 while Result < Count do //如果当前索引值小于总数则开始循环 begin Perform(LB_GETITEMRECTResultLongint(@ItemRect)) //向ListBox控件发送LB_GETITEMRECT消息获取当前Item的范围 if PtInRect(ItemRectPos) then Exit //如果刚好Pos所指的范围在当前Item的范围内则退出整个函数 Inc(Result) //将Result加相当于Result=Result + end if not Existing then Exit end Result= //如果Pos所指的范围不在ListBox范围内则返回 end 知道了吧?Delphi就是这样做的了解后我们自己也可以写一个这样的函数 |