----摘抄-----
void CShortCutDlg::OnCreate() 
{
// TODO: Add your control notification handler code here
char m_strWinDir[512];
long rval;
HKEY hKey;
DWORD dwType; 
DWORD dwSize;
rval = RegOpenKeyEx(HKEY_CURRENT_USER,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
        NULL, KEY_QUERY_VALUE, &hKey);if(rval == ERROR_SUCCESS)
{
        dwSize = 512;
        rval = RegQueryValueEx(hKey, "Programs", 0, &dwType, (LPBYTE)m_strWinDir, &dwSize);
        rval = RegCloseKey(hKey);
        strcat(m_strWinDir, "\\VC编程技巧");
        CreateDirectory(m_strWinDir, NULL);
        strcat(m_strWinDir, "\\VC编程技巧.lnk");
        HRESULT hres; 
        IShellLink* psl; 
        // 取得指向IshellLink接口的指针 
        CoInitialize(NULL);
        hres = CoCreateInstance(CLSID_ShellLink, NULL, 
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); 
        if(SUCCEEDED(hres))
        { 
IPersistFile* ppf; 
// 设置快捷对象路径,并增加描述 
psl->SetPath("c:\\VCSkill\\VCSkill.exe"); 
psl->SetWorkingDirectory("c:\\VCSkill");
psl->SetDescription("VC编程技巧"); 
hres = psl->QueryInterface(IID_IPersistFile, 
(LPVOID *)&ppf); 
if(SUCCEEDED(hres))

WORD wsz[MAX_PATH]; 
// 字符串为ANSI格式
MultiByteToWideChar(CP_ACP, 0, m_strWinDir, -1,
wsz, MAX_PATH); 
// 保存链接
hres = ppf->Save(wsz, TRUE); 
ppf->Release(); 

psl->Release(); 
        }
}
else
{
        AfxMessageBox("创建程序组和快捷方式失败,请稍后自行创建!");
}
}

解决方案 »

  1.   

    快捷方式的实质:Windows的快捷方式实际上是一个带有扩展名LNK的数据文件,其中包含有用于访问Windows某一对象(即在资源管理器中所能浏览的所有对象,包括文件,文件夹,驱动器及打印机等)的有关信息,如目标对象的路径和名称,工作目录,要传递的命令行参数,运行时的初始显示状态,图标及其快捷键等。通过在快捷方式上单击鼠标右键并在弹出菜单中选择“属性”可以观察该快捷方式的这些性质。
    快捷方式的数据文件如果存放在C:\Windows\Desktop子目录下,这个快捷方式就会显示在桌面上,而如果存放在C:\Windows\”Start Menu”\Programs子目录下,这个快捷方式就会作为“开始”菜单的一个菜单项出现。而桌面上的文件夹和“开始”菜单的菜单组则是上述两个子目录下的子目录的表现。编程思想:Windows外壳(Shell)的快捷方式是以OLE技术的组件对象模型COM(Component Object Modal)为基础而设计的。利用COM模型,一个应用程序可以调用另一应用程序的某些功能。这方面的技术细节请参阅有关文献。
    在了解了上述基本原理后,创建Windows的快捷方式就比较容易了。首先利用OLE通过调用CoCreateInstance()函数建立一个IID_IShellLink实例,并同时得到其接口指针。利用这个接口指针可以对其各项属性进行设置。为了使这些信息以快捷方式的数据文件(*.lnk)格式保存起来,还需要从IID_IShellLink对象取得其IID_IPersistFile接口指针,以便于调用其成员函数Save()保存前面设置的信息。
    至于如何删除快捷方式以及创建和删除文件夹,则只需要简单地调用文件操作函数SHFileOperation()就可以了。
    另外应该注意,在完成上述操作之后,都要调用SHChangeNotify()函数通知Windows外壳有关变化以使之及时更新其显示状态。4 应用举例
    为了具体演示上述思想的使用方法,我们用MS VC++5.0编制了如下的示例程序(如下图)。该示例程序为一个基于对话框的应用程序,两个圆形按钮用于设置要创建/删除的文件夹或快捷方式的位置,下面的四个按钮则用于执行不同的操作。另外,该程序还需要一个简单的对话框,用于输入要创建的文件夹或快捷方式的名称。下面为建立该程序后需添加的代码(方框内部分):
    // 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) ;
        //调用IPersistFile::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 ;
        return TRUE;
    }
    //取得要删除的快捷方式
    BOOL GetShortcutDel (
            LPSTR lpszInitDir,//选择文件的开始目录
            LPSTR lpszShortcut)//快捷方式名
    {
        OPENFILENAME ofn ;
        char szFilter[] = "Shortcuts\0*.lnk\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 = lpszShortcut;
        ofn.lpstrInitialDir = lpszInitDir ;
        ofn.Flags = OFN_FILEMUSTEXIST | 
            OFN_PATHMUSTEXIST | OFN_EXPLORER |
            OFN_NODEREFERENCELINKS ;
        //文件浏览
        if(! GetOpenFileName( &ofn))//选择了取消按钮
            return FALSE ;
        return TRUE ;
    }
    //删除快捷方式的数据文件 (*.lnk)
    BOOL DeleteLink( LPSTR lpszShortcut)
    {
        SHFILEOPSTRUCT fos ;    ZeroMemory( &fos, sizeof(fos)) ;
        fos.hwnd = HWND_DESKTOP ;
        fos.wFunc = FO_DELETE ;
        fos.pFrom = lpszShortcut;
        fos.pTo = NULL ;
        fos.fFlags = FOF_SILENT | FOF_ALLOWUNDO ;
        //删除快捷方式(*.lnk)
        if( 0 != SHFileOperation( &fos))
            return FALSE ;
        return TRUE ;
    }
    // 通知shell有关变化
    void NotifyShell(LONG wEventId,//事件标志
                LPSTR szPath)//路径
    {    
        SHChangeNotify( wEventId,
                        SHCNF_FLUSH | SHCNF_PATH,
                        szPath,0);
        //取得szPath的父目录
        char* p;
        for( p=szPath+lstrlen(szPath)-1;
                *p != '\\'; 
                p--);
        *p='\0';
        SHChangeNotify(SHCNE_UPDATEDIR
                |SHCNE_INTERRUPT, 
                SHCNF_FLUSH | SHCNF_PATH,szPath,0);
    }
    ///////////////////////////////////////////////////
    // CSortCutDlg dialog
    CSortCutDlg::CSortCutDlg(CWnd* pParent /*=NULL*/)
        : CDialog(CSortCutDlg::IDD, pParent)
    {
        //{{AFX_DATA_INIT(CSortCutDlg)
        //把圆形按钮“桌面”设为选中状态
        m_nLocation = 0;
        ……
    }
    ……
    void CSortCutDlg::OnCreateGroup() 
    {
        LPITEMIDLIST pidlBeginAt, pidlDestination ;
        char szPath[ MAX_PATH] ;    // 取得开始菜单或桌面的PIDL
        SHGetSpecialFolderLocation( HWND_DESKTOP, 
                nBeginAt, &pidlBeginAt) ;
        // 取得新建文件夹的父文件夹
        if( !BrowseForFolder(pidlBeginAt , 
                &pidlDestination,
                "请选择新建文件夹/菜单组的位置:"))
            return ;
        // 把PIDL转换为路径名
        SHGetPathFromIDList( pidlDestination, szPath) ;
        //取得新建文件夹的名字
        CNameDlg name_dlg;
        if(name_dlg.DoModal() == IDCANCEL)
            return;
        //形成完整的新建文件夹名
        wsprintf(szPath+lstrlen(szPath),"\\%s",
                    name_dlg.m_strName);
        //创建文件夹(子目录)
        if( !CreateDirectory( szPath, NULL))
        {
            MessageBox( "创建文件夹失败!") ;
            return ;
        }
        // 通知shell有关变化
        NotifyShell( SHCNE_MKDIR|SHCNE_INTERRUPT,
                    szPath);
    }
    void CSortCutDlg::OnCreateItem() 
    {
        char szPath[MAX_PATH]="";
                    //快捷方式的目标应用程序名
        char szLink[MAX_PATH]="";
                    //快捷方式的数据文件名
        // 取得快捷方式的目标应用程序名
        if( !SelectMenuItem( szPath))
            return ;
        // 取得新建快捷方式所在的文件夹
        //并形成其数据文件名
        if( !GetShortcutCrt( szLink))
            return ;
        // 创建快捷方式
        if(!CreateLink( szPath, szLink) )
            return;
        // 通知shell有关变化
        NotifyShell( SHCNE_CREATE|SHCNE_INTERRUPT, 
                    szLink) ;
    }
    void CSortCutDlg::OnDeleteGroup() 
    {
        LPITEMIDLIST pidlBeginAt, pidlFolder ;
        char szPath[MAX_PATH]="";    // 取得开始菜单或桌面的PIDL
        SHGetSpecialFolderLocation( HWND_DESKTOP, 
                    nBeginAt, &pidlBeginAt) ;
        // 取得要删除的文件夹
        if( !BrowseForFolder( pidlBeginAt, &pidlFolder, 
                "请选择要删除的文件夹/菜单组:"))
            return ;
        // 把PIDL转化为路径名
        SHGetPathFromIDList( pidlFolder, szPath) ;
        // 删除文件夹
        if(!DeleteFolder( szPath))
            return ;
        // 通知shell有关变化
        NotifyShell( SHCNE_RMDIR|SHCNE_INTERRUPT, 
                        szPath) ;
    }
    void CSortCutDlg::OnDeleteItem() 
    {
        LPITEMIDLIST pidlBeginAt ;
        char szShortcut[ MAX_PATH]="",
            szPath[ MAX_PATH]="";    // 取得开始菜单或桌面的PIDL
        SHGetSpecialFolderLocation( HWND_DESKTOP, 
                    nBeginAt, &pidlBeginAt) ;
        // 把PIDL转化为路径名
        SHGetPathFromIDList( pidlBeginAt, szPath) ;
        // 取得要删除的快捷方式
        if( !GetShortcutDel( szPath, szShortcut))
            return ;
        // 删除快捷方式
        if( !DeleteLink(szShortcut))
            return ;
        // 通知SHELL有关改变
        NotifyShell( SHCNE_DELETE|SHCNE_INTERRUPT, 
                    szShortcut) ;
    }
    void CSortCutDlg::OnDesktop() 
    {
        //设置起始文件夹为桌面
        nBeginAt=CSIDL_DESKTOPDIRECTORY ;    
    }
    void CSortCutDlg::OnStartmenu() 
    {
        //设置起始文件夹为“开始”菜单
        nBeginAt=CSIDL_STARTMENU;
    }---------------------------------------------------------------
    (抄的) 原作者(张俊锋 崔华锋)