在應用程序的編寫中,組合框(ComboBox)、列表框(ListBox)、等常見的部件,通常不僅要用於顯示文字,而且還要顯示其與文字相關的圖標。在一般的Windows應用程序中,這些圖標的顯示都要隨列出的顯示文本的變化而變化,例如在組合框中列出當前目錄下的所有文件時,在組合框左邊就顯示與文件名相關聯的圖標,這就是所謂的動態圖標。在Delphi中使用動態圖標的步驟如下:
一、圖標的獲取
要使用動態圖標,首先要解決的是如何獲得顯示文本和與其相關聯的圖標句柄。該圖標通過文件關聯由系統注冊表決定,並且在Windows編程中同一文件(或子目錄,或文件夾)在桌面上也可能有兩種顯示結果,這就是DOS文件名與顯示名(Display Name)。如果我們的應用程序不需要有像Windows資源浏覽器那樣的效果,則可以使用FindFirst()和FindNext()二個函數以及FindClose()過程來獲得DOS文件名,否則我們就應當使用WindowsAPI來獲得顯示名。在獲得文件名的同時可通過使用ShellAPI.pas中的SHGetFileInfo()函數來獲得其圖標句柄HICON,說明如下:
function SHGetFileInfo(pszPath: PAnsiChar; dwFileAttributes: DWORD;var psfi: TSHFileInfo; cbFileInfo,uFlags: UINT): DWordl;
pszPath 參數:指定的文件名。當uFlags的取值中不包含 SHGFI_PIDL時,可直接指定;否則pszPath要通過計算獲得,不能直接指定;
dwFileAttributes參數:文件屬性,僅當uFlags的取值中包含SHGFI_USEFILEATTRIBUTES時有效,一般不用此參數;
psfi 參數:返回獲得的文件信息,是一個記錄類型,有以下字段:
hIcon: HICON; //文件的圖標句柄
iIcon: Integer; //圖標的系統索引號
dwAttributes: DWord; //文件的屬性值
szDisplayName: array [0..MAX_PATH-1] of AnsiChar; //文件的顯示名
szTypeName: array [0..79] of AnsiChar; //文件的類型名
cbFileInfo 參數:psfi的比特值;
uFlags 參數:指明需要返回的文件信息標識符,常用的有以下常數:
SHGFI_ICON; //獲得圖標
SHGFI_DISPLAYNAME; //獲得顯示名
SHGFI_TYPENAME; //獲得類型名
SHGFI_ATTRIBUTES;//獲得屬性
SHGFI_LARGEICON; //獲得大圖標
SHGFI_SMALLICON; //獲得小圖標
SHGFI_PIDL;// pszPath是一個標識符
函數SHGetFileInfo()的返回值也隨uFlags的取值變化而有所不同。通過調用SHGetFileInfo()可以由psfi參數得到文件的圖標句柄,但要注意在uFlags參數中不使用SHGFI_PIDL時,SHGetFileInfo()不能獲得"我的電腦"等虛似文件夾的信息。
二、圖標的加載
使用Delphi提供的TImageList組件,通過調用CommCtrl .pas中的函數ImageList_AddIcon()來加載得到的圖標,並要保證其索引號與顯示文本相對應。說明如下:
function ImageList_AddIcon(ImageList: HIMAGELIST; //加載圖標的ImageList句柄
Icon: Hicon //加載的圖標句柄 ): Integer; //返回圖標在ImageList中的索引號
在需要指明圖標索引號時可使用ImageList_AddIcon()的返回值。
三、圖標和文本的繪圖式輸出
對於組合框、列表框等不能直接顯示圖標的組件,由於要求顯示圖標的同時又要同時顯示文本,可通過設置其相應的Style屬性達到目的,示例如下:
組合框:ComboBox1.Style:=csOwnerDrawVariable根據實際使用經驗最好不要在ObjectInspector窗體中直接設置,而應將代碼添加在程序的適當位置,否則可能出現繪圖區域高度不規則變化
列表框:ListBox1.Style:=lbOwnerDrawVariable
狀態欄:StatusBar1.Panels[i].Style:= psOwnerDraw 不能使用簡單狀態欄,i是狀態欄中要繪制圖標的某一窗格索引號,圖形輸出可使用TImageList的ImageList1.Draw()方法,而文本輸出則可使用TCanvas的TextOut()方法,它由組件的Canvas屬性繼承得到,顯然沒有Canvas屬性的組件不能使用此方法顯示圖標。
對於可直接顯示圖標的組件,直接指定其Images、StateImages等需要的圖標屬性為相應的TimageList組件名,並通過指定圖標的索引號則可顯示圖標。需要注意的是:在使用大圖標時,必須先調用TImageList的CreateSize()方法指定可加載圖標的尺寸,並且在每次調用TImageList的Clear方法後都要重新調用CreateSize()。
使用TImageList的ImageList1.Clear方法清除已加載的圖標,常在需要刷新時使用。