首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 實現檔案拖放功能:取得圖示並顯示於 ListView

     編輯:VC 教學

前言

實現檔案拖放功能的核心在於:取得檔案路徑、目標路徑、執行複製/移動、提取系統圖示並顯示於 UI。本文示範如何使用 SHGetFileInfo 取得檔案系統圖示索引,並配合 TListView 顯示圖示與檔名,打造類似總管的檔案列表介面。

關鍵 API:SHGetFileInfo


SHFILEINFO FileInfo;
HIMAGELIST hImgList;

// 1. 取得系統圖示清單控制代碼(大圖示)
hImgList = (HIMAGELIST)SHGetFileInfo(
    "C:\\Windows\\Notepad.exe",  // 任意存在檔案即可初始化系統圖示清單
    0,
    &FileInfo, sizeof(FileInfo),
    SHGFI_SYSICONINDEX | SHGFI_LARGEICON
);

// 2. 將系統圖示清單關聯至 ListView
SendMessage(ListView1->Handle, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)hImgList);

新增項目並指定圖示索引


// 取得特定檔案的圖示索引
SHGetFileInfo(
    "C:\\Windows\\Notepad.exe",
    0, &FileInfo, sizeof(FileInfo),
    SHGFI_ICON | SHGFI_LARGEICON  // 注意:此處用 SHGFI_ICON 取得實際圖示控制代碼
);
// FileInfo.iIcon 即為系統圖示清單中的索引

TListItem* item = ListView1->Items->Add();
item->Caption = "Notepad.exe";
item->ImageIndex = FileInfo.iIcon;

// 另一個檔案
SHGetFileInfo(
    "C:\\Windows\\System32\\calc.exe",
    0, &FileInfo, sizeof(FileInfo),
    SHGFI_ICON | SHGFI_LARGEICON
);
item = ListView1->Items->Add();
item->Caption = "Calc.exe";
item->ImageIndex = FileInfo.iIcon;

完整拖放流程實作架構

步驟關鍵 API / 邏輯說明
1. 來源檔案路徑拖曳來源:WM_DROPFILES、DragQueryFile、或 OLE IDropTarget取得被拖曳檔案完整路徑陣列
2. 目標路徑Drop 目標:SHBrowseForFolder、或 ListView 滑鼠座標對應項目決定檔案要放往何處
3. 執行複製/移動CopyFile、MoveFileEx、SHFileOperation實際檔案系統操作
4. 取得圖示SHGetFileInfo + SHGFI_SYSICONINDEX取得系統圖示清單索引,非載入實體圖示
5. 顯示於 UITListView + LVM_SETIMAGELIST將系統圖示清單綁定 ListView,項目指定 ImageIndex

SHGetFileInfo 旗標組合速查

旗標用途備註
SHGFI_ICON取得圖示控制代碼 (HICON)需自行 DestroyIcon
SHGFI_SYSICONINDEX取得系統圖示清單索引 (iIcon)效能最佳,適合 ListView 大量項目
SHGFI_LARGEICON32x32 大圖示配合 LVSIL_NORMAL
SHGFI_SMALLICON16x16 小圖示配合 LVSIL_SMALL
SHGFI_OPENICON取得「開啟狀態」圖示(資料夾打開)較少用
SHGFI_USEFILEATTRIBUTES不需檔案實體存在,僅依屬性/副檔名取得圖示適合虛擬清單

ListView 圖示模式設定


// 表單建立時
ListView1->ViewStyle = vsIcon;        // 或 vsSmallIcon, vsList, vsReport
ListView1->LargeImages = NULL;        // 稍後動態指派
ListView1->SmallImages = NULL;

// 取得系統圖示清單(一次即可,全程複用)
HIMAGELIST hLarge = (HIMAGELIST)SHGetFileInfo("C:\\", 0, &FileInfo, sizeof(FileInfo),
    SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
HIMAGELIST hSmall = (HIMAGELIST)SHGetFileInfo("C:\\", 0, &FileInfo, sizeof(FileInfo),
    SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

SendMessage(ListView1->Handle, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)hLarge);
SendMessage(ListView1->Handle, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)hSmall);

虛擬清單模式(大量檔案效能優化)

  • 設定 ListView1->OwnerData = true。
  • 處理 OnData 事件,動態提供 Caption、ImageIndex。
  • 搭配 SHGFI_USEFILEATTRIBUTES 避免逐一 SHGetFileInfo 呼叫檔案系統。

常見問題與解決

現象原因解決
圖示顯示為空白未正確關聯 ImageList 或 ImageIndex 超界檢查 LVM_SETIMAGELIST 參數、確認 iIcon 有效
所有檔案顯示相同圖示重複使用同一 FileInfo 變數未重新呼叫 SHGetFileInfo每個檔案單獨呼叫 SHGetFileInfo 取得各自 iIcon
圖示模糊/尺寸錯誤Large/Small ImageList 對應錯誤vsIcon 用 LargeImages (LVSIL_NORMAL),vsSmallIcon 用 SmallImages (LVSIL_SMALL)
SHGetFileInfo 返回 0路徑不存在、權限不足、旗標衝突檢查 GetLastError,嘗試 SHGFI_USEFILEATTRIBUTES

拖放實作補充:WM_DROPFILES 簡易版


// 表單啟用拖放
DragAcceptFiles(Handle, TRUE);

// 處理 WM_DROPFILES 訊息
void __fastcall TForm1::WMDropFiles(TMessage &Msg)
{
    HDROP hDrop = (HDROP)Msg.wParam;
    UINT fileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

    for (UINT i = 0; i < fileCount; ++i)
    {
        char path[MAX_PATH];
        DragQueryFile(hDrop, i, path, MAX_PATH);
        // 取得圖示索引並加入 ListView
        SHFILEINFO fi;
        SHGetFileInfo(path, 0, &fi, sizeof(fi), SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
        TListItem* item = ListView1->Items->Add();
        item->Caption = ExtractFileName(path);
        item->ImageIndex = fi.iIcon;
        item->Data = (void*)StrNew(path); // 保存完整路徑
    }
    DragFinish(hDrop);
}

掌握 SHGetFileInfo + 系統圖示清單 + TListView 的組合,即可輕鬆打造具備原生檔案圖示顯示的專業級檔案管理介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved