You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++与WinAPI调用创建快捷方式的标准对话框

实现调用Windows标准创建快捷方式对话框

你已经可以通过C++结合WinAPI直接创建快捷方式,现有代码如下:

#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
#include <iostream>

HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
    HRESULT hres;
    IShellLink* psl;

    // 获取IShellLink接口指针,需确保已调用CoInitialize
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (SUCCEEDED(hres))
    {
        IPersistFile* ppf;

        // 设置快捷方式目标路径和描述
        psl->SetPath(lpszPathObj);
        psl->SetDescription(lpszDesc);

        // 查询IPersistFile接口,用于保存快捷方式
        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

        if (SUCCEEDED(hres))
        {
            WCHAR wsz[MAX_PATH];

            // 转换为Unicode字符串
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);

            // 保存快捷方式
            hres = ppf->Save(wsz, TRUE);
            ppf->Release();
        }
        psl->Release();
    }
    return hres;
}

int main()
{
    CoInitialize(NULL);
    std::wstring sourceFile = L"C:\\path\\to\\source\\file.txt";
    std::string linkName = "C:\\path\\to\\file.lnk";
    std::cout << CreateLink(sourceFile.c_str(), linkName.c_str(), L"");
    CoUninitialize();
    return 0;
}

一、弹出系统「新建快捷方式」向导对话框

这个对话框就是资源管理器中「新建→快捷方式」的引导界面,会让用户输入目标路径、快捷方式名称,最终自动完成创建。实现代码如下:

#include "windows.h"
#include "shobjidl.h"
#include "objbase.h"

int main()
{
    HRESULT hr = CoInitialize(NULL);
    if (SUCCEEDED(hr))
    {
        // 创建IShellLink接口实例
        IShellLink* pShellLink = nullptr;
        hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pShellLink);
        if (SUCCEEDED(hr))
        {
            // 获取IContextMenu接口
            IContextMenu* pContextMenu = nullptr;
            hr = pShellLink->QueryInterface(IID_IContextMenu, (void**)&pContextMenu);
            if (SUCCEEDED(hr))
            {
                // 触发新建快捷方式命令
                CMINVOKECOMMANDINFOEX info = {0};
                info.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
                info.fMask = CMIC_MASK_DEFAULT;
                info.lpVerb = L"new";
                info.hwnd = GetDesktopWindow();

                hr = pContextMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
                pContextMenu->Release();
            }
            pShellLink->Release();
        }
        CoUninitialize();
    }
    return 0;
}

二、弹出标准保存对话框选择快捷方式路径

如果需要先让用户选择快捷方式的保存位置和名称,再用现有代码创建,可以使用以下两种实现:

方法1:使用SHSaveFileDialog(推荐,支持高DPI,Vista及以上系统)

#include "windows.h"
#include "shobjidl.h"
#include "objbase.h"
#include <iostream>

// 复用已有的CreateLink函数
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc);

int main()
{
    CoInitialize(NULL);

    std::wstring targetPath = L"C:\\path\\to\\source\\file.txt";

    // 创建保存文件对话框
    IFileSaveDialog* pSaveDialog = nullptr;
    HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileSaveDialog, (void**)&pSaveDialog);
    if (SUCCEEDED(hr))
    {
        // 设置对话框标题和默认文件名
        pSaveDialog->SetTitle(L"保存快捷方式");
        pSaveDialog->SetFileName(L"新建快捷方式");

        // 设置仅显示.lnk文件
        COMDLG_FILTERSPEC filterSpec[] = {
            {L"快捷方式文件 (*.lnk)", L"*.lnk"}
        };
        pSaveDialog->SetFileTypes(ARRAYSIZE(filterSpec), filterSpec);
        pSaveDialog->SetFileTypeIndex(1);

        // 显示对话框
        hr = pSaveDialog->Show(GetDesktopWindow());
        if (SUCCEEDED(hr))
        {
            // 获取用户选择的路径
            IShellItem* pItem = nullptr;
            hr = pSaveDialog->GetResult(&pItem);
            if (SUCCEEDED(hr))
            {
                PWSTR pszPath = nullptr;
                hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
                if (SUCCEEDED(hr))
                {
                    char szMultiBytePath[MAX_PATH] = {0};
                    WideCharToMultiByte(CP_ACP, 0, pszPath, -1, szMultiBytePath, MAX_PATH, NULL, NULL);
                    CreateLink(targetPath.c_str(), szMultiBytePath, L"自定义快捷方式描述");
                    CoTaskMemFree(pszPath);
                }
                pItem->Release();
            }
        }
        pSaveDialog->Release();
    }

    CoUninitialize();
    return 0;
}

// 粘贴已有的CreateLink函数实现
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
    HRESULT hres;
    IShellLink* psl;

    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (SUCCEEDED(hres))
    {
        IPersistFile* ppf;

        psl->SetPath(lpszPathObj);
        psl->SetDescription(lpszDesc);

        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

        if (SUCCEEDED(hres))
        {
            WCHAR wsz[MAX_PATH];
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
            hres = ppf->Save(wsz, TRUE);
            ppf->Release();
        }
        psl->Release();
    }
    return hres;
}

方法2:使用GetSaveFileName(兼容Windows XP及更早系统)

#include "windows.h"
#include <iostream>

// 复用已有的CreateLink函数
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc);

int main()
{
    CoInitialize(NULL);

    std::wstring targetPath = L"C:\\path\\to\\source\\file.txt";
    char szLinkPath[MAX_PATH] = {0};

    OPENFILENAMEA ofn = {0};
    ofn.lStructSize = sizeof(OPENFILENAMEA);
    ofn.hwndOwner = GetDesktopWindow();
    ofn.lpstrFilter = "快捷方式文件 (*.lnk)\0*.lnk\0所有文件 (*.*)\0*.*\0";
    ofn.lpstrFile = szLinkPath;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrTitle = "保存快捷方式";
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
    ofn.lpstrDefExt = "lnk";

    if (GetSaveFileNameA(&ofn))
    {
        CreateLink(targetPath.c_str(), szLinkPath, L"自定义快捷方式描述");
    }

    CoUninitialize();
    return 0;
}

// 粘贴已有的CreateLink函数实现
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
    HRESULT hres;
    IShellLink* psl;

    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (SUCCEEDED(hres))
    {
        IPersistFile* ppf;

        psl->SetPath(lpszPathObj);
        psl->SetDescription(lpszDesc);

        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

        if (SUCCEEDED(hres))
        {
            WCHAR wsz[MAX_PATH];
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
            hres = ppf->Save(wsz, TRUE);
            ppf->Release();
        }
        psl->Release();
    }
    return hres;
}

内容的提问来源于stack exchange,提问作者Joe J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:15:56