在應用程式的撰寫中,組合方塊(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方法清除已載入的圖標,常在需要刷新時使用。