-
Content Count
290 -
Joined
-
Last visited
-
Days Won
3
Everything posted by KodeZwerg
-
Or instead of dealing with the Vcl/Theme style you can easily put a label/panel next to a control and color it however you like and maybe add handler to simulate same behavior for mouse clicks. (Anchoring works great on that matter)
-
BiDiMode=bdRightToLeft but form caption is left align on Win10
KodeZwerg replied to lior I's topic in VCL
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Custom_Title_Bar_for_VCL_Forms -
Let me tell it that way @programmerdelphi2k, with my posted source I was able to enter "documents" as an included folder-name and "*.pdf" as a file-mask (also "c:\windows" to exclude that folder) and as a result i get all "*.pdf" files that are inside of any "documents" folder. exemplary "c:\users\documents\manual.pdf" or "c:\users\public\documents\another.pdf" or "c:\users\username\documents\etc.pdf" ... How-to with your way?
-
@Lars Fosdal In first post he tried to search for something, than he wanted a search for specific things, that will my code do.
-
@programmerdelphi2k I am happy when you are happy. To me your way is useless, you lost what I was needing, finding specific files in specific folders.
-
Take a guess 😛
-
program Project12; {$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.SysUtils; function ContainsString(const AStringList: TStringList; const ASearchFor: string): Boolean; begin Result := (AStringList.IndexOf(ASearchFor) <> -1); end; var sl: TStringList; begin try sl := TStringList.Create; try sl.Sorted := False; sl.Duplicates := dupIgnore; sl.CaseSensitive := True; sl.Add('some'); sl.Add('some.xyz'); WriteLn(ContainsString(sl, 'some')); // True WriteLn(ContainsString(sl, 'Some')); // False WriteLn(ContainsString(sl, 'yxz')); // False finally sl.Free; end; ReadLn; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
-
Does it now works for you? Feel free to remove ðŸ¤
-
Makes not much sense right now.
-
unit uFindEx; interface uses Winapi.Windows, System.SysUtils; type // My variant of an "StringList" TFindArray = TArray<string>; // array of WideString; function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; implementation const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; // Small helper to add strings in my "StringList" procedure AddFindArray(var AFindArray: TFindArray; const AString: string); inline; var i: Integer; begin i := Length(AFindArray); SetLength(AFindArray, Succ(i)); AFindArray[i] := AString; end; // This method will crawl thru a folder and collect their names // The ExclusionList should contain full path names that be total excluded from search, by default everything is included // IncludeSubFolders switch will get every folder, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path function FindExFolders(const ABasePath: string = ''; const AExclusionList: TFindArray = []; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp : TFindArray; i, ii : Integer; s:string; begin SetLength(Result, 0); if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then Exit; FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + '*.*') ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..')) and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then begin if (Length(AExclusionList) > 0) then begin for i := Low(AExclusionList) to High(AExclusionList) do if (0 = Pos(UpperCase(AExclusionList[i]), UpperCase(IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName))) then AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end else AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData)); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Result) to High(Result) do begin tmp := FindExFolders(Result[i], AExclusionList, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddFindArray(Result, tmp[ii]); end; SetLength(tmp, 0); end; // This method will crawl thru a folder and collect their filenames // IncludeSubFolders switch will get every filename, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path + filename function FindExFiles(const ABasePath: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp, Folders : TFindArray; i, ii : Integer; begin SetLength(Result, 0); if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then Exit; SetLength(Folders, 0); SetLength(tmp, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + AFileMask) ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))) then begin if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (AIncludeSubFolders and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddFindArray(Folders, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData)); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], AFileMask, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddFindArray(Result, tmp[ii]); end; SetLength(Folders, 0); SetLength(tmp, 0); end; // My variant of how a file search method can be done for windows systems // BasePath = where do we start at? eg "C:\Users" // FoldersMustExist = what foldername is a must for results? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // ExludedFolders = in what foldername you do not want to search? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // FileMask = what files you hunt for? eg "*.pas" // IncludeSubFolders = yes or no, you choose. False by default // based upon my "FindExFolders" and "FindExFiles" methods function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(Result, 0); SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); // prepare splittings if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddFindArray(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddFindArray(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then tmp := FindExFolders(ABasePath, splitExcluded, AIncludeSubFolders) else AddFindArray(tmp, ABasePath); // sieve out folders that match criteria if (Length(splitIncluded) > 0) then begin for i := Low(tmp) to High(tmp) do for ii := Low(splitIncluded) to High(splitIncluded) do if (0 <> Pos(UpperCase(splitIncluded[ii]), UpperCase(tmp[i]))) then AddFindArray(Folders, tmp[i]); end else Folders := tmp; // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddFindArray(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); end; end. Fixed the "Folder must included" thingy, now it works pretty well for me.
-
"Folder must exist" is currently not working, I will update but not today 😛
-
unit uFindEx; interface uses Winapi.Windows, System.SysUtils; type // My variant of an "StringList" TFindArray = TArray<string>; // array of WideString; function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; implementation const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; // Small helper to add strings in my "StringList" procedure AddStrArr(var AArr: TFindArray; const AString: string); inline; var i: Integer; begin i := Length(AArr); SetLength(AArr, Succ(i)); AArr[i] := AString; end; // This method will crawl thru a folder and collect their names // IncludeSubFolders switch will get every folder, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path function FindExFolders(const ABasePath: string; const AInclusionList, AExclusionList: TFindArray; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp : TFindArray; i, ii : Integer; s:string; begin SetLength(Result, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + '*.*') ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..')) and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then begin if (Length(AInclusionList) > 0) then begin for i := Low(AInclusionList) to High(AInclusionList) do if (0 <> Pos(UpperCase(AInclusionList[i]), UpperCase(IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName))) then AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end else AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (Length(AExclusionList) > 0) then begin for i := High(Result) downto Low(Result) do for ii := Low(AExclusionList) to High(AExclusionList) do if (0 <> Pos(UpperCase(AExclusionList[ii]), UpperCase(Result[i]))) then Delete(Result, i, 1); end; end; until not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Result) to High(Result) do begin tmp := FindExFolders(Result[i], AInclusionList, AExclusionList, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(tmp, 0); end; // This method will crawl thru a folder and collect their filenames // IncludeSubFolders switch will get every filename, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path + filename function FindExFiles(const ABasePath: string; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp, Folders : TFindArray; i, ii : Integer; begin SetLength(Result, 0); SetLength(Folders, 0); SetLength(tmp, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + AFileMask) ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))) then begin if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (AIncludeSubFolders and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddStrArr(Folders, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], AFileMask, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(Folders, 0); SetLength(tmp, 0); end; // My variant of how a file search method can be done for windows systems // BasePath = where do we start at? eg "C:\Users" // FoldersMustExist = what foldername is a must for results? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // ExludedFolders = in what foldername you do not want to search? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // FileMask = what files you hunt for? eg "*.pas" // IncludeSubFolders = yes or no, you choose. False by default // based upon my "FindExFolders" and "FindExFiles" methods function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddStrArr(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddStrArr(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then Folders := FindExFolders(ABasePath, splitIncluded, splitExcluded, AIncludeSubFolders) else AddStrArr(Folders, ABasePath); // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddStrArr(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); end; end. Can you retry please @programmerdelphi2k @robertjohns, just replace the full units code with above. Thanks for tipp about SetLength() @programmerdelphi2k, will be added later, in above i put now the exclusions right into the searching job, should be in theory faster now 😛 Ps: Now it is working with a full given pathname for exclusion, eg: "c:\windows"
-
Please not use a full path at excluding, for that my code ain't designed yet.
-
function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddStrArr(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddStrArr(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then tmp := FindExFolders(ABasePath, AIncludeSubFolders) else AddStrArr(tmp, ABasePath); // sieve out folders that match criteria if (Length(splitIncluded) > 0) then begin for i := Low(tmp) to High(tmp) do for ii := Low(splitIncluded) to High(splitIncluded) do if (0 <> Pos(UpperCase(splitIncluded[ii]), UpperCase(tmp[i]))) then AddStrArr(Folders, tmp[i]); end else Folders := tmp; // remove unwanted folders from search if (Length(splitExcluded) > 0) then for i := High(Folders) downto Low(Folders) do for ii := Low(splitExcluded) to High(splitExcluded) do if (0 <> Pos(PathDelim + UpperCase(splitExcluded[ii]), UpperCase(Folders[i]))) then Delete(Folders, i, 1); SetLength(tmp, 0); // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddStrArr(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); end; I apology, please update that method like shown above and now it really should work, I've not tested it much with extra large filesystems, on a small one it works like it should. You can enter "Windows" or "windows" or just "win", everything that has this in name will be excluded from the deeper file search mechanism. When I got more free time I will continue making it better.
-
Please compare with my approach, I posted earlier a full demo app that works straight out of the box, would like to see time results and if my way would also benefit of a full exclusion from giving names.
-
Yes, it was very complicated to fix. Uploaded a fully working Demo application based on my above mentioned code, added "Exclude" capabilities as you wanted. FindEx.zip
-
type _FINDEX_INFO_LEVELS = (FindExInfoStandard, FindExInfoBasic, FindExInfoMaxInfoLevel); TFINDEX_INFO_LEVELS = _FINDEX_INFO_LEVELS; _FINDEX_SEARCH_OPS = (FindExSearchNameMatch, FindExSearchLimitToDirectories, FindExSearchLimitToDevices, FindExSearchMaxSearchOp); TFINDEX_SEARCH_OPS = _FINDEX_SEARCH_OPS;
-
Here is my way on Windows to search for files or folders by using fastest method. There is still space for optimizations. Written and tested with FreePascal. unit uMain; {$mode objfpc}{$H+} interface uses Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls; type { TfrmMain } TfrmMain = class(TForm) btnStart: TButton; cbSubFolder: TCheckBox; edtBase: TEdit; edtFolder: TEdit; edtMask: TEdit; lblResult: TLabel; lbFiles: TListBox; pnlOptions: TPanel; pnlResult: TPanel; procedure btnStartClick(Sender: TObject); private public end; var frmMain: TfrmMain; implementation {$R *.lfm} type // My variant of an "StringList" TStrArr = array of WideString; const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; // Small helper to add strings in my "StringList" procedure AddStrArr(var AArr: TStrArr; const AString: WideString); inline; var i: Integer; begin i := Length(AArr); SetLength(AArr, Succ(i)); AArr[i] := AString; end; // This method will crawl thru a folder and collect their names // IncludeSubFolders switch will get every folder, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path function FindExFolders(const BasePath: WideString; const IncludeSubFolders: Boolean = False): TStrArr; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFINDEX_INFO_LEVELS; FindExSearchOps : TFINDEX_SEARCH_OPS; AdditionalFlags : DWORD; tmp : TStrArr; i, ii : Integer; begin SetLength(Result{%H-}, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(BasePath) + '*.*') ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then repeat if ((Win32FindData.cFileName <> '.') and (Win32FindData.cFileName <> '..') and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddStrArr(Result{%H-}, IncludeTrailingBackslash(BasePath) + Win32FindData.cFileName); until not Windows.FindNextFileW(FindExHandle, Win32FindData); Windows.FindClose(FindExHandle); if IncludeSubFolders then for i := Low(Result) to High(Result) do begin tmp := FindExFolders(Result[i], IncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(tmp, 0); end; // This method will crawl thru a folder and collect their filenames // IncludeSubFolders switch will get every filename, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path + filename function FindExFiles(const BasePath: WideString; const FileMask: WideString = '*.*'; const IncludeSubFolders: Boolean = False): TStrArr; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFINDEX_INFO_LEVELS; FindExSearchOps : TFINDEX_SEARCH_OPS; AdditionalFlags : DWORD; tmp, Folders : TStrArr; i, ii : Integer; begin SetLength(Result{%H-}, 0); SetLength(Folders{%H-}, 0); SetLength(tmp{%H-}, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(BasePath) + FileMask) ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then repeat if ((Win32FindData.cFileName <> '.') and (Win32FindData.cFileName <> '..')) then begin if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then AddStrArr(Result, IncludeTrailingBackslash(BasePath) + Win32FindData.cFileName); if (IncludeSubFolders and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddStrArr(Folders, IncludeTrailingBackslash(BasePath) + Win32FindData.cFileName); end; until not Windows.FindNextFileW(FindExHandle, Win32FindData); Windows.FindClose(FindExHandle); if IncludeSubFolders then for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], FileMask, IncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(Folders, 0); SetLength(tmp, 0); end; // My variant of how a file search method can be done for windows systems // BasePath = where do we start at? eg "C:\Users" // BaseFolder = what foldername is a must for results? eg "Documents", can be left empty for all // FileMask = what files you hunt for? eg "*.pas" // IncludeSubFolders = yes or no, you choose. False by default // based upon my "FindExFolders" and "FindExFiles" methods function FindEx(const BasePath: WideString; const BaseFolder: WideString = ''; const FileMask: WideString = '*.*'; const IncludeSubFolders: Boolean = False): TStrArr; var tmp, Folders, Files: TStrArr; i, ii: Integer; begin SetLength(tmp{%H-}, 0); SetLength(Folders{%H-}, 0); SetLength(Files{%H-}, 0); // collect folder(s) to work on if IncludeSubFolders then tmp := FindExFolders(BasePath, IncludeSubFolders) else AddStrArr(tmp, BasePath); // sieve out folders that match criteria if (BaseFolder <> '') then begin for i := Low(tmp) to High(tmp) do if (0 <> Pos(UpperCase(BaseFolder), UpperCase(tmp[i]))) then AddStrArr(Folders, tmp[i]); end else Folders := tmp; SetLength(tmp, 0); // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], FileMask); // do not enable the IncludeSubFolders switch here (!) for ii := Low(tmp) to High(tmp) do AddStrArr(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); end; { TfrmMain } procedure TfrmMain.btnStartClick(Sender: TObject); var i: Integer; List: TStrArr; begin lblResult.Caption := 'Search in progress, program may freeze, please wait...'; lblResult.Refresh; List := FindEx(WideString(edtBase.Text), WideString(edtFolder.Text), WideString(edtMask.Text), cbSubFolder.Checked); lbFiles.Items.BeginUpdate; lbFiles.Clear; for i := Low(List) to High(List) do lbFiles.Items.Add(AnsiString(List[i])); lbFiles.Items.EndUpdate; lblResult.Caption := 'Found ' + IntToStr(lbFiles.Count) + ' file(s).'; SetLength(List, 0); end; end. It should be easy to adapt any different kind of specifications, like excluding a defined folder. Enjoy!
-
Justification for Header different to resto column in TListView?
KodeZwerg replied to Ian Branch's topic in General Help
All of that is not needed, just do it in the Object Inspector like I told. -
Justification for Header different to resto column in TListView?
KodeZwerg replied to Ian Branch's topic in General Help
Just create first column without caption and set its width to 0. The others do what you want to do. -
Poor image quality with DrawBitmap when destination is smaller than source
KodeZwerg replied to XylemFlow's topic in FMX
How about using an ImageViewer control, put your bitmap in and give the control the "BestFit" property. -
resourcestring declaration works stangely in Delphi DLL
KodeZwerg replied to DeadlineX's topic in General Help
Welcome to forum! I am no clairvoyant and I assume nobody here is. So without showing anything how you do, what you think we can say? Watch line 123 there at call xyz you did something wrong?! Best practice would be a small demo zipped that shows us what you do and how you try to achieve that. -
Delphi 11 Community Edition based on 11.3.1 Pro
-
Delphi version 1 had no FMX and would probably not run under Windows 11 at all. (16bit)
- 4 replies
-
- delphi 11.2
- ide
-
(and 1 more)
Tagged with:
-
That "double don't" mean you do use Delphi for that, right?