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

在 Windows 快速啟動列建立捷徑完整實現 (C++ Builder)

     編輯:VC 教學

前言

「快速啟動」列 (Quick Launch) 是 Windows 98~7 早期版本任務列旁的工具列區域,允許使用者單鍵啟動常用程式。雖 Windows 7+ 以任務列釘選取代,但企業環境、舊系統維護、特定自動化腳本仍有需求。本文提供基於 IShellLink 的完整實現,封裝為可重用的 TShortcutCfg 結構與 CreateQuickLaunchShortcut 函數。

快速啟動目錄路徑解析

快速啟動目錄位於使用者設定檔下:


// 典型路徑 (Windows XP/2000/Server 2003):
%APPDATA%\Microsoft\Internet Explorer\Quick Launch\
// 即:C:\Documents and Settings\Username\Application Data\Microsoft\Internet Explorer\Quick Launch\

// Windows Vista/7 (若啟用舊版快速啟動):
%APPDATA%\Microsoft\Internet Explorer\Quick Launch\

程式碼使用 SHGetSpecialFolderLocation(CSIDL_APPDATA) 獲取 %APPDATA%,再拼接固定相對路徑。

完整代碼實現 (來自原文,經整理修正)


#define NO_WIN32_LEAN_AND_MEAN
#include 
#include 

// 捷徑配置結構
struct TShortcutCfg {
    TShortcutCfg() {
        nShowCmd = SW_SHOWNORMAL;
        wHotKey = 0;
        nIconIndex = 0;
    }
    AnsiString strShortcutName;  // 捷徑名稱 (不含 .lnk)
    AnsiString strLnkDir;        // 保留欄位,本實現固定用 Quick Launch 目錄
    AnsiString strDestFile;      // 目標檔案完整路徑
    AnsiString strArguments;     // 命令列參數
    AnsiString strIconFile;      // 圖示來源檔案
    int        nIconIndex;       // 圖示索引
    AnsiString strWorkingDir;    // 工作目錄
    AnsiString strDescription;   // 描述/工具提示
    WORD       wHotKey;          // 熱鍵
    int        nShowCmd;         // 顯示命令 (SW_SHOWNORMAL 等)
};

// 在快速啟動列建立捷徑
bool CreateQuickLaunchShortcut(TShortcutCfg* scConfig) {
    char szBuf[MAX_PATH];
    bool bReturn = true;
    wchar_t wszBuf[MAX_PATH];
    IShellLink* pShellLink = NULL;
    AnsiString strShortcutFile;
    LPITEMIDLIST lpItemIdList = NULL;

    // 1. 獲取 %APPDATA% 路徑
    HRESULT hr = SHGetSpecialFolderLocation(0, CSIDL_APPDATA, &lpItemIdList);
    if (FAILED(hr)) return false;

    if (SHGetPathFromIDList(lpItemIdList, szBuf)) {
        if (DirectoryExists(AnsiString(szBuf))) {
            // 組合完整 .lnk 路徑
            strShortcutFile = AnsiString(szBuf) + 
                "\\Microsoft\\Internet Explorer\\Quick Launch\\" + 
                scConfig->strShortcutName + ".lnk";
            strShortcutFile.WideChar(wszBuf, MAX_PATH);
        } else {
            bReturn = false;
        }
    } else {
        bReturn = false;
    }
    CoTaskMemFree(lpItemIdList); // 釋放 PIDL
    if (!bReturn) return false;

    // 2. 建立 Shell Link 物件
    hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                          IID_IShellLink, (void**)&pShellLink);
    if (FAILED(hr)) return false;

    // 3. 獲取 IPersistFile 介面
    IPersistFile* ppf = NULL;
    hr = pShellLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
    if (FAILED(hr)) { pShellLink->Release(); return false; }

    // 4. 設定捷徑屬性 (逐項檢查失敗即停止)
    if (bReturn && scConfig->strDestFile != "")
        bReturn = SUCCEEDED(pShellLink->SetPath(scConfig->strDestFile.c_str()));

    if (bReturn && scConfig->strArguments != "")
        bReturn = SUCCEEDED(pShellLink->SetArguments(scConfig->strArguments.c_str()));

    if (bReturn && scConfig->strIconFile != "" && FileExists(scConfig->strIconFile))
        pShellLink->SetIconLocation(scConfig->strIconFile.c_str(), scConfig->nIconIndex);

    if (bReturn && scConfig->strWorkingDir != "")
        pShellLink->SetWorkingDirectory(scConfig->strWorkingDir.c_str());

    if (bReturn && scConfig->strDescription != "")
        pShellLink->SetDescription(scConfig->strDescription.c_str());

    if (bReturn && scConfig->wHotKey != 0)
        pShellLink->SetHotkey(scConfig->wHotKey);

    if (bReturn && scConfig->nShowCmd != 0)
        pShellLink->SetShowCmd(scConfig->nShowCmd);

    // 5. 儲存捷徑檔案
    if (bReturn)
        bReturn = SUCCEEDED(ppf->Save(wszBuf, TRUE)); // TRUE = 覆寫

    // 6. 清理
    ppf->Release();
    pShellLink->Release();
    return bReturn;
}

使用範例


void __fastcall TForm1::Button1Click(TObject *Sender) {
    TShortcutCfg scShortcut;
    scShortcut.strDestFile = "C:\\Program Files\\MyApp\\MyApp.exe";
    scShortcut.strShortcutName = "MyApp";
    scShortcut.strArguments = "/minimized";
    scShortcut.strDescription = "啟動 MyApp 並最小化到系統盤";
    scShortcut.strIconFile = "C:\\Program Files\\MyApp\\MyApp.exe";
    scShortcut.nIconIndex = 0;
    scShortcut.strWorkingDir = "C:\\Program Files\\MyApp";
    // scShortcut.wHotKey = MAKEWORD('M', HOTKEYF_CTRL | HOTKEYF_ALT); // Ctrl+Alt+M

    if (CreateQuickLaunchShortcut(&scShortcut))
        ShowMessage("快速啟動捷徑建立成功!");
    else
        ShowMessage("建立失敗:請確認 Quick Launch 目錄存在且有寫入權限。");
}

關鍵技術點補充

1. 熱鍵設定 (wHotKey)


// 組合熱鍵:低位元組為虛擬鍵碼,高位元組為修飾鍵旗標
// 修飾鍵:HOTKEYF_CONTROL(2), HOTKEYF_ALT(4), HOTKEYF_SHIFT(1), HOTKEYF_EXT(8)
scShortcut.wHotKey = MAKEWORD('N', HOTKEYF_CONTROL | HOTKEYF_ALT); // Ctrl+Alt+N

2. 圖示處理

  • SetIconLocation 接受任何含圖示資源的檔案 (.exe, .dll, .ico)
  • nIconIndex 為資源索引 (0 為第一個),可用工具 (如 Resource Hacker) 查看
  • 若 strIconFile 為空,系統自動使用目標檔案預設圖示

3. 顯示命令 (nShowCmd)

常數值效果
SW_HIDE0隱藏視窗
SW_SHOWNORMAL1正常顯示 (預設)
SW_SHOWMINIMIZED2最小化顯示
SW_SHOWMAXIMIZED3最大化顯示
SW_SHOWNOACTIVATE4顯示但不激活

Windows 7+ 環境下的替代方案

Windows 7 移除了傳統快速啟動列,改用任務列釘選。程式化釘選需使用 ITaskbarList3 介面 (需 Windows 7 SDK):


// 概念代碼,需連結 Windows 7 SDK
ITaskbarList3* pTbl = NULL;
CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&pTbl);
pTbl->HrInit();
// 釘選應用程式到任務列
pTbl->AddTab(hwnd); // 或使用 IShellLink + 特殊屬性

但此 API 不直接支援「釘選任意 .lnk」,通常做法是建立捷徑到 %APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar 目錄,系統會自動映射到任務列。

常見問題排查

Q: 程式碼返回 false,捷徑未建立?
A: 按序檢查:1) SHGetSpecialFolderLocation 是否成功;2) Quick Launch 目錄是否存在 (使用者可能從未啟用);3) 目錄寫入權限;4) 目標檔案是否存在;5) COM 初始化 (CoInitialize) 是否在線程呼叫前完成。
Q: 捷徑建立了但圖示不顯示?
A: 1) strIconFile 路徑錯誤;2) nIconIndex 超出資源範圍;3) 圖示快取未刷新,嘗試 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL) 通知 Shell。
Q: 如何建立「所有使用者」的快速啟動捷徑?
A: 使用 CSIDL_COMMON_APPDATA (All Users\Application Data) 拼接相同相對路徑,但需管理員權限寫入。

現代化建議

  • 新開發專案應優先支援 任務列釘選 (Windows 7+)
  • 提供「建立桌面捷徑」+「釘選到任務列」雙選項安裝精靈頁面
  • 使用 WiX / InstallShield 等安裝製作工具原生支援捷徑建立,減少自訂代碼
  • 企業環境可透過 Group Policy (GPO) 部署捷徑至使用者快速啟動/任務列
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved