1. 程式人生 > >在桌面建立 LNK 快捷方式

在桌面建立 LNK 快捷方式

有時候,為了方便使用者使用我們編寫的程式,需要在桌面,快速啟動或程式組中建立程式的快捷方式。下面就介紹在VC下如何為程式建立快捷方式。

一.得到桌面,快速啟動或程式組的路徑

這裡介紹二個win32 API函式來完成這個任務。

第一個函式獲得系統特殊路徑

HRESULT SHGetSpecialFolderLocation(

HWND hwndOwner,  int nFolder, PIDLIST_ABSOLUTE *ppidl

);

第一個引數表示所有者視窗控制代碼,一般傳入NULL就可以了。

第二個引數要示是一個整數id,決定哪個目錄是待查詢目錄,它的取值可能是

  CSIDL_BITBUCKET            

回收站

  CSIDL_CONTROLS            控制面板

  CSIDL_DESKTOP              Windows桌面desktop;

  CSIDL_DESKTOPDIRECTORY   desktop的目錄;

  CSIDL_DRIVES                我的電腦

  CSIDL_FONTS                 字型目錄

  CSIDL_NETHOOD             網路上的芳鄰

  CSIDL_NETWORK             網路上的芳鄰virtual folder

  CSIDL_PERSONAL             

我的文件

  CSIDL_PRINTERS              印表機

  CSIDL_PROGRAMS             程式組

  CSIDL_RECENT                最近開啟文件

  CSIDL_SENDTO                傳送到選單項

  CSIDL_STARTMENU            快速啟動選單

  CSIDL_STARTUP               啟動目錄

  CSIDL_TEMPLATES            臨時文件

第三個引數表示一個條目識別符號列表指標,可以傳入一個LPITEMIDLIST型別變數,再從這個變數中得到表示路徑的字串。使用完後,要用void

CoTaskMemFree(void * pv)來釋放資源。

第二個函式將一個條目識別符號列表轉換為一個檔案系統路徑

BOOL SHGetPathFromIDList( 

PCIDLIST_ABSOLUTE pidl,  LPTSTR pszPath

);

第一個引數 pidl就是用第一個函式所得到的條目識別符號列表指標。

第二個引數pszPath返回表示路徑的字串。

這二個函式的標頭檔案均為<shlobj.h>並要引入shell32.lib

下面給出了一個程式,用來列舉你電腦上一些系統特殊路徑:

#include <stdio.h>

#include <windows.h>

#include <shlobj.h>

#pragma comment(lib, "shell32.lib")

int main()

{

const int ENDNUMBER = -1;//哨兵,在遍歷陣列時遇到此數表示已經到達了陣列的最後。

//設定這個後,你可以在nFolders陣列中任意新增刪除資料而不用在遍歷陣列時考慮其中有多少個數據。

CoInitialize(NULL);

int nFolders[] = {

CSIDL_BITBUCKET, CSIDL_CONTROLS, CSIDL_DESKTOP, CSIDL_DESKTOPDIRECTORY,

CSIDL_DRIVES, CSIDL_FONTS, CSIDL_NETHOOD, CSIDL_NETWORK, CSIDL_PERSONAL,

CSIDL_PRINTERS, CSIDL_PROGRAMS, CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU,

CSIDL_STARTUP, CSIDL_TEMPLATES, ENDNUMBER

};

HRESULT hr;

LPITEMIDLIST ppidl;

char          szPath[MAX_PATH];

int i = 0; 

while (nFolders[i] != ENDNUMBER)

{

hr = SHGetSpecialFolderLocation(NULL, nFolders[i], &ppidl);

if (hr != S_OK)

{

printf("SHGetSpecialFolderLocation Error\n");

}

else

{

if (SHGetPathFromIDList(ppidl, szPath))

printf("%s\n", szPath);

else

printf("SHGetPathFromIDList Error\n");

CoTaskMemFree(ppidl);

}

i++;

}

CoUninitialize();

return 0;

}

由於系統的差異,有時會輸出“SHGetPathFromIDList Error”,在我電腦上就輸出了5次。有了這個例子,相信不難寫出得到桌面桌面(CSIDL_DESKTOP),快速啟動(CSIDL_APPDATA),程式組(CSIDL_PROGRAMS)的路徑函式。

不過要稍稍注意下快捷啟動,要再加上"\\Microsoft\\Internet Explorer\\Quick Launch"

二.建立快捷方式檔案

完成第一步的任務後接下來的問題是如何建立快捷方式檔案即.lnk檔案。首先要了解快捷方式檔案要設定什麼,然後了了解怎樣設定。

2.1快捷方式檔案有哪些要設定的內容

下面給出了Spy++Kmplayer Plus二個程式的快捷方式。

快捷方式必須設定目標,起始位置,快捷鍵,備註都可以選擇性的設定,執行方式一般取預設值----常規視窗。

2.2如何設定快捷方式檔案的內容

這要用到二個COM介面IShellLinkIPersistFile。由於篇幅問題,這裡只講解二個介面的部分函式。

IShellLink的部分函式

HRESULT SetPath(LPCTSTR pszFile);             設定目標

HRESULT SetWorkingDirectory(LPCTSTR pszDir);  設定起始位置

HRESULT SetHotkey(WORD wHotkey);           設定快捷鍵

HRESULT SetShowCmd(int iShowCmd);           設定執行方式

有三種選擇SW_SHOWNORMAL常規視窗

SW_SHOWMAXIMIZED最大化SW_SHOWMINNOACTIVE最小化

HRESULT SetDescription(LPCTSTR pszName);      設定備註

要特別說下SetHotkey()中的引數WORD wHotkeyMSDN上對其的解釋為:

The address of the hot key. The virtual key code is in the low-order byte, and the modifier flags are in the high-order byte. The modifier flags can be a combination of the following values.

HOTKEYF_ALT        ALT key

HOTKEYF_CONTROL   CTRL key

HOTKEYF_EXT        Extended key

HOTKEYF_SHIFT      SHIFT key

意思就是對這個WORD值,低位上是virtual key code,高位上可以是ALT,CTRL等組合鍵。可以用MAKEWORD(low, high)來生成一個WORD,如Ctrl+F12可以用MAKEWORD(VK_F12, HOTKEYF_CONTROL)表示。

IPersistFile的部分函式

HRESULT Save(          儲存快捷方式

LPCOLESTR pszFileName, BOOL fRemember

);

第一個引數是要儲存檔案的檔名,要求是絕對路徑。

第二個引數涉及COM的持續性問題(注1),一般傳入TRUE即可。

要建立COM物件可以用CoCreateInstance()函式(見注2)和QueryInterface()函式(見注3)。下面給出了建立的程式碼:

IShellLink*pLink  //IShellLink物件指標

IPersistFile *ppf;      //IPersisFil物件指標

建立IShellLink例項

CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void**)&pLink);

IShellLink物件中獲取IPersistFile介面

pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);

建立之後就可以對pLink設定目標,快捷鍵,備註等,設定完後再用ppf建立快捷方式檔案就可以了。當然最後要記得釋放資源,pLink->Release(); ppf->Release()

三.已封裝好的函式程式碼

下面給出封裝好的函式程式碼,可以在程式中直接使用(在XP+VC6.0下測試過)。

//得到當前桌面路徑

BOOL GetDesktopPath(char *pszDesktopPath)

{

LPITEMIDLIST ppidl = NULL;

if (SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &ppidl) == S_OK)

{

BOOLflag =   SHGetPathFromIDList(ppidl, pszDesktopPath);

CoTaskMemFree(ppidl);

return flag;

}

return FALSE;

}    

//得到快速啟動欄的路徑

BOOL GetIEQuickLaunchPath(char *pszIEQueickLaunchPath)

{    

LPITEMIDLIST ppidl;                   

if (SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &ppidl) == S_OK)

{

BOOLflag =   SHGetPathFromIDList(ppidl, pszIEQueickLaunchPath);

strcat(pszIEQueickLaunchPath, "\\Microsoft\\Internet Explorer\\Quick Launch");

CoTaskMemFree(ppidl);

return flag;

}

return FALSE;

}

//得到開始->程式組的路徑

BOOL GetProgramsPath(char *pszProgramsPath)

{

LPITEMIDLIST ppidl;

if (SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &ppidl) == S_OK)

{

BOOLflag = SHGetPathFromIDList(ppidl, pszProgramsPath);

CoTaskMemFree(ppidl);

return flag;

}

return FALSE;

}

/*

函式功能:對指定檔案在指定的目錄下建立其快捷方式

函式引數:

lpszFileName    指定檔案,為NULL表示當前程序的EXE檔案。

lpszLnkFileDir  指定目錄,不能為NULL

lpszLnkFileName 快捷方式名稱,為NULL表示EXE檔名。

wHotkey         0表示不設定快捷鍵

pszDescription  備註

iShowCmd        執行方式,預設為常規視窗

*/

BOOL CreateFileShortcut(LPCSTRlpszFileName, LPCSTRlpszLnkFileDir, LPCSTRlpszLnkFileName,       LPCSTRlpszWorkDir, WORDwHotkey, LPCTSTRlpszDescription, int iShowCmd = SW_SHOWNORMAL)

{

if (lpszLnkFileDir == NULL)

return FALSE;

HRESULThr;

IShellLink*pLink //IShellLink物件指標

IPersistFile *ppf; //IPersisFil物件指標

//建立IShellLink物件

hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink);

if (FAILED(hr))

return FALSE;

//IShellLink物件中獲取IPersistFile介面

hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);

if (FAILED(hr))

{

pLink->Release();

return FALSE;

}

//目標

if (lpszFileName == NULL)

pLink->SetPath(_pgmptr);

else

pLink->SetPath(lpszFileName);

//工作目錄

if (lpszWorkDir != NULL)

pLink->SetPath(lpszWorkDir);

//快捷鍵

if (wHotkey != 0)

pLink->SetHotkey(wHotkey);

//備註

if (lpszDescription != NULL)

pLink->SetDescription(lpszDescription);

//顯示方式

pLink->SetShowCmd(iShowCmd);

//快捷方式的路徑 + 名稱

char szBuffer[MAX_PATH];

if (lpszLnkFileName != NULL) //指定了快捷方式的名稱

sprintf(szBuffer, "%s\\%s", lpszLnkFileDir, lpszLnkFileName);

else  

{

//沒有指定名稱,就從取指定檔案的檔名作為快捷方式名稱。

char *pstr;

if (lpszFileName != NULL)

pstr = strrchr(lpszFileName, '\\');

else

pstr = strrchr(_pgmptr, '\\');

if (pstr == NULL)

{    

ppf->Release();

pLink->Release();

return FALSE;

}

//注意字尾名要從.exe改為.lnk

sprintf(szBuffer, "%s\\%s", lpszLnkFileDir, pstr);

int nLen = strlen(szBuffer);

szBuffer[nLen - 3] = 'l';

szBuffer[nLen - 2] = 'n';

szBuffer[nLen - 1] = 'k';

}

//儲存快捷方式到指定目錄下

WCHARwsz[MAX_PATH];  //定義Unicode字串

MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, wsz, MAX_PATH);

hr = ppf->Save(wsz, TRUE);

ppf->Release();

pLink->Release();

return SUCCEEDED(hr);

}

呼叫如下例:

int main()

{

char  szPath[MAX_PATH];

CoInitialize(NULL);

GetDesktopPath(szPath);

if (CreateFileShortcut(NULL, szPath, NULL, NULL, MAKEWORD(VK_F12, HOTKEYF_CONTROL), "That is a test"))

printf("建立成功\n");

CoUninitialize();

return 0;

}

標頭檔案及引用庫:

#include <stdio.h>

#include <windows.h>

#include <shlobj.h>

#pragma comment(lib, "shell32.lib")

效果如圖: