「快速啟動」列 (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 目錄存在且有寫入權限。");
}
// 組合熱鍵:低位元組為虛擬鍵碼,高位元組為修飾鍵旗標
// 修飾鍵:HOTKEYF_CONTROL(2), HOTKEYF_ALT(4), HOTKEYF_SHIFT(1), HOTKEYF_EXT(8)
scShortcut.wHotKey = MAKEWORD('N', HOTKEYF_CONTROL | HOTKEYF_ALT); // Ctrl+Alt+N
SetIconLocation 接受任何含圖示資源的檔案 (.exe, .dll, .ico)nIconIndex 為資源索引 (0 為第一個),可用工具 (如 Resource Hacker) 查看strIconFile 為空,系統自動使用目標檔案預設圖示| 常數 | 值 | 效果 |
|---|---|---|
| SW_HIDE | 0 | 隱藏視窗 |
| SW_SHOWNORMAL | 1 | 正常顯示 (預設) |
| SW_SHOWMINIMIZED | 2 | 最小化顯示 |
| SW_SHOWMAXIMIZED | 3 | 最大化顯示 |
| SW_SHOWNOACTIVATE | 4 | 顯示但不激活 |
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 目錄,系統會自動映射到任務列。
SHGetSpecialFolderLocation 是否成功;2) Quick Launch 目錄是否存在 (使用者可能從未啟用);3) 目錄寫入權限;4) 目標檔案是否存在;5) COM 初始化 (CoInitialize) 是否在線程呼叫前完成。strIconFile 路徑錯誤;2) nIconIndex 超出資源範圍;3) 圖示快取未刷新,嘗試 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL) 通知 Shell。CSIDL_COMMON_APPDATA (All Users\Application Data) 拼接相同相對路徑,但需管理員權限寫入。