关闭

给应用程序创建快捷方式VC实现

4507人阅读 评论(0) 收藏 举报
 1 引言
在Windows 3.x中,软件安装程序通常使用动态数据交换(DDE)的方法在程序管理器(Program Manager)中创建一个程序组(Program Group)。随着Windows95/98/NT这些32操作系统在系统内核和用户界面上的巨大改进,这种方法在已经不再适用了。现在,几乎所有的安装 程序都是在“开始”菜单中添加新的菜单项,或者在桌面上建立新的快捷方式(Shortcut)(有时还要建立相应的菜单组或文件夹来包含多个菜单项或快捷 方式),以便于用户使用时方便快捷地启动软件。
通过手工操作建立这些菜单项或快捷方式并不复杂,在一般Windows使用手册中都有介绍,相信大家都很熟悉,在此不再赘述。笔者在有关资料的基础上,通过实践摸索,找到了在应用程序中完成上述工作的方法。这正是开发安装程序所必需的。

2 快捷方式的实质
Windows 的快捷方式实际上是一个带有扩展名LNK的数据文件,其中包含有用于访问Windows某一对象(即在资源管理器中所能浏览的所有对象,包括文件,文件 夹,驱动器及打印机等)的有关信息,如目标对象的路径和名称,工作目录,要传递的命令行参数,运行时的初始显示状态,图标及其快捷键等。通过在快捷方式上单击鼠标右键并在弹出菜单中选择“属性”可以观察该快捷方式的这些性质。
快 捷方式的数据文件如果存放在C:/Windows/Desktop子目录下,这个快捷方式就会显示在桌面上,而如果存放在C:/Windows/” Start Menu”/Programs子目录下,这个快捷方式就会作为“开始”菜单的一个菜单项出现。而桌面上的文件夹和“开始”菜单的菜单组则是上述两个子目录 下的子目录的表现。

3 编程思想
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 :
#i nclude "stdafx.h"
#i nclude "SortCut.h"
#i nclude "SortCutDlg.h"

#i nclude "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;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:284056次
    • 积分:2818
    • 等级:
    • 排名:第12705名
    • 原创:62篇
    • 转载:31篇
    • 译文:0篇
    • 评论:86条
    最新评论