Difference between revisions of "Windows Programming Tips"

From Free Pascal wiki
Jump to navigationJump to search
(→‎Creating a shortcut (.lnk) file: Easier shortcut example)
Line 57: Line 57:
  
 
===Creating a shortcut (.lnk) file===
 
===Creating a shortcut (.lnk) file===
Taken from forum post by Lainz:
+
Creating a shortcut on the desktop (can be easily adapted to any location). Adapted from [http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg13325.html post by Felipe Monteiro de Carvalho]
[http://lazarus.freepascal.org/index.php/topic,13845.msg72867.html#msg72867 Windows Startup post on forum]
+
The ISLink object has more methods that you can use to modify your shortcut...
  
 
<delphi>
 
<delphi>
UNIT shortcut;
+
uses
 +
...
 +
windows, shlobj {for special folders}, ActiveX, ComObj;
 +
...
 +
procedure CreateDesktopShortCut(Target, TargetArguments, ShortcutName: string);
 +
var
 +
  IObject: IUnknown;
 +
  ISLink: IShellLink;
 +
  IPFile: IPersistFile;
 +
  PIDL: PItemIDList;
 +
  InFolder: array[0..MAX_PATH] of Char;
 +
  TargetName: String;
 +
  LinkName: WideString;
 +
begin
 +
  { Creates an instance of IShellLink }
 +
  IObject := CreateComObject(CLSID_ShellLink);
 +
  ISLink := IObject as IShellLink;
 +
  IPFile := IObject as IPersistFile;
  
INTERFACE
+
  ISLink.SetPath(pChar(Target));
 +
  ISLink.SetArguments(pChar(TargetArguments));
 +
  ISLink.SetWorkingDirectory(pChar(ExtractFilePath(Target)));
  
   uses windows;
+
   { Get the desktop location }
 +
  SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, PIDL);
 +
  SHGetPathFromIDList(PIDL, InFolder);
 +
  LinkName := InFolder + PathDelim + ShortcutName+'.lnk';
  
   FUNCTION createShortcut(lnkpos : widestring; dstfn,dstargs,dstwdir,descr,iconfn : AnsiString; iconnum : longint) : boolean;
+
   { Create the link }
 
+
   IPFile.Save(PWChar(LinkName), false);
  // create a windows shortcut file (*.lnk)@lnkpos.
 
  // example: createSohrtcut('c:\test.lnk','c:\pascal\myprog.exe','-L 1000','c:\pascal','A nice Program.','c:\pascal\myprog.exe',0);
 
 
 
IMPLEMENTATION
 
 
 
TYPE
 
REFCLSID = PGUID;
 
REFIID  = PGUID;
 
 
 
CONST
 
CLSID_ShellLink  : TGUID = '{00021401-0000-0000-C000-000000000046}';
 
IID_IShellLink   : TGUID = '{000214EE-0000-0000-C000-000000000046}';
 
IID_IPersistFile : TGUID = '{0000010b-0000-0000-C000-000000000046}';
 
CLSCTX_INPROC_SERVER = 1;
 
 
 
FUNCTION CoInitialize(p : pointer) : HRESULT; stdcall;  external 'ole32.dll';
 
FUNCTION CoUninitialize(p : pointer) : HRESULT; stdcall;  external 'ole32.dll';
 
FUNCTION CoCreateInstance(a:REFCLSID; b:pointer; c:DWORD; d:REFIID; e:pointer) : HRESULT; stdcall;  external 'ole32.dll';
 
 
 
TYPE
 
PPISHellLink = ^PISHellLink;
 
PISHellLink = ^ISHellLink;
 
ISHellLink = packed record
 
  QueryInterface : FUNCTION(basis,id,p : pointer) : Hresult; stdcall;
 
  AddRef : FUNCTION(basis : pointer) : Hresult; stdcall;
 
  Release : FUNCTION(basis : pointer) : Hresult; stdcall;
 
  GetPath : pointer;
 
  GetIDList : pointer;
 
  SetIDList : pointer;
 
  GetDescription : pointer;
 
  SetDescription : FUNCTION(basis : pointer; descr : Pchar) : Hresult; stdcall;
 
  GetWorkingDirectory : pointer;
 
  SetWorkingDirectory : FUNCTION(basis : pointer; descr : Pchar) : Hresult; stdcall;
 
  GetArguments : pointer;
 
  SetArguments : FUNCTION(basis : pointer; args : Pchar) : Hresult; stdcall;
 
  GetHotkey : pointer;
 
  SetHotkey : pointer;
 
  GetShowCmd : pointer;
 
  SetShowCmd : pointer;
 
  GetIconLocation : pointer;
 
  SetIconLocation : FUNCTION(basis : pointer; iconfile : Pchar; icon : longint) : Hresult; stdcall;
 
  SetRelativePath : pointer;
 
  Resolve : pointer;
 
  SetPath : FUNCTION(basis : pointer; path : Pchar) : Hresult; stdcall;
 
 
end;
 
end;
  
PPIPersistFile = ^PIPersistFile;
 
PIPersistFile  = ^IPersistFile;
 
IPersistFile  = packed record
 
  QueryInterface : FUNCTION(basis,id,p : pointer) : Hresult; stdcall;
 
  AddRef : FUNCTION(basis : pointer) : Hresult; stdcall;
 
  Release : FUNCTION(basis : pointer) : Hresult; stdcall;
 
  GetClassID : FUNCTION(basis,p : pointer) : Hresult; stdcall;
 
  IsDirty : FUNCTION(basis : pointer) : Hresult; stdcall;
 
  Load : FUNCTION(basis : pointer; fn : Pchar; dw : dword) : Hresult; stdcall;
 
  Save : FUNCTION(basis : pointer; fn : Pchar; dw : dword) : Hresult; stdcall;
 
  SaveCompleted : FUNCTION(basis : pointer; fn : Pchar) : Hresult; stdcall;
 
  GetCurFile : FUNCTION(basis : pointer; fn : PPchar) : Hresult; stdcall;
 
end;
 
 
 
FUNCTION createShortcut(lnkpos : widestring; dstfn,dstargs,dstwdir,descr,iconfn : AnsiString; iconnum : longint) : boolean;
 
VAR psl : PPISHellLink; psp : PPIPersistFile;
 
BEGIN
 
  createShortcut := FALSE;
 
  if CoCreateInstance(@CLSID_ShellLink,nil,CLSCTX_INPROC_SERVER,@IID_IShellLink,@psl)=0 then begin
 
//    writeln('got IShellLink');
 
    if  (psl^^.setPath(psl,@dstfn[1])=0)
 
    and (psl^^.SetArguments(psl,@dstargs[1])=0)
 
    and (psl^^.SetWorkingDirectory(psl,@dstwdir[1])=0)
 
    and (psl^^.SetDescription(psl,@descr[1])=0)
 
    and (psl^^.SetIconLocation(psl,@iconfn[1],iconnum)=0)
 
    and (psl^^.queryInterface(psl,@IID_IPersistFile,@psp)=0) then begin
 
      if psp^^.save(psp,@lnkpos[1],0)=0 then createShortcut := true; 
 
      psp^^.release(psp);
 
    end;
 
    psl^^.Release(psl);
 
  end;
 
END;
 
 
BEGIN
 
  CoInitialize(nil);
 
END.
 
 
</delphi>
 
</delphi>
  

Revision as of 09:21, 1 February 2012

This page is dedicated to desktop Windows programming tips.

Other Interfaces

Platform specific Tips

Interface Development Articles

Articles about Windows Programming

  • High DPI - How to make your application DPI-aware on Windows 7.
  • Aero Glass - How to apply Aero Glass effect in a Lazarus Form on Windows 7.
  • Windows Icon - How to design your icon with the right sizes.
  • Inno Setup Usage - How to create setup files with File Association support.

Windows specific compiler options

The most prominent options are the -W flags. A GUI application requires the -WG flag. See Project Options / Compiler Options / Linking / Target OS Specific options / Win32 GUI application. No console is shown, writeln and readln are not possible, you will get File not open errors. Omitting this option creates a console application (same as passing -WC).

Code snippets

Listing all available drives

<delphi> program listdevices;

{$ifdef fpc}{$mode delphi}{$endif} {$apptype console}

uses

 Windows;

var

 Drive: Char;
 DriveLetter: string;

begin

 WriteLn('The following drives were found in this computer:');
 WriteLn();
 // Search all drive letters
 for Drive := 'A' to 'Z' do
 begin
   DriveLetter := Drive + ':\';
  
   case GetDriveType(PChar(DriveLetter)) of
    DRIVE_REMOVABLE: WriteLn(DriveLetter + ' Floppy Drive');
    DRIVE_FIXED:     WriteLn(DriveLetter + ' Fixed Drive');
    DRIVE_REMOTE:    WriteLn(DriveLetter + ' Network Drive');
    DRIVE_CDROM:     WriteLn(DriveLetter + ' CD-ROM Drive');
    DRIVE_RAMDISK:   WriteLn(DriveLetter + ' RAM Disk');
   end;
 end;
 // Also add a stop to see the result under Windows
 WriteLn();
 WriteLn('Please press <ENTER> to exit the program.');
 ReadLn(DriveLetter);

end. </delphi>

Creating a shortcut (.lnk) file

Creating a shortcut on the desktop (can be easily adapted to any location). Adapted from post by Felipe Monteiro de Carvalho The ISLink object has more methods that you can use to modify your shortcut...

<delphi> uses ... windows, shlobj {for special folders}, ActiveX, ComObj; ... procedure CreateDesktopShortCut(Target, TargetArguments, ShortcutName: string); var

 IObject: IUnknown;
 ISLink: IShellLink;
 IPFile: IPersistFile;
 PIDL: PItemIDList;
 InFolder: array[0..MAX_PATH] of Char;
 TargetName: String;
 LinkName: WideString;

begin

 { Creates an instance of IShellLink }
 IObject := CreateComObject(CLSID_ShellLink);
 ISLink := IObject as IShellLink;
 IPFile := IObject as IPersistFile;
 ISLink.SetPath(pChar(Target));
 ISLink.SetArguments(pChar(TargetArguments));
 ISLink.SetWorkingDirectory(pChar(ExtractFilePath(Target)));
 { Get the desktop location }
 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, PIDL);
 SHGetPathFromIDList(PIDL, InFolder);
 LinkName := InFolder + PathDelim + ShortcutName+'.lnk';
 { Create the link }
 IPFile.Save(PWChar(LinkName), false);

end;

</delphi>

Getting special folders (My documents, Desktop, local application data, etc)

Often it is useful to get the location of a special folder such as the desktop. The example below shows how you can get the LocalAppData directory - where the Lazarus installer stores its configuration by default. Look in the shlobj unit for more defines that let you look up the Desktop, Recycle Bin, etc. <delphi> uses ... shlobj;

var

 AppDataPath: Array[0..MaxPathLen] of Char; //Allocate memory

... begin ...

   AppDataPath:=;
   SHGetSpecialFolderPath(0,AppDataPath,CSIDL_LOCAL_APPDATA,false);
   writeln('Your local appdata path is: ' + AppDataPath);

</delphi>