Dateien, Ordner und Laufwerke
Die Volume-ID eines Laufwerks ermitteln
Die Funktion "VolumeID" gibt die Volume-ID, also den Namen einer Partition zurück:
function VolumeID(DriveChar: Char): string;
var
OldErrorMode : Integer;
NotUsed, VolFlags : DWORD;
Buf : array [0..MAX_PATH] of Char;
begin
OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
GetVolumeInformation(PChar(DriveChar + ':\'), Buf,
sizeof(Buf), nil, NotUsed, VolFlags,
nil, 0);
Result := Format('[%s]',[Buf]);
finally
SetErrorMode(OldErrorMode);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption:=VolumeID('c');
end;
|
Wie kann man aus einem Delphi-Programm eine Diskette formatieren?
Dieses Beispiel demonstriert das "stille" Formatieren eines Datenträgers. Die Routine ruft das DOS-Programm Format.com auf, darum erscheint kein Windows-Formatier-Dialog, es wird auch kein DOS-Fenster geöffnet. Nach dem Aufruf des Formatierprogramms wartet die Routine, bis das Formatieren beendet ist und prüft schließlich noch, ob die Formatierung erfolgreich war:
function TMainform.Diskette_formatieren(Laufwerk: String): Integer;
var
Befehl : String;
Datei : TextFile;
TempDateiName : Array [0..255] of Char;
TempVerzeichnis : Array [0..255] of Char;
StartupInfo : TStartupInfo;
ProcessInfo : TProcessInformation;
SektorenProCluster : Integer;
BytesProSektor : Integer;
FreieCluster : Integer;
ClusterInsgesamt : Integer;
Temp : Integer;
begin
// Datei zum Beantworten der Abfragen von FORMAT.EXE
// im Temp-Verzeichnis anlegen.
GetTempPath(255, TempVerzeichnis);
GetTempFileName(TempVerzeichnis, 'TMP', 0, TempDateiName);
// Antwort-Datei erzeugen
AssignFile(Datei, TempDateiName);
Rewrite(Datei); // Antwort-Datei erzeugen und öffnen
Writeln(Datei, #13#10); // 1. Return ("Diskette einlegen ...")
Writeln(Datei, #13#10); // 2. Return (Diskettenbezeichnung)
Writeln(Datei, 'n'#13#10); // keine weitere Diskette
CloseFile(Datei); // Datei schließen
// Befehlszeile zum Aufrufen von FORMAT.COM
// command.com /c = automatisch nach Beendigung schließen
// format ... /u = unbedingt formatieren
// format ... /c = defekte Sektoren prüfen
Befehl := 'command.com /c format '+Laufwerk+' /u /c < '+TempDateiName;
// StartupInfo initialisieren.
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb := SizeOf(TStartupInfo);
// DOS-Fenster soll nicht angezeigt werden.
StartupInfo.dwFlags := StartF_UseShowWindow;
StartupInfo.wShowWindow := SW_Hide;
// Formatieren
if CreateProcess(nil, PChar(Befehl), nil, nil,
False, 0, nil, 'c:\',
StartupInfo,
ProcessInfo) then begin
// Warten bis Format beendet ist.
WaitForSingleObject(ProcessInfo.hProcess, Infinite);
CloseHandle(ProcessInfo.hProcess);
end;
// Antwort-Datei wieder löschen
DeleteFile(TempDateiName);
// War das Formatieren erfolgreich?
if GetDiskFreeSpace(PChar(Laufwerk), SektorenProCluster,
BytesProSektor, FreieCluster,
ClusterInsgesamt) then begin
// Anzahl defekter Sektoren berechnen
Temp := FreieCluster * SektorenProCluster * BytesProSektor;
Result := (1457664 - Temp) div BytesProSektor;
end
else
// Diskette nicht eingelegt oder unformatiert
Result := - 1;
end; {Gerd Kayser}
|
Ermitteln von kurzen und langen Dateinamen
Mit der Funktion GetShortPathName ermittelt man aus einem langen Windows 95-Dateinamen den kurzen DOS-Dateinamen im Format 8.3:
function ShortFilename(LongName:string):string; var ShortName : PChar; begin ShortName:=StrAlloc(Max_Path); GetShortPathName(PChar(LongName), ShortName, Max_Path); Result:=string(ShortName); StrDispose(ShortName); end; |
In LongName wird der (lange) Original-Dateinamen als PCHAR-String übergeben, der kurze 8.3-dateiname wird als Wert der Funktion zurückgegeben. MaxLength ist die maximal erlaubte Dateinamensgröße. Der Pfad muß mit übergeben werden und wird auch wieder in Result zurückgegeben.
Zur Ermittlung eines langen Dateinamens aus einem kurzen (bzw. abgekürzten) empfiehlt sich diese Funktion, die auf der FindFirst-Routine basiert:
function GetLongPathName(APath:String):String;
var
i : Integer;
h : THandle;
Data : TWin32FindData;
IsBackSlash : Boolean;
begin
APath:=ExpandFileName(APath);
i:=Pos('\',APath);
Result:=Copy(APath,1,i);
Delete(APath,1,i);
repeat
i:=Pos('\',APath);
IsBackSlash:=i>0;
if Not IsBackSlash then
i:=Length(APath)+1;
h:=FindFirstFile(PChar(Result+Copy(APath,1,i-1)),Data);
if h<>INVALID_HANDLE_VALUE then begin
try
Result:=Result+Data.cFileName;
if IsBackSlash then
Result:=Result+'\';
finally
Windows.FindClose(h);
end;
end
else begin
Result:=Result+APath;
Exit;
end;
Delete(APath,1,i);
until Length(APath)=0;
end; {Peter Haas}
|
Wie prüfe ich, ob der User einen gültigen Dateinamen eingegeben hat?
Einfach testen, ob eines der folgenden Zeichen im Dateinamen (hier:Filename) enthalten ist:
const
{fuer 8.3-Dateinamen im DOS-Format:}
ShortForbiddenChars :
set of char=[';','=','+','<','>','|','"','[',']',' ','\',#39];
{fuer lange Dateinamen im Win95-Format:}
LongForbiddenChars :
set of char=['<','>','|','"','\'];
procedure TForm1.Edit1Change(Sender: TObject);
var NameValid : boolean;
Filename : string;
i : word;
begin
Filename:=Edit1.Text;
NameValid:=true;
if CheckBoxLong.Checked then begin
for i:=1 to length(Filename) do
if Filename[i] in LongForbiddenChars then
NameValid:=false;
end
else begin
for i:=1 to length(Filename) do
if Filename[i] in ShortForbiddenChars then
NameValid:=false;
end;
if not NameValid then
ShowMessage('Ungültig!');
end;
|
Wie kürzt man einen Dateipfad ab, daß er eine bestimmte Länge nicht überschreitet?
Ab Delphi 3 gibt es dafür die undokumentierte Funktion "MinimizeName" aus der Unit "FileCtrl":
PathName:=Appication.Exename;
Label1.Caption:=MinimizeName(PathName, {Der abzukürzende Pfadname}
Label1.Canvas, {Die Referenz-Zeichenfläche}
Label1.Width); {Die maximale Ausgabe-Breite}
|
Die Verkürzung eines Pfadnamens kann dann z.B. so aussehen:
C:\Programme\Borland\Delphi3\Projekte\Demos wird zu
C:\...\Projekte\Demos
Für ältere Delphiversionen kann man meine Komponente TSRLabel von meiner Komponentenseite benutzen.
Wie erstelle ich eine Dateiliste mit den registrierten Icons und Dateibeschreibungen?
Diese Unit demonstriert, wie ein TListView mit den Dateiennamen aus einem beliebigen Verzeichnis, sowie mit den damit assoziierten Icons und Dateibeschreibungen gefüllt wird.
Sie können auch ein komplettes Beispielprojekt (3 kB) mit dieser Unit vom Server laden.
Wie kann man Dateien löschen, kopieren oder verschieben?
1.) Dateien löschen
Dazu gibt es mehere Möglichkeiten:
var Dateiname : string;
{Möglichkeit 1: DeleteFile}
if not DeleteFile(Dateiname) then
ShowMessage('Datei "'+Dateiname+'" konnte nicht gelöscht werden!');
{Möglichkeit 2: Erase}
var F : File;
begin
AssignFile(F,Dateiname);
{$I-}
Erase(F);
{$I+}
if IOResult<>0 then
ShowMessage('Datei "'+Dateiname+'" konnte nicht gelöscht werden!');
|
Sie können auch ein komplettes Beispielprojekt (5 kB) mit dieser Unit vom Server laden.
2.) Dateien kopieren oder verschieben
Auch dazu gibt es mehere Möglichkeiten:
{Möglichkeit 1: CopyFile}
var Quelldatei, Zieldatei : string;
if not CopyFile(PChar(Quelldatei), PChar(Zieldatei), true) then
ShowMessage('Datei "'+Quelldatei+'" konnte nicht kopiert werden!');
{Möglichkeit 2: Per TFileStream}
FUNCTION QuickCopy ( Quelle, Ziel : STRING ) : BOOLEAN;
VAR
S, T: TFileStream;
BEGIN
Result := TRUE;
S := TFileStream.Create( Quelle, fmOpenRead );
TRY
TRY
T := TFileStream.Create( Ziel, fmOpenWrite OR fmCreate );
EXCEPT
Screen.Cursor := crDefault;
MessageDlg('Fehler beim Erzeugen der Zieldatei'+#13+Ziel, mtError, [mbOK], 0);
Result := FALSE;
END;
TRY
TRY
T.CopyFrom( S, S.Size ) ;
if Config.CopyDat then
FileSetDate( T.Handle, FileGetDate( S.Handle ) )
else
FileSetDate( T.Handle, DateTimeToFileDate(Now) );
{ Dateizeit setzen }
EXCEPT
Screen.Cursor := crDefault;
MessageDlg('Fehler beim Kopieren der Zieldatei'+#13+Ziel, mtError, [mbOK], 0);
Result := FALSE
END;
FINALLY
T.Free
END;
FINALLY
S.Free
END
END; {QuickCopy}
|
Die 3. Möglichkeit ist die API-Funktion SHFileOperation, mit dieser kann man auch die Standard-Windows-Fortschrittanzeige anzeigen. Der Gebrauch von SHFileOperation, sowie SHBrowseForFolder wird in dieser Unit demonstriert.
Sie können auch ein komplettes Beispielprojekt (5 kB) mit dieser Unit vom Server laden.
Wie kann man das Änderungsdatum von Dateien ermitteln?
Die einfachste Variante heißt FileAge:
var DOSDatum : integer;
WinDatum : TDateTime;
Dateiname : string;
DOSDatum:=FileAge(Dateiname);
WinDatum:=FileDateToDateTime(DOSDatum);
|
function Dateidatum(Dateiname:string):TDateTime;
var SR : TSearchRec;
begin
if FindFirst(Dateiname,faAnyFile,SR)=0 then begin
Result:=FileDateToDateTime(SR.Time);
FindClose(SR);
end;
end;
|
Wie kann man die Größe von Dateien ermitteln?
Man kann die Datei als File of Byte öffnen und dann die Dateigröße mit der FileSize-Funktion ermitteln, oder man benutzt die FindFirst-Funktion:
Function MyFileSize(Filename:string):integer;
var SR : TSearchRec;
begin
if FindFirst(Filename, faAnyFile, SR)=0 then begin
Result:=SR.Size;
FindClose(SR);
end
else
Result:=-1;
end; {MyFileSize}
|
Wie kann man alle Dateien eines Ordners mitsamt der Unterverzeichnisse ermitteln?
Diese Funktion liest rekursiv alle Dateinamen eines Ordners und dessen Unterverzeichnisse in eine Stringliste ein und gibt außerdem als Result die Gesamtgröße des Verzeichnisbaumes zurück:
var VerzListe : TStringList;
function VerzGroesse(Verzeichnis:string):longint;
var SR : TSearchRec;
Groesse : longint;
begin
Groesse:=0;
if Verzeichnis[length(Verzeichnis)]<>'\' then
Verzeichnis:=Verzeichnis+'\';
if FindFirst(Verzeichnis+'*.*',$3F,SR)=0 then begin
repeat
if ((SR.Attr and faDirectory)>0) and (SR.Name<>'.') and (SR.Name<>'..') then
Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name)
else
Groesse:=Groesse+SR.Size;
if (SR.Name<>'.') and (SR.Name<>'..') then
VerzListe.Add(Verzeichnis+SR.Name);
until FindNext(SR)<>0;
FindClose(SR);
end;
Result:=Groesse;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
VerzListe:=TStringList.Create;
Label1.Caption:=IntToStr(VerzGroesse('C:\Programme'))+' Byte';
ListBox1.Items.Assign(VerzListe);
VerzListe.Free;
end;
|
Wie man einen Verzeichnisbaum in ein TTreeView einliest
Die Funktion "Verzeichnisse_Einlesen" liest rekursiv alle Ordner eines Verzeichnisbaumes und optional auch alle Dateien als Baumstruktur in ein TTreeView ein:
{Aufrufbeispiel:}
TreeView1.Items.Clear;
Verzeichnisse_Einlesen(TreeView1,'C:\',nil,false);
procedure Verzeichnisse_Einlesen(Tree : TTreeView;
Verzeichnis : String;
Eintrag : TTreeNode;
Mit_Dateien : Boolean);
Var SearchRec : TSearchRec;
EintragTemp : TTreeNode;
begin
Tree.Items.BeginUpdate;
if Verzeichnis[length(Verzeichnis)]<>'\' then
Verzeichnis:=Verzeichnis+'\';
if FindFirst(Verzeichnis+ '*.*', faDirectory, SearchRec)=0 then begin
repeat
if (SearchRec.Attr and faDirectory = faDirectory)
and (SearchRec.Name[1] <> '.') then begin
//Eintrag ist ein Verzeichnis
if (SearchRec.Attr and faDirectory > 0) then
//zum aktuellen Eintrag hinzufügen
Eintrag := Tree.Items.AddChild(Eintrag, SearchRec.Name);
//Eintrag merken
EintragTemp := Eintrag.Parent;
//auf Untereinträge prüfen
Verzeichnisse_Einlesen(Tree,
Verzeichnis + SearchRec.Name,
Eintrag,
Mit_Dateien);
//Eintrag wiederholen
Eintrag := EintragTemp;
end
else
//Eintrag ist eine Datei
if Mit_Dateien then
if SearchRec.Name[1] <> '.' then
Tree.Items.AddChild(Eintrag, SearchRec.Name);
until FindNext(SearchRec)<>0;
FindClose(SearchRec);
end;
Tree.Items.EndUpdate;
end; {Michael Geisler}
|
Wie kann man Dateien in einem Verzeichnisbaum suchen?
Diese Unit zeigt, wie man rekursiv eine bestimmte Datei in einem Verzeichnisbaum sucht. Die Funktion der rekursiven Suche in der Unit demonstriert dieses Beispielprojekt.
Wie löscht man nur bestimmte Dateien in allen Unterverzeichnissen?
Die Prozedur "DeleteFiles" löscht alle Dateien, deren Name einer vorgegebenen Maske entspricht, in einem bestimmten Verzeichnis und optional in allen daran anhängenden Unterverzeichnissen:
procedure DeleteFiles(const Path, Mask: string; SubDirectories: Boolean);
var
Result: integer;
SR: TSearchRec;
begin
if FindFirst(Path + Mask, faAnyFile - faDirectory, SR) = 0 then begin
repeat
if not SysUtils.DeleteFile (Path + SR.Name) then begin
FileSetAttr(Path + SR.Name, 0); {Alle Dateiattribute löschen}
SysUtils.DeleteFile(Path + SR.Name);
end;
until FindNext(SR) <> 0;
SysUtils.FindClose(SR);
end;
{ Rekursiv durch alle Unterverzeichnisse }
if SubDirectories then begin
if SysUtils.FindFirst(Path + '*.*', faDirectory, SR) then begin
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then begin
FileSetAttr(Path + SR.Name, faDirectory);
DeleteFiles(Path + SR.Name + '\', Mask, true);
RmDir(Path + SR.Name); {Leeres Verzsichnis löschen}
end;
until FindNext(SR) <> 0;
SysUtils.FindClose(SR);
end;
end;
end; {Angepasst für Win NT von Marco Klemm}
|
DeleteFiles ('C:\Temp\', '*.txt', true);
|
Wie stelle ich fest, ob ein bestimmter Laufwerkstyp (z.B. CD-ROM) vorhanden ist?
Diese Funktion erstellt eine Stringliste mit allen Laufwerksbuchstaben eines bestimmten Typs und gibt als Result die Anzahl der vorhandenen Laufwerke zurück:
var DriveList : TStringList;
LWCount : byte;
function GetDrives(DriveType:integer):byte;
var Drives : array [1..255] of char;
LWListe : TStringList;
i : byte;
Len : DWord;
begin
LWListe:=TStringList.Create;
{Alle Laufwerke ermitteln}
Len:=GetLogicalDriveStrings(255,@Drives);
for i:=1 to Len-2 do
if (i mod 4)=1 then
LWListe.Add(copy(Drives,i,3));
{Laufwerke des angegebenen Typs zählen}
Result:=0;
DriveList.Clear;
for i:=0 to LWListe.Count-1 do begin
if GetDriveType(PChar(LWListe[i]))=DriveType then begin
Result:=Result+1;
DriveList.Add(copy(LWListe[i],1,2))
end;
end;
LWListe.Destroy;
end;
DriveList:=TStringLIst.Create;
{Wechselplatten:}
LWCount:=GetDrives(DRIVE_REMOVABLE);
{Festplatten:}
LWCount:=GetDrives(DRIVE_FIXED);
{Netzlaufwerke:}
LWCount:=GetDrives(DRIVE_REMOTE);
{CD-ROM:}
LWCount:=GetDrives(DRIVE_CDROM);
{RAM-Disks:}
LWCount:=GetDrives(DRIVE_RAMDISK);
{..Mach' was mit der DriveList..}
DriveList.Free;
|
Wie stelle ich fest, ob eine Diskette im Laufwerk steckt?
Die Funktion "DiskSize" gibt als Größe -1 zurück, wenn kein Datenträger vorhanden ist. Um keine System-Fehlermeldung zu erhalten, benutzt man die API-Funktion "SetErrorMode":
procedure TForm1.Button1Click(Sender: TObject);
var
ErrorMode: word;
begin
{Meldung eines kritischen Systemfehlers vehindern}
ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
try
if DiskSize(1) = -1 then
ShowMessage('Drive not ready');
finally
{ErrorMode auf den alten Wert setzen}
SetErrorMode(ErrorMode);
end;
end;
|
Wie ermittelt man das mit einem Dateitypen verknüpfte Programm?
Die Funktion GetExeForExtension funktioniert sowohl unter Win3.x, als auch unter Win9x. Sie findet das mit einem Dateitypen verknüpfte Programm, indem man ihr die Dateiendung übergibt. Unter Win9x wird das Programm aus der Registry ausgelesen, unter Win3.x aus der Systemdatei Win.ini.
uses
{$IFDEF WIN32}
Registry; {Unter Win9x benutzen wir die Registry}
{$ELSE}
IniFiles; {Unter Win3.x benutzen wir die Datei win.ini}
const MAX_PATH = 144;
{$ENDIF}
function GetExeForExtension(Ext:string):string;
var
{$IFDEF WIN32}
reg : TRegistry;
s : string;
{$ELSE}
WinIni : TIniFile;
WinIniFileName : array[0..MAX_PATH] of char;
s : string;
{$ENDIF}
begin
{$IFDEF WIN32}
s:='';
reg:=TRegistry.Create;
reg.RootKey:=HKEY_CLASSES_ROOT;
if reg.OpenKey('.'+ext+'\shell\open\command', false) then
begin
{The open command has been found}
s:=reg.ReadString('');
reg.CloseKey;
end
else begin
{perhaps there is a system file pointer}
if reg.OpenKey('.'+ext, false) then begin
s:=reg.ReadString('');
reg.CloseKey;
if s<>'' then begin
{A system file pointer was found}
if reg.OpenKey(s+'\shell\open\command', false) then
{The open command has been found}
s:=reg.ReadString('');
reg.CloseKey;
end;
end;
end;
{Delete any command line, quotes and spaces}
if Pos('%', s)>0 then
Delete(s, Pos('%', s), length(s));
if ((length(s)>0) and (s[1]='"')) then
Delete(s, 1, 1);
if ((length(s)>0) and (s[length(s)]='"')) then
Delete(s, Length(s), 1);
while ((length(s)>0) and
((s[length(s)]=#32) or (s[length(s)] = '"'))) do
Delete(s, Length(s), 1);
{$ELSE}
GetWindowsDirectory(WinIniFileName, sizeof(WinIniFileName));
StrCat(WinIniFileName, '\win.ini');
WinIni:=TIniFile.Create(WinIniFileName);
s:=WinIni.ReadString('Extensions', ext, '');
WinIni.Free;
{Delete any command line}
if Pos(' ^', s)>0 then
Delete(s, Pos(' ^', s), length(s));
{$ENDIF}
Result:=s;
end; {Johannes..}
|
ShowMessage(GetAssociatedProgram('gif'));
|
function GetExeForFile(const FileName: String): String;
var x: Integer;
begin
SetLength(Result, MAX_PATH);
if FindExecutable(PChar(FileName), nil, PChar(Result))>=32
then SetLength(Result, StrLen(PChar(Result)))
else Result:=inttostr(x);
end; {Michael Winter}
|
Wie verknüpft man ein eigenes Programm mit einem bestimmten Dateitypen?
Ich habe ein Delphi-Programm, daß für bestimmte Dateien zuständig sein soll (*.xyz). Wie bringe ich jetzt Windows am einfachsten bei, daß bei einem Doppelklick automatisch mein Programm aufgerufen werden soll ?
Diese Funktion RegistriereAnwendung für 32Bit-Windows von Edmund Matzke nimmt alle erforderlichen Einträge in der Windows-Registrierdatenbank vor.
uses Registry;
function RegistriereAnwendung(extension,
typename,
commandKey,
command: PChar): boolean;
var key: HKey;
begin
Result := false;
if RegCreateKey(HKEY_CLASSES_ROOT, extension, key) = ERROR_SUCCESS then begin
if RegSetValue(key, nil, REG_SZ, typename, 0) = ERROR_SUCCESS then begin
RegCloseKey(key);
if RegCreateKey(HKEY_CLASSES_ROOT, commandKey, key) = ERROR_SUCCESS then begin
if RegSetValue(key, nil, REG_SZ, command, 0) = ERROR_SUCCESS then begin
RegCloseKey(key);
Result := true; // hat geklappt
end
else begin
RegCloseKey(key);
RegDeleteKey(HKEY_CLASSES_ROOT, extension);
end;
end
else
RegDeleteKey(HKEY_CLASSES_ROOT, extension);
end
else begin
RegCloseKey(key);
RegDeleteKey(HKEY_CLASSES_ROOT, extension);
end;
end;
end; {Edmund Matzke}
|
uses IniFiles;
function RegistriereAnwendung(extension,
command: string): boolean;
var
WinIni : TIniFile;
WinIniFileName : array[0..MAX_PATH] of char;
s : array[0..64] of char;
begin
GetWindowsDirectory(WinIniFileName, sizeof(WinIniFileName));
StrCat(WinIniFileName, '\win.ini');
try
WinIni := TIniFile.Create(WinIniFileName);
WinIni.WriteString('Extensions',
extension,
command+' ^.'+extension);
WinIni.Free;
Result:=true;
StrCopy(S, 'Extensions');
SendMessage(HWND_BROADCAST, WM_WININICHANGE,
0, LongInt(@S));
except
Result:=false;
end;
end;
|
{Win32:}
RegistriereAnwendung('.xyz', 'MeinProggy',
'MeinProggy\DefaultIcon', PChar(Application.ExeName + ',0'));
{Win16:}
RegistriereAnwendung('.xyz', Application.ExeName);
|
procedure TMainForm.FormCreate(Sender: TObject);
begin
if ParamCount>0 then
Datei_laden(ParamStr(1)); // Den Code zum Laden der Daten ausführen
end;
|
type
TMainForm = class(TForm)
Private
procedure NeedFileOpen(var Msg: tMessage); Message wmMainInstanceOpenFile;
[..]
procedure TMainForm.NeedFileOpen(var Msg: tMessage);
var Path : string;
PC : array[0..MAX_PATH] of Char;
begin
GlobalGetAtomName(Msg.wParam, PC, MAX_PATH);
Path := Trim(StrPas(PC));
Datei_laden(Path); // Den Code zum Laden der Daten ausführen
end;
|
Wie kann ich die Versionsnummer einer Datei (z.B. einer DLL) auslesen?
Benutze die API-Funktion "GetFileVersionInfo":
function GetBuildInfo(const AFilename:String; var V1,V2,V3,V4:Word):Boolean;
var
VerInfoSize : Integer;
VerValueSize : DWord;
Dummy : DWord;
VerInfo : Pointer;
VerValue : PVSFixedFileInfo;
begin
VerInfoSize:=GetFileVersionInfoSize(PChar(AFilename),Dummy);
Result:=False;
if VerInfoSize<>0 then begin
GetMem(VerInfo,VerInfoSize);
try
if GetFileVersionInfo(PChar(AFilename),0,VerInfoSize,VerInfo) then begin
if VerQueryValue(VerInfo,'\',Pointer(VerValue),VerValueSize) then
with VerValue^ do begin
V1:=dwFileVersionMS shr 16;
V2:=dwFileVersionMS and $FFFF;
V3:=dwFileVersionLS shr 16;
V4:=dwFileVersionLS and $FFFF;
end;
Result:=True;
end;
finally
FreeMem(VerInfo,VerInfoSize);
end;
end;
end; {Peter Haas}
|
Fortgeschrittene Anwendung der SHBrowseForFolder-API-Funktion
Mit der API-Funktion "SHBrowseForFolder" kann man sich einen Dialog zur Verzeichnisauswahl anzeigen lassen. Ein Anwendungsbeispiel findet man in der Demo-Unit zur SHFileOperation-Funktion. Thorsten Vitt erklärt auf seiner Delphi-Tips-Seite, wie man ein Root-Verzeichnis bestimmen und bei der Anzeige des Dialogs einen Ordner vorwählen kann.
Auf der Grundlage seines Artikels habe ich ein Beispiel-Projekt erstellt, welches die in Thorstens Artikel beschriebenen Funktionen demonstriert. Das Projekt benötigt eine installierte RxLibrary, weil ich ausnahmsweise mal andere, als die Delphi-Standard-Komponenten verwendet habe. Man kann aber auch einfach diese Unit des Beispiel-Projekts in ein eigenes Projekt einbinden.
Erzeugen von Programmgruppen und Verknüpfungen
- DDE mit dem Programm-Manager in Win 3.x
In Windows 3.x erzsugt man Programmgruppen und Verknüpfunden per DDE-Konversation mit dem Progrmm-Manager. Dazu kann man einfach eine DDEClient-Komponente (System, DdeClientItem) auf das Formular setzen. Mit dieser baut man dann die DDE-Verbindung zum Programm-Manager auf, um eine Programmgruppe und eine Verlknüpfung zu erstellen:
Var Macro : String;
Cmd: array[0..255] of Char;
NewPrg,Desc : String;
Begin { Create the group, does nothing if it existst }
Name := 'StartUp';
Macro := Format('[CreateGroup(%s)]', [Name]) + #13#10;
StrPCopy (Cmd, Macro);
DDEClient.OpenLink;
if not DDEClient.ExecuteMacro(Cmd, False) then
MessageDlg(<ErrorMsg>, mtInformation, [mbOK], 0);
{ Then you add you program }
NewPrg := 'C:\HELLO.EXE'; {Full path of the program you}
Desc := 'Say Hello'; {Description that appears under the icon}
Macro := '[AddItem('+NewPrg+','+Desc+')]'+ #13#10;
StrPCopy (Cmd, Macro);
if not f1_.DDEClient.ExecuteMacro(Cmd, False) then
MessageDlg(<errorMsg>,mtInformation, [mbOK], 0);
{ To make sure the group is saved }
StrPCopy (Cmd,'[ShowGroup(nonexist,1)]');
DDEClient.ExecuteMacro(Cmd, False);
{ Now... this part doesn't work and I don't know why }
{ Anybody who knows why is welcome }
StrPCopy (Cmd,'[reload()]');
DDEClient.ExecuteMacro(Cmd, False);
{ and close the link }
DDEClient.CloseLink;
End;
|
DeleteGroup(GroupName) |
DeleteItem(ItemName) |
{This example needs a listbox called AllGroups}
procedure GetGroups(Sender: TObject);
var Thedata: pchar; {pchar that holds the groups}
dat: char; {used to process each group}
charcount: word;
Theitem,theline: string;
begin {get allgroups items}
charcount:=0;
TheData:= DDEClientConv2.RequestData('Groups');
theline:='';
repeat
application.processmessages;
dat:=Thedata[charcount]; {get character from the Thedata}
if (dat=chr(10)) {or (dat=chr(13))} then begin
while Pos(char(10), Theline) > 0 do
delete(Theline,pos(char(10),Theline),1);
while Pos(char(13), Theline) > 0 do
delete(Theline,pos(char(13),Theline),1);
If theline='' then
continue;
allgroups.items.add(theline); {Allgroups is a LISTBOX}
theline:='';
end;
Theline:=theline+dat;
inc(charcount);
until charcount >= strlen(Thedata);
strdispose(Thedata);
end;
|
Win32-API-Funktionen
Eine Textdatei mit den Win32-API-Funktionen zur Erstellung von Verknüpfungen (Shortcuts) und Programmgruppen kann hier geladen werden. Eine Delphi-Klasse zum Herumspielen mit Shell-Links findet man auf der Homepage von Thorsten Vitt.
Wie kann man aus einer *.lnk die Informationen zur eigentlichen Datei entnehmen?
Du mußt die Units ComObj, ActiveX und ShlObj einbinden. Dann kann man über die IShellLink-Schnittstelle die Informationen zum Linkfile abfragen. Diese Funktion liefert z.B. den Namen der EXE-Datei, auf die die Verknüpfung verweist:
function GetExeFromLink(LinkFile:string):string;
var
IU : IUnknown;
SL : IShellLink;
PF : IPersistFile;
FindDate : TWin32FindData;
TargetFile : array[0..MAX_PATH] of char;
begin
{ Herstellen des IShellLink und IPersistFile zum Zugriff auf
die .LNK Datei. }
IU := CreateComObject(CLSID_ShellLink);
SL := IU as IShellLink;
PF := SL as IPersistFile;
{ .LNK Datei in IPersistFile Objekt laden. }
PF.Load(PWideChar(LinkFile), STGM_READ);
{ Den Link durch Aufruf der Resolve-Methode auflösen }
SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI);
{ Jetzt kommt man an die Infos }
SL.GetPath(TargetFile, MAX_PATH, FindDate, SLGP_UNCPRIORITY);
{ Zieldatei ausgeben }
Result:=string(TargetFile);
end; {Oliver Stoer}
|
function GetExeFromLink(LinkFile:string):string;
var
FDir,
FName,
ExeName : PChar;
z : integer;
begin
{Speicher für die PChar-Variablen allozieren}
ExeName:=StrAlloc(255);
FName:=StrAlloc(255);
FDir:=StrAlloc(255);
StrPCopy(FName, ExtractFileName(FileName));
StrPCopy(FDir, ExtractFilePath(FileName));
z:=FindExecutable(FName, FDir, ExeName);
if z>32 then
Result:=StrPas(ExeName)
else
Result:='';
{Speicher der PChar-Variablen freigeben}
StrDispose(FDir);
StrDispose(FName);
StrDispose(ExeName);
end; {Michael Hanel}
|
Wie kann man den Eigenschaften-Dialog des Windows-Explorers für Dateien anzeigen?
Dazu benutzt man die "TShellExecuteInfo"-Datenstruktur der API-Funktion "ShellExecuteEx":
function ShowProperties(hWndOwner: HWND; const FileName: string;
Registerkarte: PChar): Boolean;
var Info: TShellExecuteInfo;
begin
{ Fill in the SHELLEXECUTEINFO structure }
with Info do begin
cbSize := SizeOf(Info);
fMask := SEE_MASK_NOCLOSEPROCESS or
SEE_MASK_INVOKEIDLIST or
SEE_MASK_FLAG_NO_UI;
wnd := hWndOwner;
lpVerb := 'properties';
lpFile := pChar(FileName);
lpParameters := registerkarte;
lpDirectory := nil;
nShow := 0;
hInstApp := 0;
lpIDList := nil;
end;
{ Call Windows to display the properties dialog. }
Result := ShellExecuteEx(@Info);
end; {Frank Wunderlich}
|
Der Aufruf der Funktion sieht dann so aus:
ShowProperties(HInstance, PCHAR(Dateiname), 'Freigabe'); 'Freigabe' steht für die Caption der Registerseite, Dateiname ist der Name der Datei mit komplettem Pfad.
Wie kann man die Schublade eines Ein CD-Laufwerks öffnen und schließen?
Dazu benutzt man die "MCISendString"-Funktion aus der Unit "MMSystem":
uses MMSystem;
// Schublade öffnen:
procedure TMainForm.MItemCDEjectClick(Sender: TObject);
var Befehl : string;
ErrCode : integer;
ErrStr : array [0..255] of char;
begin
Befehl := 'open '+Config.Laufwerk+' type cdaudio alias geraet';
MCISendString(PChar(Befehl), nil, 0, 0);
ErrCode:=MCISendString('set geraet door open wait', nil, 0, 0);
MCISendString('close geraet', nil, 0, 0);
if ErrCode <> 0 then begin
MCIGetErrorString(ErrCode, ErrStr, 255);
StatusBar.Panels[1].Text:=ErrStr;
end;
end;
// Schublade schließen:
procedure TMainForm.MItemCDCloseClick(Sender: TObject);
var Befehl : string;
ErrCode : integer;
ErrStr : array [0..255] of char;
begin
Befehl := 'open '+Config.Laufwerk+' type cdaudio alias geraet';
MCISendString(PChar(Befehl), nil, 0, 0);
ErrCode:=MCISendString('set geraet door closed wait',nil, 0, 0);
MCISendString('close geraet', nil, 0, 0);
if ErrCode <> 0 then begin
MCIGetErrorString(ErrCode, ErrStr, 255);
StatusBar.Panels[1].Text:=ErrStr;
end;
end;
|