📄 fileviewer.pas
字号:
unit FileViewer;
{$I JCL.INC}
{.$DEFINE UsePeImagesCache}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, ExtCtrls, Menus, JclPeImage;
type
TFileViewerChild = class(TForm)
DependencyTreeView: TTreeView;
Splitter1: TSplitter;
ListViewsPanel: TPanel;
Splitter2: TSplitter;
ImportListView: TListView;
ExportListView: TListView;
PopupMenu1: TPopupMenu;
Copy1: TMenuItem;
Save1: TMenuItem;
N1: TMenuItem;
Selectall1: TMenuItem;
Win32helpkeyword1: TMenuItem;
ModulesListView: TListView;
Splitter3: TSplitter;
DumpPEfile1: TMenuItem;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure ExportListViewData(Sender: TObject; Item: TListItem);
procedure ImportListViewData(Sender: TObject; Item: TListItem);
procedure ExportListViewColumnClick(Sender: TObject;
Column: TListColumn);
procedure ImportListViewColumnClick(Sender: TObject;
Column: TListColumn);
procedure FormDestroy(Sender: TObject);
procedure DependencyTreeViewChange(Sender: TObject; Node: TTreeNode);
procedure DependencyTreeViewDeletion(Sender: TObject; Node: TTreeNode);
procedure ModulesListViewInfoTip(Sender: TObject; Item: TListItem;
var InfoTip: String);
procedure ExportListViewDblClick(Sender: TObject);
procedure ModulesListViewDblClick(Sender: TObject);
private
FAnyRootError: Boolean;
FBasePath: string;
FCurrentImportDirIndex: Integer;
FFileName: TFileName;
FModulesList: TStringList;
FExportViewImage, FParentImportViewImage: TJclPeImage;
FPeImagesCache: TJclPeImagesCache;
function GetModuleName: string;
procedure SetFileName(const Value: TFileName);
procedure ExportListViewSort;
function ModuleToFileName(const ModuleName: string): TFileName;
procedure ImportListViewSort;
procedure InitTree;
function IsListViewActiveAndFocused( ListView: TListView): Boolean;
procedure UpdateExportView(Node: TTreeNode);
procedure UpdateModulesView;
procedure UpdateParentImportView(Node: TTreeNode);
class procedure UpdateSortData(Column: TListColumn);
function GetSelectedFileName: TFileName;
public
function GetWin32Function: string;
property FileName: TFileName read FFileName write SetFileName;
property ModuleName: string read GetModuleName;
property SelectedFileName: TFileName read GetSelectedFileName;
end;
var
FileViewerChild: TFileViewerChild;
implementation
uses DependViewMain, ToolsUtils, JclSysInfo, JclStrings, JclFileUtils;
{$R *.DFM}
type
TPeModuleState = (
modNoErrors, // Normal module with no errors.
modFwdNoErrors, // Forwarded module with no errors.
modDupNoErrors, // Duplicate module with no errors.
modDupFwdNoErrors, // Forwarded duplicate module with no errors.
modExportMissing, // Module with one or more missing export functions
modFwdExportMissing, // Forwarded module with one or more missing export functions
modDupExportMissing, // Duplicate module with one or more missing export functions
modDupFwdExportMissing, // Forwarded duplicate module with one or more missing export functions
modMissing, // Missing module.
modFwdMissing, // Missing forwarded module.
modInvalid, // Invalid module.
modFwdInvalid, // Invalid forwarded module.
modRoot // Root node.
);
TPeModuleImageInfo = record
ImageIndex, StateIndex: Integer;
end;
PPeModuleNodeData = ^TPeModuleNodeData;
TPeModuleNodeData = record
State: TPeModuleState;
ImportDirectoryIndex: Integer;
end;
const
imgModule = 0;
imgDupModule = 1;
imgModExportMissing = 2;
imgDupExportMissing = 3;
imgMissingModule = 4;
imgInvalidModule = 5;
imgForwardFlag = 6;
imgRoot = 7;
imgExport = 8;
imgFwdExport = 9;
imgImport = 10;
imgUnresolvedImport = 11;
imgSortAsceding = 12;
imgSortDesceding = 3;
ErrorModules = [modMissing, modFwdMissing, modInvalid, modFwdInvalid];
MissingExportModules = [modExportMissing, modFwdExportMissing, modDupExportMissing,
modDupFwdExportMissing, modMissing, modFwdMissing, modInvalid, modFwdInvalid];
ForwardedModules = [modFwdNoErrors, modDupFwdNoErrors, modFwdExportMissing,
modDupFwdExportMissing];
ModuleImages: array[TPeModuleState] of TPeModuleImageInfo = (
(ImageIndex: imgModule; StateIndex: -1),
(ImageIndex: imgModule; StateIndex: imgForwardFlag),
(ImageIndex: imgDupModule; StateIndex: -1),
(ImageIndex: imgDupModule; StateIndex: imgForwardFlag),
(ImageIndex: imgModExportMissing; StateIndex: -1),
(ImageIndex: imgModExportMissing; StateIndex: imgForwardFlag),
(ImageIndex: imgDupExportMissing; StateIndex: -1),
(ImageIndex: imgDupExportMissing; StateIndex: imgForwardFlag),
(ImageIndex: imgMissingModule; StateIndex: -1),
(ImageIndex: imgMissingModule; StateIndex: imgForwardFlag),
(ImageIndex: imgInvalidModule; StateIndex: -1),
(ImageIndex: imgInvalidModule; StateIndex: imgForwardFlag),
(ImageIndex: imgRoot; StateIndex: -1)
);
{ TFileViewerChild }
procedure TFileViewerChild.FormCreate(Sender: TObject);
begin
FModulesList := TStringList.Create;
FModulesList.Sorted := True;
FModulesList.Duplicates := dupIgnore;
FExportViewImage := TJclPeImage.Create;
FPeImagesCache := TJclPeImagesCache.Create;
{$IFNDEF UsePeImagesCache}
FParentImportViewImage := TJclPeImage.Create;
{$ENDIF}
FCurrentImportDirIndex := -1;
ExportListView.Height := ListViewsPanel.ClientHeight div 2;
ImportListView.Tag := $100;
UpdateSortData(ImportListView.Columns[0]);
ExportListView.Tag := $100;
UpdateSortData(ExportListView.Columns[0]);
ModulesListView.Columns[0].Width := ColumnTextWidth;
end;
procedure TFileViewerChild.FormDestroy(Sender: TObject);
begin
FModulesList.Free;
FExportViewImage.Free;
FPeImagesCache.Free;
{$IFNDEF UsePeImagesCache}
FParentImportViewImage.Free;
{$ENDIF}
end;
procedure TFileViewerChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Fix_ListViewBeforeClose(Self);
Action := caFree;
end;
function TFileViewerChild.GetModuleName: string;
begin
Result := ExtractFileName(FFileName);
end;
procedure TFileViewerChild.InitTree;
var
RootNode: TTreeNode;
procedure SetNodeState(Node: TTreeNode; State: TPeModuleState);
var
I: Integer;
begin
PPeModuleNodeData(Node.Data)^.State := State;
Node.ImageIndex := ModuleImages[State].ImageIndex;
Node.SelectedIndex := ModuleImages[State].ImageIndex;
Node.StateIndex := ModuleImages[State].StateIndex;
if State in (MissingExportModules + ErrorModules) then
begin
if Node.Parent = RootNode then FAnyRootError := True;
I := FModulesList.IndexOf(Node.Text);
Assert(I >= 0);
FModulesList.Objects[I] := Pointer(State);
end;
end;
function AddNode(Node: TTreeNode; const Text: string; State: TPeModuleState): TTreeNode;
var
Data: PPeModuleNodeData;
begin
Result := DependencyTreeView.Items.AddChild(Node, Text);
New(Data);
Result.Data := Data;
SetNodeState(Result, State);
end;
procedure ScanModule(const ModuleName: string; Node: TTreeNode; Forwarded, ErrorsOnly: Boolean);
var
ExeImage: TJclPeImage;
I, Found: Integer;
S: string;
TempNode: TTreeNode;
AddedNodes: array of TTreeNode;
AddedNodesCount: Integer;
begin
ExeImage := FPeImagesCache[ModuleToFilename(ModuleName)];
case ExeImage.Status of
stOk:
if not ErrorsOnly then
begin
with ExeImage.ImportList do
begin
SetLength(AddedNodes, Count);
AddedNodesCount := 0;
CheckImports(FPeImagesCache);
SortList(ilName);
for I := 0 to Count - 1 do
begin
S := Items[I].Name;
Found := FModulesList.IndexOf(S);
if Found = -1 then
begin
Found := FModulesList.Add(S);
FModulesList.Objects[Found] := Pointer(modNoErrors);
if Items[I].TotalResolveCheck = icUnresolved then
TempNode := AddNode(Node, S, modExportMissing)
else
TempNode := AddNode(Node, S, modNoErrors);
AddedNodes[AddedNodesCount] := TempNode;
Inc(AddedNodesCount);
end else
begin
if Items[I].TotalResolveCheck = icUnresolved then
TempNode := AddNode(Node, S, modDupExportMissing)
else
TempNode := AddNode(Node, S, modDupNoErrors);
ScanModule(TempNode.Text, TempNode, False, True); // !
end;
PPeModuleNodeData(TempNode.Data)^.ImportDirectoryIndex := Items[I].ImportDirectoryIndex;
end;
end;
for I := 0 to AddedNodesCount - 1 do
ScanModule(AddedNodes[I].Text, AddedNodes[I], False, False);
with ExeImage.ExportList do
begin
CheckForwards(FPeImagesCache);
for I := 0 to ForwardedLibsList.Count - 1 do
begin
S := ForwardedLibsList[I];
Found := FModulesList.IndexOf(S);
if Found = -1 then
begin
Found := FModulesList.Add(S);
FModulesList.Objects[Found] := Pointer(modNoErrors);
if TJclPeResolveCheck(ForwardedLibsList.Objects[I]) = icUnresolved then
AddNode(Node, S, modFwdExportMissing)
else
AddNode(Node, S, modFwdNoErrors);
end else
begin
if TJclPeResolveCheck(ForwardedLibsList.Objects[I]) = icUnresolved then
TempNode := AddNode(Node, S, modDupFwdExportMissing)
else
TempNode := AddNode(Node, S, modDupFwdNoErrors);
ScanModule(TempNode.Text, TempNode, True, True); // !
end;
end;
end;
end;
stNotFound:
if Forwarded then SetNodeState(Node, modFwdMissing) else SetNodeState(Node, modMissing);
else
if Forwarded then SetNodeState(Node, modFwdInvalid) else SetNodeState(Node, modInvalid);
end;
end;
begin
with DependencyTreeView do
begin
Items.BeginUpdate;
try
Items.Clear;
Screen.Cursor := crHourGlass;
RootNode := AddNode(nil, ModuleName, modRoot);
FModulesList.AddObject(ModuleName, Pointer(modRoot));
ScanModule(FFileName, RootNode, False, False);
RootNode.Expand(False);
Selected := RootNode;
finally
Items.EndUpdate;
Screen.Cursor := crDefault;
end;
end;
UpdateModulesView;
{$IFNDEF UsePeImagesCache}
FPeImagesCache.Clear;
{$ENDIF}
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -