最近在用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就是這樣做的了解後我們自己也可以寫一個這樣的函數
From:http://tw.wingwit.com/Article/program/Delphi/201311/24668.html