Home Articles Books Downloads FAQs Tips

Q: Create a shortcut on the desktop


Answer

The API provides a COM interface called IShellLink that allows you create a shortcut. To create a shortcut on the desktop, you instantiate an IShellLink object, fill in its attributes, and save the link to the desktop directory.

The code example below demonstrates how to make a shortcut. In this example, the shortcut is saved to the root of the C:\ drive.

//----------------------------------------------------------------------
#include <shlobj.h>

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    // Allow the user to find a file with a common dialog box,
    // then create a shortcut to that file.
    if(OpenDialog1->Execute())
        CreateShortCut(OpenDialog1->FileName);
}
//----------------------------------------------------------------------
void TForm1::CreateShortCut(const AnsiString &file)
{
    // IShellLink allows us to create the shortcut.   
    // IPersistFile saves the link to the hard drive. 
    IShellLink* pLink;
    IPersistFile* pPersistFile;

    // First, we have to initialize the COM library
    if(SUCCEEDED(CoInitialize(NULL)))
    {
        // If CoInitialize doesn't fail, then instantiate an 
        // IShellLink object by calling CoCreateInstance.
        if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL,
                                      CLSCTX_INPROC_SERVER,
                                      IID_IShellLink, (void **) &pLink)))
        {
            // if that succeeds, then fill in the shortcut attributes
            pLink->SetPath(file.c_str());
            pLink->SetDescription("Woo hoo, look at Homer's shortcut");
            pLink->SetShowCmd(SW_SHOW);

            // Now we need to save the shortcut to the hard drive. The
            // IShellLink object also implements the IPersistFile interface.
            // Get the IPersistFile part of the object using QueryInterface.
            if(SUCCEEDED(pLink->QueryInterface(IID_IPersistFile,
                                               (void **)&pPersistFile)))
            {
                // If that succeeds, then call the Save method of the
                // IPersistFile object to write the shortcut to the desktop.
                WideString strShortCutLocation("C:\\bcbshortcut.lnk");
                pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE);
                pPersistFile->Release();
            }
            pLink->Release();
        }

        // Calls to CoInitialize need a corresponding CoUninitialize call
        CoUninitialize();
    }
}
//----------------------------------------------------------------------

If you execute this code, you should see a new shortcut file in the root of your C:\ drive. This is cool, but the purpose of this FAQ is to create a shortcut on the desktop. The preceeding example code does not save the shortcut to the proper place

To make the shortcut appear on the desktop instead of on the root of the drive, we simply need to change where we save the shortcut LNK file to. We can borrow code from the FAQ on determining the location of special folders to find the path to the Windows Desktop directory. Once we know where the desktop directory is, we can save our shortcut file to that directory. After doing that, Windows will display the shortcut icon on the desktop. The code below shows a new version of the CreateShortCut that saves the shortcut to the windows desktop

//----------------------------------------------------------------------
void TForm1::CreateShortCut(const AnsiString &file)
{
    IShellLink* pLink;
    IPersistFile* pPersistFile;
    LPMALLOC      ShellMalloc;
    LPITEMIDLIST  DesktopPidl;
    char DesktopDir[MAX_PATH];

    // We are going to create a pidl, and it will need to be
    // freed by the shell mallocator. Get the shell mallocator
    // object using API SHGetMalloc function. Return if failure.
    if(FAILED(SHGetMalloc(&ShellMalloc)))
        return;

    // use the API to get a pidl for the desktop directory
    // if function fails, return without proceeding
    if(FAILED(SHGetSpecialFolderLocation(NULL,
                                         CSIDL_DESKTOPDIRECTORY,
                                         &DesktopPidl)))
        return;

    // Now convert the pidl to a character string
    // return if function fails
    if(!SHGetPathFromIDList(DesktopPidl, DesktopDir))
    {
        ShellMalloc->Free(DesktopPidl);
        ShellMalloc->Release();
        return;
    }

    // At this point, we are done with the pidl and the
    // mallocator, so free them up
    ShellMalloc->Free(DesktopPidl);
    ShellMalloc->Release();

    if(SUCCEEDED(CoInitialize(NULL)))
    {
        if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL,
                                      CLSCTX_INPROC_SERVER,
                                      IID_IShellLink, (void **) &pLink)))
        {
            pLink->SetPath(file.c_str());
            pLink->SetDescription("Woo hoo, look at Homer's shortcut");
            pLink->SetShowCmd(SW_SHOW);

            if(SUCCEEDED(pLink->QueryInterface(IID_IPersistFile,
                                               (void **)&pPersistFile)))
            {

                WideString strShortCutLocation(DesktopDir);
                strShortCutLocation += "\\bcbshortcut.lnk";
                pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE);
                pPersistFile->Release();
            }
            pLink->Release();
        }
        CoUninitialize();
    }
}
//----------------------------------------------------------------------

Don't get bogged down in the COM

Creating shortcuts involves some use of COM. It is important not to let yourself get bogged down in the complexities of COM. COM is just another way of creating and using objects. It may be helpful to think of the COM code in this FAQ in terms of equivalent code in C++. Pretend that the IShellLink and IPersistFile objects are no different that other objects that you create with new and delete. It is also helpful to ignore the error handling code so that you can see what is really happening.

COM code                                   C++ psuedo-equivalent
IShellLink*   pLink;                       TShellLink   *Link;
IPersistFile* pPersistFile;                TPersistFile *PersistFile;

CoInitialize();

                                           // CoCreateInstance is like new  
CoCreateInstance(CLSID_ShellLink,          Link = new TShellLink;
                 NULL,
                 CLSCTX_INPROC_SERVER,
                 IID_IShellLink,
                 (void **) &pLink)

                                           // These are like member functions
pLink->SetPath(file.c_str());              Link->SetPath(file.c_str());
pLink->SetShowCmd(SW_SHOW);                Link->SetShowCmd(SW_SHOW);


                                           // QueryInterface is like casting
pLink->QueryInterface(IID_IPersistFile     PersistFile =
               (void **)&pPersistFile)))      dynamic_cast<TPersistFile*>(Link);

pPersistFile->Save("C:\\", TRUE);          PersistFile->Save("C:\\");


                                           // Release is like delete
pPersistFile->Release();                   delete PersistFile
pLink->Release();                          delete Link;

CoUninitialize();

IShellLink Interface

The example code in this FAQ only called three IShellLink methods: SetPath, SetDescritpion, and SetShowCmd. The IShellLink interface supports several other member functions. The list below summarizes the most useful functions.

  • SetArguments Command-line arguments passed to program
  • SetDescription Sets description (not sure where this is used)
  • SetHotkey Creates global hot key for the shortcut
  • SetIconLocation Allows you to specify the icon for the shortcut
  • SetIDList pidl replacement for SetPath
  • SetPath File that you are creating the shortcut for
  • SetShowCmd Hide, minimize, or maximize the program
  • SetWorkingDirectory Initial working directory for program
  • GetXXX Each Set function has a corresponding Get function

See the API help file for more info on IShellLink.


Downloads for this FAQ
shortcut.zip BCB3 project creates a shortcut on the desktop.
shortcutx.zip Same as shortcut.zip. Includes an EXE. Download is 138 k.


Copyright © 1997-2000 by Harold Howe.
All rights reserved.