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.