📄 srchu.pas
字号:
unit SrchU;
interface
uses Classes, StdCtrls;
type
TSearchThread = class(TThread)
private
LB: TListbox;
CaseSens: Boolean;
FileNames: Boolean;
Recurse: Boolean;
SearchStr: string;
SearchPath: string;
FileSpec: string;
AddStr: string;
FSearchFile: string;
procedure AddToList;
procedure DoSearch(const Path: string);
procedure FindAllFiles(const Path: string);
procedure FixControls;
procedure ScanForStr(const FName: string; var FileStr: string);
procedure SearchFile(const FName: string);
procedure SetSearchFile;
protected
procedure Execute; override;
public
constructor Create(CaseS, FName, Rec: Boolean; const Str, SPath,
FSpec: string);
destructor Destroy; override;
end;
implementation
uses SysUtils, StrUtils, Windows, Forms, Main;
constructor TSearchThread.Create(CaseS, FName, Rec: Boolean; const Str,
SPath, FSpec: string);
begin
CaseSens := CaseS;
FileNames := FName;
Recurse := Rec;
SearchStr := Str;
SearchPath := AddBackSlash(SPath);
FileSpec := FSpec;
inherited Create(False);
end;
destructor TSearchThread.Destroy;
begin
FSearchFile := '';
Synchronize(SetSearchFile);
Synchronize(FixControls);
inherited Destroy;
end;
procedure TSearchThread.Execute;
begin
FreeOnTerminate := True; // set up all the fields
LB := MainForm.lbFiles;
Priority := TThreadPriority(MainForm.SearchPri);
if not CaseSens then SearchStr := UpperCase(SearchStr);
FindAllFiles(SearchPath); // process current directory
if Recurse then // if subdirs, then...
DoSearch(SearchPath); // recurse, otherwise...
end;
procedure TSearchThread.FixControls;
{ Enables controls in main form. Must be called through Synchronize }
begin
MainForm.EnableSearchControls(True);
end;
procedure TSearchThread.SetSearchFile;
{ Updates status bar with filename. Must be called through Synchronize }
begin
MainForm.StatusBar.Panels[1].Text := FSearchFile;
end;
procedure TSearchThread.AddToList;
{ Adds string to main listbox. Must be called through Synchronize }
begin
LB.Items.Add(AddStr);
end;
procedure TSearchThread.ScanForStr(const FName: string;
var FileStr: string);
{ Scans a FileStr of file FName for SearchStr }
var
Marker: string[1];
FoundOnce: Boolean;
FindPos: integer;
begin
FindPos := Pos(SearchStr, FileStr);
FoundOnce := False;
while (FindPos <> 0) and not Terminated do
begin
if not FoundOnce then
begin
{ use ":" only if user doesn't choose "filename only" }
if FileNames then
Marker := ''
else
Marker := ':';
{ add file to listbox }
AddStr := Format('File %s%s', [FName, Marker]);
Synchronize(AddToList);
FoundOnce := True;
end;
{ don't search for same string in same file if filenames only }
if FileNames then Exit;
{ Add line if not filename only }
AddStr := GetCurLine(FileStr, FindPos);
Synchronize(AddToList);
FileStr := Copy(FileStr, FindPos + Length(SearchStr),
Length(FileStr));
FindPos := Pos(SearchStr, FileStr);
end;
end;
procedure TSearchThread.SearchFile(const FName: string);
{ Searches file FName for SearchStr }
var
DataFile: THandle;
FileSize: Integer;
SearchString: string;
begin
FSearchFile := FName;
Synchronize(SetSearchFile);
try
DataFile := FileOpen(FName, fmOpenRead or fmShareDenyWrite);
if DataFile = 0 then raise Exception.Create('');
try
{ set length of search string }
FileSize := GetFileSize(DataFile, nil);
SetLength(SearchString, FileSize);
{ Copy file data to string }
FileRead(DataFile, Pointer(SearchString)^, FileSize);
finally
CloseHandle(DataFile);
end;
if not CaseSens then SearchString := UpperCase(SearchString);
ScanForStr(FName, SearchString);
except
on Exception do
begin
AddStr := Format('Error reading file: %s', [FName]);
Synchronize(AddToList);
end;
end;
end;
procedure TSearchThread.FindAllFiles(const Path: string);
{ procedure searches Path subdir for files matching filespec }
var
SR: TSearchRec;
begin
{ find first file matching spec }
if FindFirst(Path + FileSpec, faArchive, SR) = 0 then
try
repeat
SearchFile(Path + SR.Name); // process file
until (FindNext(SR) <> 0) or Terminated; // find next file
finally
SysUtils.FindClose(SR); // clean up
end;
end;
procedure TSearchThread.DoSearch(const Path: string);
{ procedure recurses through a subdirectory tree starting at Path }
var
SR: TSearchRec;
begin
{ look for directories }
if FindFirst(Path + '*.*', faDirectory, SR) = 0 then
try
repeat
{ if it's a directory and not '.' or '..' then... }
if ((SR.Attr and faDirectory) <> 0) and (SR.Name[1] <> '.') and
not Terminated then
begin
FindAllFiles(Path + SR.Name + '\'); // process directory
DoSearch(Path + SR.Name + '\'); // recurse
end;
until (FindNext(SR) <> 0) or Terminated; // find next directory
finally
SysUtils.FindClose(SR); // clean up
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -