通过手工操作建立这些菜单项或快捷方式并不复杂,在一般Windows使用手册中都有介绍,相信大家都很熟悉,在此不再赘述。笔者在有关资料的基础上,通过实践摸索,找到了在应用程序中完成上述工作的方法。这正是开发安装程序所必需的。
  Windows的快捷方式实际上是一个带有扩展名LNK的数据文件,其中包含有用于访问Windows某一对象(即在资源管理器中所能浏览的所有对象,包括文件,文件夹,驱动器及打印机等)的有关信息,如目标对象的路径和名称,工作目录,要传递的命令行参数,运行时的初始显示状态,图标及其快捷键等。通过在快捷方式上单击鼠标右键并在弹出菜单中选择“属性”可以观察该快捷方式的这些性质。
  快捷方式的数据文件如果存放在C:/Windows/Desktop子目录下,这个快捷方式就会显示在桌面上,而如果存放在C:/Windows/”Start Menu”/Programs子目录下,这个快捷方式就会作为“开始”菜单的一个菜单项出现。而桌面上的文件夹和“开始”菜单的菜单组则是上述两个子目录下的子目录的表现。
  Windows外壳(Shell)的快捷方式是以OLE技术的组件对象模型COM(Component ObjectModal)为基础而设计的。利用COM模型,一个应用程序可以调用另一应用程序的某些功能。这方面的技术细节请参阅有关文献。
  创建Windows的快捷方式比较容易。首先利用OLE通过调用CoCreateInstance()函数建立一个IID_IShellLink实例,并同时得到其接口指针。利用这个接口指针可以对其各项属性进行设置。为了使这些信息以快捷方式的数据文件(*.lnk)格式保存起来,还需要从IID_IShellLink对象取得其IID_IPersistFile接口指针,以便于调用其成员函数Save()保存前面设置的信息。
  至于如何删除快捷方式以及创建和删除文件夹,则只需要简单地调用文件操作函数SHFileOperation()就可以了。另外应该注意,在完成上述操作之后,都要调用SHChangeNotify()函数通知Windows外壳有关变化以使之及时更新其显示状态。
  该示例程序为一个基于对话框的应用程序,两个圆形按钮用于设置要创建/删除的文件夹或快捷方式的位置,下面的四个按钮则用于执行不同的操作。另外,该程序还需要一个简单的对话框,用于输入要创建的文件夹或快捷方式的名称。

// SortCut.cpp :
BOOL CSortCutApp::InitInstance()
{
    ......
    CoInitialize (NULL);
    CSortCutDlg dlg;
    m_pMainWnd = &dlg;
    ......
    CoUninitialize ();
    return FALSE;
}
// SortCutDlg.cpp :
#include "stdafx.h"
#include "SortCut.h"
#include "SortCutDlg.h"

#include "NameDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//起始文件夹的PIDL
int nBeginAt=CSIDL_DESKTOPDIRECTORY;
......

//浏览文件夹
BOOL BrowseForFolder(
LPITEMIDLIST pidlRoot,//浏览开始处的PIDL
LPITEMIDLIST *ppidlDestination,
//浏览结束时所选择的PIDL
LPCSTR lpszTitle)//浏览对话框中的提示文字
{
    BROWSEINFO BrInfo ;
    ZeroMemory( &BrInfo, sizeof(BrInfo)) ;
    BrInfo.hwndOwner = HWND_DESKTOP ;
    BrInfo.pidlRoot = pidlRoot ;
    BrInfo.lpszTitle = lpszTitle ;
   
    //浏览文件夹
    *ppidlDestination= SHBrowseForFolder(&BrInfo);

//用户选择了取消按钮
    if(NULL == *ppidlDestination) return FALSE ;

return TRUE ;
}
//取得快捷方式的目标应用程序名
SelectMenuItem( LPSTR szFileName)
{
    OPENFILENAME ofn ;
    static CHAR szFilter[] = "Programs/0*.exe/0" ;
    ZeroMemory(&ofn, sizeof( OPENFILENAME)) ;
    ofn.lStructSize = sizeof( OPENFILENAME) ;
    ofn.hwndOwner = HWND_DESKTOP;
    ofn.lpstrFilter = szFilter ;
    ofn.nFilterIndex = 0 ;
    ofn.nMaxFile = MAX_PATH ;
    ofn.lpstrTitle = "请选择目标应用程序:" ;
    ofn.lpstrFile = szFileName ;
    ofn.Flags = OFN_FILEMUSTEXIST |
    OFN_PATHMUSTEXIST | OFN_EXPLORER ;
   
    //文件浏览
    if(!GetOpenFileName( &ofn))//选择了取消按钮
       return FALSE ;
   
    return TRUE ;
}

//取得要创建的快捷方式的名字
BOOL GetShortcutCrt(LPSTR szPath)
{
    LPITEMIDLIST pidlBeginAt, pidlDestination ;

// 取得开始菜单或桌面的PIDL
    SHGetSpecialFolderLocation( HWND_DESKTOP,
    nBeginAt, &pidlBeginAt) ;

// 取得要创建的快捷方式所在的位置
    if( !BrowseForFolder(pidlBeginAt,&pidlDestination,"请选择快捷方式所在的位置:"))
       return FALSE ;

// 把PIDL转换为路径名
    SHGetPathFromIDList( pidlDestination, szPath) ;

// 取得快捷方式名称
    CNameDlg name_dlg;
    if(name_dlg.DoModal() == IDCANCEL)
       return FALSE ;

//把快捷方式名和扩展名.LNK添加到路径名后
    //形成完整的快捷方式数据文件名
    wsprintf(szPath+lstrlen(szPath),"//%s.lnk",
    name_dlg.m_strName) ;
    return TRUE ;
}

//创建快捷方式
BOOL CreateLink (
LPSTR szPath,//快捷方式的目标应用程序名
LPSTR szLink)//快捷方式的数据文件名(*.lnk)
{
    HRESULT hres ;
    IShellLink * psl ;
    IPersistFile* ppf ;
    WORD wsz[ MAX_PATH] ;

//创建一个IShellLink实例
    hres = CoCreateInstance( CLSID_ShellLink, NULL,    CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
    if( FAILED( hres))    return FALSE ;

//设置目标应用程序
    psl -> SetPath( szPath) ;

//设置快捷键(此处设为Shift+Ctrl+'R')
    psl -> SetHotkey( MAKEWORD( 'R',
    HOTKEYF_SHIFT |HOTKEYF_CONTROL)) ;

//从IShellLink获取其IPersistFile接口
    //用于保存快捷方式的数据文件 (*.lnk)

hres = psl -> QueryInterface( IID_IPersistFile,
    (void**)&ppf) ;
    if( FAILED( hres))     return FALSE ;

// 确保数据文件名为ANSI格式
    MultiByteToWideChar( CP_ACP, 0, szLink, -1,
    wsz, MAX_PATH) ;

//调用IPersist:Save
    //保存快捷方式的数据文件 (*.lnk)
    hres = ppf -> Save( wsz, STGM_READWRITE) ;

//释放IPersistFile和IShellLink接口
    ppf -> Release( ) ;
    psl -> Release( ) ;
    return TRUE;
}

//删除文件夹
BOOL DeleteFolder( LPSTR pszFolder)
{
    SHFILEOPSTRUCT fos ;
    ZeroMemory( &fos, sizeof( fos)) ;
    fos.hwnd = HWND_DESKTOP;
    fos.wFunc = FO_DELETE ;
    fos.fFlags = FOF_SILENT | FOF_ALLOWUNDO ;
    fos.pFrom = pszFolder ;
   
    // 删除文件夹及其内容
    if( 0 != SHFileOperation( &fos)) return FALSE ;
}

// 获取当前路径
TCHAR szPath [MAX_PATH] = _T("") ;
GetModuleFileName( NULL, szPath, MAX_PATH ) ;
PathRemoveFileSpec(szPath) ;
m_strCurPath = szPath ;

TCHAR   szDirFile[MAX_PATH]= _T("") ;
TCHAR   szDirDesktop[MAX_PATH]= _T("") ;  
SHGetSpecialFolderPath(NULL,szDirFile,CSIDL_PERSONAL,false);   //得到我的文件的路径
m_SpecialFolderPath=szDirFile;
m_DirFlag=GetFileAttributes(m_SpecialFolderPath+"//MTDS_IMAGES");//文件夹是否存在
if(m_DirFlag ==0xFFFFFFFF)//文件夹不存在
CreateDirectory(m_SpecialFolderPath+"//MTDS_IMAGES",NULL);

//创建快捷方式------少了个判断文件是否创建成功,判断创建实例是否成功
CString m_szDirDesktop;
WORD wsz[MAX_PATH];
SHGetSpecialFolderPath(NULL,szDirDesktop,CSIDL_DESKTOPDIRECTORY,false);//获得Desktop的目录
m_szDirDesktop=szDirDesktop;
IShellLink* psl ;
    IPersistFile* ppf;
//创建一个IShellLink实例
// if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL,CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl)));
CoCreateInstance(CLSID_ShellLink, NULL,CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
//设置目标应用程序
psl->SetPath(m_SpecialFolderPath+"//MTDS_IMAGES");
//从IShellLink获取其IPersistFile接口
//用于保存快捷方式的数据文件 (*.lnk)
// if(SUCCEEDED(psl -> QueryInterface( IID_IPersistFile,(void**)&ppf) ));
psl -> QueryInterface( IID_IPersistFile,(void**)&ppf);
// 确保数据文件名为ANSI格式
MultiByteToWideChar( CP_ACP, 0, m_szDirDesktop+"//MTDS_IMAGE.lnk", -1,wsz, MAX_PATH);
//调用IPersist:Save
//保存快捷方式的数据文件 (*.lnk)
ppf -> Save( wsz, STGM_READWRITE) ;
ppf -> Release( ) ;
psl -> Release( ) ;

m_bDefaultSkin = !PathFileExists( GetFilePath(FILE_SKIN)) ;
}

使用API函数SHGetSpecialFolderLocation。shlobj.h里有SHGetSpecialFolderLocation的原型声明。这个函数可以帮我们找到Windows的桌面目录、启动目录、我的文档目录等。
SHGetSpecialFolder需要三个参数。 第一个参数是HWND,它指定了"所有者窗口":在调用这个函数时可能出现的对话框或消息框。第二个参数是一个整数id,决定哪个目录是待查找目录,它的取值可能是:
CSIDL_BITBUCKET 回收站
CSIDL_CONTROLS 控制面板
CSIDL_DESKTOP Windows 桌面Desktop
CSIDL_DESKTOPDIRECTORY Desktop的目录
CSIDL_DRIVES 我的电脑
CSIDL_FONTS 字体目录
CSIDL_NETHOOD 网上邻居
CSIDL_NETWORK 网上邻居虚拟目录
CSIDL_PERSONAL 我的文档
CSIDL_PRINTERS 打印机
CSIDL_PROGRAMS 程序组
CSIDL_RECENT 最近打开的文档
CSIDL_SENDTO “发送到”菜单项
CSIDL_STARTMENU 任务条启动菜单项
CSIDL_STARTUP 启动目录
CSIDL_TEMPLATES 文档模板

Following sample code creates a shortcut and sets the shortcut's icon to an icon contained in shell32.dll:
/*PARAMETERS
fname_to_create_link = (e.g.) "c://mytextfile.txt"
lnk_fname = (e.g.) "yourname.lnk"
*/

void CreateLinkThenChangeIcon(LPTSTR fname_to_create_link,
LPTSTR lnk_fname)
{
HRESULT hres;
IShellLink *psl = NULL;
IPersistFile *pPf = NULL;
WORD wsz[256];
TCHAR buf[256];
int id;
LPITEMIDLIST pidl;

hres = CoCreateInstance( CLSID_ShellLink,

NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
(LPVOID*)&psl);
if(FAILED(hres))
goto cleanup;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&pPf);
if(FAILED(hres))
goto cleanup;
hres = psl->SetPath(fname_to_create_link);
if(FAILED(hres))

goto cleanup;
//place the shortcut on the desktop
SHGetSpecialFolderLocation(hwnd, CSIDL_DESKTOP, >pidl);

SHGetPathFromIDList(pidl, buf);

lstrcat(buf,"//");
lstrcat(buf,lnk_fname);

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

hres = pPf->Save(wsz, TRUE);

if(FAILED(hres))

goto cleanup;

GetSystemDirectory(buf, 256);

lstrcat(buf,"//shell32.dll");

hres = psl->SetIconLocation(buf, 1);

if(FAILED(hres))

goto cleanup;

hres = psl->GetIconLocation(buf, 256, &id);

if(FAILED(hres))

goto cleanup;

pPf-&Save(wsz, TRUE);

cleanup:

if(pPf)

pPf->Release();

if(psl)

psl->Release();

}
It works!

//

1、快捷方式的实质
Windows的快捷方式实际上是一个带有扩展名LNK的数据文件,其中包含有用于访问Windows某一对象(即在资源管理器中所能浏览的所有对象,包括文件,文件夹,驱动器及打印机等)的有关信息,如目标对象的路径和名称,工作目录,要传递的命令行参数,运行时的初始显示状态,图标及其快捷键等。通过在快捷方式上单击鼠标右键并在弹出菜单中选择“属性”可以观察该快捷方式的这些性质。

2、编程思想

Windows外壳(Shell)的快捷方式是以OLE技术的组件对象模型COM(Component ObjectModal)为基础而设计的。利用COM模型,一个应用程序可以调用另一应用程序的某些功能。

Windows提供了一个COM接口IshellLink,它能够帮助我们创建、修改、删除快捷方式。要使用COM接口提供的功能,必须首先调用CoCreateInstance()函数建立一个IID_IShellLink实例,并同时得到其接口指针。利用这个接口指针可以对其各项属性进行设置。创建实例后,通过调用SetPath()方法设置快捷方式指向的源程序的路径,快捷方式的存储位置应该是:“程序”的位置+程序组名称+快捷方式名称+扩展名.lnk;通过SetDescription()方法设置快捷方式的描述,当然你还可以调用比如SetHotKey()等方法设置热键、显示的图标(默认为实际程序的图标)等。为了使这些信息以快捷方式的数据文件(*.lnk)格式保存起来,还需要从IID_IShellLink对象取得其IID_IPersistFile接口指针,以便于调用其成员函数Save()保存前面设置的信息。

需要注意的是:快捷方式应该使用Unicode存储,所以必须调用wcscpy()函数将其转换。
//Create
BOOL CMainDlg::CreateLink(LPCSTR pszShortcutFile,/*源*/
    LPCSTR pszLink, /*lnk名*/
    LPCSTR pszDesc/*描述*/)
{
HRESULT hres;
CComPtr<IShellLink> psl;
CComPtr<IPersistFile> ppf;

hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
   IID_IShellLink, (void **)&psl);
if (FAILED(hres))
{
   return FALSE;
}

hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
if (FAILED(hres))
{
   return FALSE;
}

WORD wsz [MAX_PATH];

hres = psl->SetPath (pszShortcutFile);
if (FAILED(hres))
{
   return FALSE;
}

hres = psl->SetDescription (pszDesc);
if (FAILED(hres))
{
   return FALSE;
}
#ifndef _UNICODE
MultiByteToWideChar (CP_ACP, 0, pszLink, -1, wsz, MAX_PATH);
#else
wcscpy(wsz,szLink);
#endif
hres = ppf->Save (wsz, TRUE);
if (FAILED(hres))
{
   return FALSE;
}

return TRUE;
}

string CMainDlg::GetShortcutTarget(LPCSTR pszLinkFileName)
{
HRESULT hres;

CString Link, Temp = pszLinkFileName;
Temp.MakeLower();
if (Temp.Find(".lnk")==-1)           //Check if the name ends with .lnk
{
   Link = pszLinkFileName;
   Link +=_T(".lnk");   //if not, append it
}
else
{
   Link = pszLinkFileName;
}

string Info;
CComPtr<IShellLink> psl;

hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
   IID_IShellLink, (LPVOID*) &psl);

if (SUCCEEDED(hres))
{
   CComPtr<IPersistFile> ppf;
   hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf);
   if (SUCCEEDED(hres))
   {
    WORD wsz[MAX_PATH];
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Link, -1, wsz,MAX_PATH);
    hres = ppf->Load(wsz, 0);
   
    if (SUCCEEDED(hres))
    {
        hres = psl->Resolve(NULL,SLR_ANY_MATCH | SLR_NO_UI);
        if(SUCCEEDED(hres))
        {
           psl->GetPath(Temp.GetBuffer(1024), 1024, NULL,SLGP_UNCPRIORITY);
      
            Temp.ReleaseBuffer();
           Info = Temp;
          return Info;
        }

}
   }
}
return NULL;

如何在程序中创建快捷方式相关推荐

  1. 如何在程序中创建快捷方式?

    这里给出一个创建快捷方式的例子,是使用IShellLink和IPersistFile两个COM接口实现的. 例子代码如下: CFileDialog openDlg(TRUE, NULL, NULL, ...

  2. 在Win32程序中创建OpenGL渲染环境

    在Win32程序中创建OpenGL渲染环境 创建opengl渲染环境步骤: 选定像素格式 //WinMain()HDC dc = GetDC(hwnd);PIXELFORMATDESCRIPTOR p ...

  3. 如何使用Angular Router在Angular 9应用程序中创建导航

    This article will demonstrate the proper way to create page navigation leveraging routing features p ...

  4. 如何在桌面或者开始菜单中创建快捷方式

    //在桌面或者开始菜单中创建快捷方式 //pazSrcPath:源文件路径 //bDesktop:标志位,用来判断是否在桌面上创建快捷方式,真,在桌面上创建,否则在开始菜单中创建 bool creat ...

  5. Java实现pdf转tex_使用Free Spire.PDF在Java程序中创建和转换PDF文件

    在这篇文章中,我将举例说明如何创建一个包含标题,段落,图像,编号列表和表格的简单的PDF文件,以及如何使用Free Spire.PDF将PDF转换为其他文件格式. 概述 Free Spire.PDF ...

  6. 在Java程序中创建和转换PDF文件

    点击上方关注 "终端研发部" 设为"星标",和你一起掌握更多数据库知识 作者: Codingqi123 来源: jianshu.com/p/db15232987 ...

  7. 微信小程序怎么新建php文件,微信小程序中创建小程序页面的步骤介绍(图文)...

    本篇文章给大家带来的内容是关于微信小程序之创建小程序页面的步骤介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 创建一个简单的页面,创建小程序页面的具体几个步骤: 1. 在page ...

  8. java控件数组_在C# WinForm程序中创建控件数组及相应的事件处理

    控件数组是VB提供的一个优秀的设计解决方案,它能很方便快捷的处理大批同类控件的响应和时间处理,但不知为什么在C#中这个优秀特性没有传承下来,甚为可惜,本文将要探讨就是如何在C# WinForm程序实现 ...

  9. ipad原始邮箱服务器端口,如何在iPhone/iPad/iPod touch邮件应用程序中创建帐户(默认POP3)?...

    下面向大家介绍如何使用iPhone/iPad/iPod touch上的邮件应用程序Mail创建 yeah 邮箱帐户,这里以iPod touch为例(iPhone/iPad中除了界面略有区别外,操作基本 ...

最新文章

  1. SAP MM已经转成PO的采购申请Item依旧可以被删除?
  2. SpringtMVC中配置 mvc:annotation-driven/ 与 mvc:default-servlet-handler/ 的作用
  3. 64位环境0和NULL的区别
  4. the params of sys aud mod req msgs from TV
  5. vue小demo易错点总结
  6. Linux下安装amsn
  7. semver语义化版本号
  8. python爬虫设计思路_python网络爬虫(9)构建基础爬虫思路
  9. python可能导致异常的代码_Python程序可能导致文件系统错误?
  10. 游竹林寺不得,谈封山收费
  11. iwconfig 安装_嵌入式wifi iwconfig编译
  12. ai交互剧本_AI可以制作音乐,剧本和诗歌。 电影呢?
  13. 【JavaScript】(二)俄罗斯方块
  14. 阿里IOT用AMQP在服务端订阅消息,踩坑
  15. ThinkPad E450(c)添加或者更换内存条的一些问题
  16. python爬取笔趣阁
  17. 用python对excel进行打印操作
  18. 怎么样导包测试JavaWeb代码?
  19. 如何通过cmd怎么打开计算机管理
  20. 软考高级系统架构设计师系列论文七:论基于构件的软件开发

热门文章

  1. 微软计划再裁11000人!距上次裁员仅3个月,CEO:未来两年都是苦日子
  2. visual studio 2017如何打开 *.sdf 数据库文件 (笔记)
  3. 求助高手:惠普HP NC523FSP 网卡在Windows10 64位系统下的驱动程序
  4. 2018ACM校赛 D 白狼(暴力枚举)
  5. 电脑主机不停重复启动怎么解决
  6. 新版markdown功能发布!支持github flavored markdown!
  7. 《我不是药神》明星见面会
  8. 自定义半屏弹窗Dialog或Activity背景半透明
  9. html设置文本边框为透明,透明框中的文本
  10. Adobe_Creative_Cloud_Cleaner_Tool强制卸载