When I need to make tricks as an override of protected methods, I tend to use a general solution to the problem ... I do a class hack.
Here's how to do it using TDirectoryListbox .
In each form you need to use this hacked TDirectoryListbox just add unitTDirectoryListbox_WithHiddenAndSystemFolders to the uses interface, so the form will use the hacked TDirectoryListbox .
Create a file called unitTDirectoryListbox_WithHiddenAndSystemFolders.pas in the proyect folder.
Put this text inside this file (I will explain later what I did):
unit unitTDirectoryListbox_WithHiddenAndSystemFolders; interface uses Windows ,SysUtils ,Classes ,FileCtrl ; type TDirectoryListbox=class(FileCtrl.TDirectoryListbox) private FPreserveCase:Boolean; FCaseSensitive:Boolean; protected function ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; procedure BuildList;override; public constructor Create(AOwner:TComponent);override; destructor Destroy;override; property PreserveCase:Boolean read FPreserveCase; property CaseSensitive:Boolean read FCaseSensitive; end; implementation constructor TDirectoryListbox.Create(AOwner:TComponent); begin inherited Create(AOwner); end; destructor TDirectoryListbox.Destroy; begin inherited Destroy; end; function TDirectoryListbox.ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; var TheCount,Status:Integer; SearchRec:TSearchRec; begin TheCount:=0; Status:=FindFirst(IncludeTrailingPathDelimiter(ParentDirectory)+'*.*',faDirectory or faHidden or faSysFile,SearchRec); try while 0=Status do begin if faDirectory=(faDirectory and SearchRec.Attr) then begin if ('.'<>SearchRec.Name) and ('..'<>SearchRec.Name) then begin DirectoryList.Add(SearchRec.Name); Inc(TheCount); end; end; Status:=FindNext(SearchRec); end; finally FindClose(SearchRec); end; ReadDirectoryNames:=TheCount; end; procedure TDirectoryListBox.BuildList; var TempPath: string; DirName: string; IndentLevel, BackSlashPos: Integer; VolFlags: DWORD; I: Integer; Siblings: TStringList; NewSelect: Integer; Root: string; begin try Items.BeginUpdate; Items.Clear; IndentLevel := 0; Root := ExtractFileDrive(Directory)+'\'; GetVolumeInformation(PChar(Root), nil, 0, nil, DWORD(i), VolFlags, nil, 0); FPreserveCase := VolFlags and (FS_CASE_IS_PRESERVED or FS_CASE_SENSITIVE) <> 0; FCaseSensitive := (VolFlags and FS_CASE_SENSITIVE) <> 0; if (Length(Root) >= 2) and (Root[2] = '\') then begin Items.AddObject(Root, OpenedBMP); Inc(IndentLevel); TempPath := Copy(Directory, Length(Root)+1, Length(Directory)); end else TempPath := Directory; if (Length(TempPath) > 0) then begin if AnsiLastChar(TempPath)^ <> '\' then begin BackSlashPos := AnsiPos('\', TempPath); while BackSlashPos <> 0 do begin DirName := Copy(TempPath, 1, BackSlashPos - 1); if IndentLevel = 0 then DirName := DirName + '\'; Delete(TempPath, 1, BackSlashPos); Items.AddObject(DirName, OpenedBMP); Inc(IndentLevel); BackSlashPos := AnsiPos('\', TempPath); end; end; Items.AddObject(TempPath, CurrentBMP); end; NewSelect := Items.Count - 1; Siblings := TStringList.Create; try Siblings.Sorted := True; { read all the dir names into Siblings } ReadDirectoryNames(Directory, Siblings); for i := 0 to Siblings.Count - 1 do Items.AddObject(Siblings[i], ClosedBMP); finally Siblings.Free; end; finally Items.EndUpdate; end; if HandleAllocated then ItemIndex := NewSelect; end; end.
Now I will explain what I did:
- By adding
unitTDirectoryListbox_WithHiddenAndSystemFolders to the uses interface, I force the form to use the modified component (aka, hacked ). - I started by copying a protected method called
ReadDirectoryNames (the one that needs to be modified), I will copy it from the FileCtrl unit, and then I will edit this copy on my own device to fix problem (without showing hidden folders or system folders); trick should edit the FindFirst call by adding the or faHidden or faSysFile faDirectory part after faDirectory , also change the SlashSep to IncludeTrailingPathDelimiter (avoid some additional links, etc.) and also perform formatting (indexing, etc.), so I see that this method has been modified. - Then I follow the missing things ... like a
BuildList , I just simply copy it from unit FileCtrl without any changes (if not copying the hack does not work, as the ReadDirectoryNames call is inside the BuildList ). - Then I copy the declaration of
FPreserveCase and FCaseSensitive and their property declarations (they are used inside the BuildList method). - That is, the now modified
TDirectoryListbox will see hidden and system folders
We hope this helps others, so you can simultaneously TDirectoryListbox (original and modified) at the same time (but not in the same form, sorry) in your project, without changing the VCL at all.
PD: Someone who has additional knowledge can add properties for customization, if he should show or not hide and / or system folders as an improvement, he should not be very difficoult, two private logical variables and their corresponding property declaration with read and write methods ... I didn’t do this, because I would like to add not only these two, but also SymLinks, etc. (Search faSymLink on unit SysUtils and see how many there are, work hard to add all of them), sorry for any inconvenience for this.