VC 为程序创建快捷方式的详细讲解

有时候,为了方便用户使用我们编写的程序,需要在桌面,快速启动或程序组中创建程序的快捷方式。下面就介绍在VC下如何为程序创建快捷方式。

一.得到桌面,快速启动或程序组的路径

这里介绍二个win32 API函数来完成这个任务。


第一个函数 获得系统特殊路径


1 HRESULT SHGetSpecialFolderLocation(
2  
3 HWND hwndOwner,  int nFolder, PIDLIST_ABSOLUTE *ppidl
4  
5 );

第一个参数表示所有者窗口句柄,一般传入NULL就可以了。


第二个参数要示是一个整数id,决定哪个目录是待查找目录,它的取值可能是

01   CSIDL_BITBUCKET            回收站
02 CSIDL_CONTROLS            控制面板
03 CSIDL_DESKTOP              Windows桌面desktop;
04 CSIDL_DESKTOPDIRECTORY   desktop的目录;
05 CSIDL_DRIVES                我的电脑
06 CSIDL_FONTS                 字体目录
07 CSIDL_NETHOOD             网上邻居
08 CSIDL_NETWORK             网上邻居virtual folder
09 CSIDL_PERSONAL             我的文档
10 CSIDL_PRINTERS              打印机
11 CSIDL_PROGRAMS             程序组
12 CSIDL_RECENT                最近打开文档
13 CSIDL_SENDTO                发送到菜单项
14 CSIDL_STARTMENU            快速启动菜单
15  CSIDL_STARTUP               启动目录
16 CSIDL_TEMPLATES            临时文档

第三个参数表示一个条目标识符列表指针,可以传入一个LPITEMIDLIST类型变量,再从这个变量中得到表示路径的字符串。使用完后,要用void CoTaskMemFree(void * pv)来释放资源。

第二个函数 将一个条目标识符列表转换为一个文件系统路径

1 BOOL SHGetPathFromIDList(
2  
3 PCIDLIST_ABSOLUTE pidl,  LPTSTR pszPath
4  
5 );

第一个参数 pidl就是用第一个函数所得到的条目标识符列表指针。


第二个参数pszPath返回表示路径的字符串。

这二个函数的头文件均为<shlobj.h>并要引入shell32.lib。


下面给出了一个程序,用来列举你电脑上一些系统特殊路径:

01 #include <stdio.h>
02 #include <windows.h>
03 #include <shlobj.h>
04 #pragma comment(lib, "shell32.lib")
05  
06 int main()
07 {
08     const int ENDNUMBER = -1;//哨兵,在遍历数组时遇到此数表示已经到达了数组的最后。
09     //设置这个后,你可以在nFolders数组中任意添加删除数据而不用在遍历数组时考虑其中有多少个数据。
10  
11     CoInitialize(NULL);
12     int nFolders[] = {
13         CSIDL_BITBUCKET, CSIDL_CONTROLS, CSIDL_DESKTOP, CSIDL_DESKTOPDIRECTORY,
14         CSIDL_DRIVES, CSIDL_FONTS, CSIDL_NETHOOD, CSIDL_NETWORK, CSIDL_PERSONAL,
15         CSIDL_PRINTERS, CSIDL_PROGRAMS, CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU,
16         CSIDL_STARTUP, CSIDL_TEMPLATES, ENDNUMBER
17     };
18  
19     HRESULT       hr;
20     LPITEMIDLIST  ppidl;
21     char          szPath[MAX_PATH];
22  
23     int i = 0; 
24     while (nFolders[i] != ENDNUMBER)
25     {
26         hr = SHGetSpecialFolderLocation(NULL, nFolders[i], &ppidl);
27         if (hr != S_OK)
28         {
29             printf("SHGetSpecialFolderLocation Error\n");
30         }
31         else
32         {
33             if (SHGetPathFromIDList(ppidl, szPath))
34                 printf("%s\n", szPath);
35             else
36                 printf("SHGetPathFromIDList Error\n");
37             CoTaskMemFree(ppidl);
38         }
39  
40         i++;
41     }
42     CoUninitialize();
43     return 0;
44 }

由于系统的差异,有时会输出“SHGetPathFromIDList Error”,在我电脑上就输出了5次。有了这个例子,相信不难写出得到桌面桌面(CSIDL_DESKTOP),快速启动(CSIDL_APPDATA),程序组(CSIDL_PROGRAMS)的路径函数。


不过要稍稍注意下快捷启动,要再加上"\\Microsoft\\Internet Explorer\\Quick Launch"。

二.创建快捷方式文件

完成第一步的任务后接下来的问题是如何创建快捷方式文件即.lnk文件。首先要了解快捷方式文件要设置什么,然后了了解怎样设置。


2.1快捷方式文件有哪些要设置的内容

下面给出了Spy++和Kmplayer Plus二个程序的快捷方式。


快捷方式必须设置目标,起始位置,快捷键,备注都可以选择性的设置,运行方式一般取默认值----常规窗口。

VC 为程序创建快捷方式的详细讲解_第1张图片



2.2如何设置快捷方式文件的内容

这要用到二个COM接口IShellLink和IPersistFile。由于篇幅问题,这里只讲解二个接口的部分函数。


IShellLink的部分函数

1 HRESULT SetPath(LPCTSTR pszFile);             设置目标
2 HRESULT SetWorkingDirectory(LPCTSTR pszDir);  设置起始位置
3 HRESULT SetHotkey(WORD wHotkey);           设置快捷键
4 HRESULT SetShowCmd(int iShowCmd);           设置运行方式

有三种选择

1 SW_SHOWMAXIMIZED最大化
2 S0W_SHOWMINNOACTIVE最小化 <span>SW_SHOWNORMAL常规窗口</span>

HRESULT SetDescription(LPCTSTR pszName);      设置备注


要特别说下SetHotkey()中的参数WORD wHotkey。MSDN上对其的解释为:

1 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.
2  
3 HOTKEYF_ALT        ALT key
4  
5 HOTKEYF_CONTROL   CTRL key
6  
7 HOTKEYF_EXT        Extended key
8  
9 HOTKEYF_SHIFT      SHIFT key

意思就是对这个WORD值,低位上是virtual key code,高位上可以是ALT,CTRL等组合键。可以用MAKEWORD(low, high)来生成一个WORD,如Ctrl+F12可以用MAKEWORD(VK_F12, HOTKEYF_CONTROL)表示。

IPersistFile的部分函数

1 HRESULT Save(          保存快捷方式
2  
3   LPCOLESTR pszFileName, BOOL fRemember
4  
5 );

第一个参数是要保存文件的文件名,要求是绝对路径。

第二个参数涉及COM的持续性问题(注1),一般传入TRUE即可。



要创建COM对象可以用CoCreateInstance()函数(见注2)和QueryInterface()函数(见注3)。下面给出了创建的代码:

1 IShellLink     *pLink;   //IShellLink对象指针
2 IPersistFile    *ppf;      //IPersisFil对象指针

创建IShellLink实例

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

从IShellLink对象中获取IPersistFile接口

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

创建之后就可以对pLink设置目标,快捷键,备注等,设置完后再用ppf创建快捷方式文件就可以了。当然最后要记得释放资源,pLink->Release(); ppf->Release()。


三.已封装好的函数代码

下面给出封装好的函数代码,可以在程序中直接使用(在XP+VC6.0下测试过)。

001 //得到当前桌面路径
002 BOOL GetDesktopPath(char *pszDesktopPath)
003 {
004     LPITEMIDLIST  ppidl = NULL;
005      
006     if (SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &ppidl) == S_OK)
007     {
008         BOOL flag = SHGetPathFromIDList(ppidl, pszDesktopPath);
009         CoTaskMemFree(ppidl);
010         return flag;
011     }
012  
013     return FALSE;
014 }  
015 //得到快速启动栏的路径
016 BOOL GetIEQuickLaunchPath(char *pszIEQueickLaunchPath)
017 {  
018     LPITEMIDLIST  ppidl;           
019      
020     if (SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &ppidl) == S_OK)
021     {
022         BOOL flag = SHGetPathFromIDList(ppidl, pszIEQueickLaunchPath);
023         strcat(pszIEQueickLaunchPath, "\\Microsoft\\Internet Explorer\\Quick Launch");
024         CoTaskMemFree(ppidl);
025         return flag;
026     }
027  
028     return FALSE;
029 }
030 //得到 开始->程序组 的路径
031 BOOL GetProgramsPath(char *pszProgramsPath)
032 {
033     LPITEMIDLIST  ppidl;
034      
035     if (SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &ppidl) == S_OK)
036     {
037         BOOL flag = SHGetPathFromIDList(ppidl, pszProgramsPath);
038         CoTaskMemFree(ppidl);
039         return flag;
040     }
041  
042     return FALSE;
043 }
044 /*
045 函数功能:对指定文件在指定的目录下创建其快捷方式
046 函数参数:
047 lpszFileName    指定文件,为NULL表示当前进程的EXE文件。
048 lpszLnkFileDir  指定目录,不能为NULL。
049 lpszLnkFileName 快捷方式名称,为NULL表示EXE文件名。
050 wHotkey         为0表示不设置快捷键
051 pszDescription  备注
052 iShowCmd        运行方式,默认为常规窗口
053 */
054 BOOL CreateFileShortcut(LPCSTR lpszFileName, LPCSTR lpszLnkFileDir, LPCSTR lpszLnkFileName, LPCSTR lpszWorkDir, WORDwHotkey, LPCTSTR lpszDescription, int iShowCmd = SW_SHOWNORMAL)
055 {
056     if (lpszLnkFileDir == NULL)
057         return FALSE;
058  
059     HRESULT hr;
060     IShellLink     *pLink;  //IShellLink对象指针
061     IPersistFile   *ppf; //IPersisFil对象指针
062      
063     //创建IShellLink对象
064     hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink);
065     if (FAILED(hr))
066         return FALSE;
067      
068     //从IShellLink对象中获取IPersistFile接口
069     hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
070     if (FAILED(hr))
071     {
072         pLink->Release();
073         return FALSE;
074     }
075      
076     //目标
077     if (lpszFileName == NULL)
078         pLink->SetPath(_pgmptr);
079     else
080         pLink->SetPath(lpszFileName);
081      
082     //起始位置
083     if (lpszWorkDir != NULL)
084         pLink->SetWorkingDirectory(lpszWorkDir);
085      
086     //快捷键
087     if (wHotkey != 0)
088         pLink->SetHotkey(wHotkey);
089      
090     //备注
091     if (lpszDescription != NULL)
092         pLink->SetDescription(lpszDescription);
093      
094     //显示方式
095     pLink->SetShowCmd(iShowCmd);
096  
097  
098     //快捷方式的路径 + 名称
099     char szBuffer[MAX_PATH];
100     if (lpszLnkFileName != NULL) //指定了快捷方式的名称
101         sprintf(szBuffer, "%s\\%s", lpszLnkFileDir, lpszLnkFileName);
102     else  
103     {
104         //没有指定名称,就从取指定文件的文件名作为快捷方式名称。
105         char *pstr;
106         if (lpszFileName != NULL)
107             pstr = strrchr(lpszFileName, '\\');
108         else
109             pstr = strrchr(_pgmptr, '\\');
110  
111         if (pstr == NULL)

你可能感兴趣的:(com)