VC++ 创建桌面开始菜单快捷方式(附源码)

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++ 创建桌面开始菜单快捷方式(附源码)相关的知识,希望对你有一定的参考价值。

       很多公司的软件安装包不再使用InstallShied、InnoSetup等打包工具,他们自己编写代码去制作安装包,这样就能灵活地控制打包的流程、实现酷炫的UI界面。自制安装包的一个重要的一项就是创建桌面和开始菜单的快捷方式,这其中可能会产生一些bug,我们都遇到过,在此将这块的内容分享给大家。

 1、创建快捷方式

       创建快捷方式的代码是通用的,不管是创建桌面快捷方式,还是创建开始菜单快捷方式,都要调用下面封装的接口CreateFileShortcut:(该接口中主要使用前两个参数lpszTargetFilePath和lpszLnkPath,后面几个参数基本不用的)

/**
* 创建快捷方式
*
* @param lpszTargetFilePath 指定快捷方式指向的实际文件路径
* @param lpszLnkPath 快捷方式文件本身的完整路径
* @param wHotkey 为0表示不设置快捷键 
* @param lpszDescription 备注
* @param iShowCmd 显示方式
* @return  TRUE:成功,FALSE:失败
*/
BOOL CreateFileShortcut( LPCTSTR lpszTargetFilePath, LPCTSTR lpszLnkPath, WORD wHotkey, 
	LPCTSTR lpszDescription, int iShowCmd )
    
    if ( lpszTargetFilePath  == NULL || lpszLnkPath == NULL ) 
	
        return FALSE;
	

    HRESULT hr;    
    IShellLink   *pLink;  // IShellLink对象指针    
    IPersistFile *ppf;    // IPersisFil对象指针 

    //::CoInitialize( NULL );
    
    // 创建IShellLink对象    
    hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink );    
	if (  FAILED( hr ) )  
	
		//::CoUninitialize()
		return FALSE;
	
    
    // 从IShellLink对象中获取IPersistFile接口    
    hr = pLink->QueryInterface( IID_IPersistFile, (void**)&ppf );    
    if ( FAILED( hr ) )        
            
        pLink->Release();  
		//::CoUninitialize()
        return FALSE;        
        
    
    // 快捷方式指向的实际文件路径    
    if ( lpszTargetFilePath != NULL )
	
		CString strWorkDirectry = lpszTargetFilePath;
		strWorkDirectry = strWorkDirectry.Left( strWorkDirectry.ReverseFind( _T('\\\\') ) );

        pLink->SetPath( lpszTargetFilePath );
		pLink->SetWorkingDirectory( strWorkDirectry );

		// 解决快捷图标不刷新、更改图标时找不到文件的问题
		// 快捷方式文件的图标就是其指向的exe文件的图标
		pLink->SetIconLocation( lpszTargetFilePath, 0 ); 

		IShellLinkDataList *pShellLinkDataList = NULL;
		hr = pLink->QueryInterface( IID_IShellLinkDataList, (void**)&pShellLinkDataList );
		if ( FAILED(hr) )
		
			ppf->Release();
			pLink->Release();
			return FALSE;
		

		// 避免64系统中图标路径被解析成环境变量,导致快捷方式图标异常
		// 这个地方的代码是用API Monitor工具探测互联网大厂软件的函数调用记录添加上来的
		DWORD dwFlags = SLDF_DEFAULT;
		pShellLinkDataList->GetFlags( &dwFlags );
		if ( (dwFlags & SLDF_HAS_EXP_ICON_SZ) == SLDF_HAS_EXP_ICON_SZ )
		
			pShellLinkDataList->SetFlags( SLDF_DEFAULT );
			pShellLinkDataList->RemoveDataBlock( EXP_SZ_ICON_SIG );
		

		pShellLinkDataList->Release();
       
    
    // 设置快捷键    
    if ( wHotkey != 0 )
      
        pLink->SetHotkey( wHotkey );
    
    
    // 设置备注    
    if ( lpszDescription != NULL )
    
        pLink->SetDescription( lpszDescription );
    
    
    // 显示方式    
    pLink->SetShowCmd( iShowCmd );    
    
    // 保存快捷方式到指定目录下    
    // 要将路径字符串转化成宽字节字符串,COM接口ppf->Save要传入宽字符
	BOOL bUnicode = FALSE;
	WCHAR* pwTemp = NULL;
#ifdef _UNICODE
	pwTemp = (LPTSTR)lpszLnkPath;
	bUnicode = TRUE;
#else
	int nLen = MultiByteToWideChar( CP_ACP, 0, lpszLnkPath, -1, NULL, 0 );
	pwTemp = new WCHAR[nLen+1];
	memset( pwTemp, 0, (nLen+1)*sizeof(WCHAR) );
	MultiByteToWideChar( CP_ACP, 0, lpszLnkPath, -1, pwTemp, nLen+1, NULL, NULL );
#endif
    
    hr = ppf->Save( pwTemp, TRUE ); 

    ppf->Release();    
    pLink->Release(); 

	if ( !bUnicode && pwTemp != NULL )
	
		delete []pwTemp;
		pwTemp = NULL;
	

	//::CoUninitialize();

    return SUCCEEDED( hr );    

2、创建桌面快捷方式

        下面是在公共桌面中创建快捷方式:

// 得到公共用户桌面
BOOL GetPublicUserDesktopPath( TCHAR *pszDesktopPath )

	LPITEMIDLIST  ppidl = NULL;  
	if ( SHGetSpecialFolderLocation( NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &ppidl ) == S_OK )
	
		BOOL flag =  SHGetPathFromIDList( ppidl, pszDesktopPath );

		CoTaskMemFree( ppidl );
		return flag;
	

	return FALSE;


// 在公共用户桌面上创建快捷方式
void CreateDesktopShortCut()

	::CoInitialize( NULL );

	TCHAR achDesktopDir[MAX_PATH] =  0 ;    
	BOOL bRet = GetPublicUserDesktopPath( achDesktopDir );
	if ( !bRet )
	
		::CoUninitialize();
		return;
	

	CString strTargetExePath;  // 快捷方式指向的exe路径
	CString strLnkPath;        // 快捷方式文件本省的路径
	
	// ... // 路径获取部分省略
	
	CreateFileShortcut( strTargetExePath, strLnkPath, 0, NULL );

	::CoUninitialize(); 

3、创建开始菜单快捷方式

// 得到 开始->程序组 的路径
BOOL CProcessLogic::GetProgramsPath( TCHAR *pszProgramsPath )

	LPITEMIDLIST  ppidl;
	if ( SHGetSpecialFolderLocation( NULL, CSIDL_COMMON_PROGRAMS, &ppidl ) == S_OK )    
	        
		BOOL flag = SHGetPathFromIDList( ppidl, pszProgramsPath );   

		CoTaskMemFree( ppidl );        
		return flag;
	 

	return FALSE;    


void CreateStartMenuShortCut()

	::CoInitialize( NULL );

	TCHAR achProgramsDir[MAX_PATH] =  0 ;    
	BOOL bRet = GetProgramsPath( achProgramsDir );
	if ( !bRet )
	
		::CoUninitialize();
		return;
	

	// 创建文件夹:C:\\Documents and Settings\\All Users\\「开始」菜单\\程序1\\
	CString strTLLnkDir = _T("程序1"); 
	CreateDirectory( strTLLnkDir, NULL ); // 创建程序1文件夹

	// 创建 程序1\\程序1.lnk
	CString strTargetPath; // 快捷方式指向的exe路径
	CString strLnkPath;// 快捷方式文件本省的路径
	
	// ... // 路径获取部分省略
	
	CreateFileShortcut( strTargetPath, strLnkPath, 0, NULL );
	
	::CoUninitialize();

以上是关于VC++ 创建桌面开始菜单快捷方式(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

win10怎么把开始菜单中程序图标设置桌面快捷方式

[转]NSIS 制作安装包无法创建桌面快捷方式或无法删除开始菜单项

Delphi -- 创建 桌面发送到...快速启动栏开始菜单程序菜单右键菜 单

电脑装软件无法创建快捷方式,开始菜单里也只有文件夹没有软件

RStudio在桌面找不到快捷方式怎么办

VS2013安装完之后,桌面没快捷方式,原文件夹在哪里找到打开的程序?