home *** CD-ROM | disk | FTP | other *** search
- unit RXMain;
-
- { This program provides an example of how to use the TreeView and ListView
- components in a fashion similar to the Microsoft Windows Explorer.
-
- It is not intended to be a fully functional resource viewer. }
-
- interface
-
- uses
- SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
- ExeImage, StdCtrls, Buttons, ExtCtrls, ComCtrls, Menus, RXMisc, HexDump,
- ImgList;
-
- type
- TMainForm = class(TForm)
- StatusBar: TStatusBar;
- TreeViewPanel: TPanel;
- Panel1: TPanel;
- ImageViewer: TImage;
- ListView: TListView;
- TreeView: TTreeView;
- Splitter: TPanel;
- Notebook: TNotebook;
- ListViewPanel: TPanel;
- ListViewCaption: TPanel;
- FileOpenDialog: TOpenDialog;
- FileSaveDialog: TSaveDialog;
- MainMenu: TMainMenu;
- miFile: TMenuItem;
- miFileExit: TMenuItem;
- miFileSave: TMenuItem;
- miFileOpen: TMenuItem;
- miView: TMenuItem;
- miViewStatusBar: TMenuItem;
- miViewLargeIcons: TMenuItem;
- miViewSmallIcons: TMenuItem;
- miViewList: TMenuItem;
- miViewDetails: TMenuItem;
- miHelp: TMenuItem;
- miHelpAbout: TMenuItem;
- Small: TImageList;
- Large: TImageList;
- StringViewer: TMemo;
- procedure FileExit(Sender: TObject);
- procedure FileOpen(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure ListViewEnter(Sender: TObject);
- procedure SaveResource(Sender: TObject);
- procedure SelectListViewType(Sender: TObject);
- procedure ShowAboutBox(Sender: TObject);
- procedure ToggleStatusBar(Sender: TObject);
- procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
- procedure SplitterMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure SplitterMouseMove(Sender: TObject; Shift: TShiftState; X,
- Y: Integer);
- procedure SplitterMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure ViewMenuDropDown(Sender: TObject);
- procedure NotebookEnter(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- private
- FExeFile: TExeImage;
- HexDump: THexDump;
- SplitControl: TSplitControl;
- procedure LoadResources(ResList: TResourceList; Node: TTreeNode);
- procedure DisplayResources;
- procedure UpdateViewPanel;
- procedure UpdateListView(ResList: TResourceList);
- procedure UpdateStatusLine(ResItem: TResourceItem);
- end;
-
- var
- MainForm: TMainForm;
-
- implementation
-
- uses About, RXTypes;
-
- {$R *.DFM}
- {$R RXIMAGES.RES}
-
- const
- itBitmap: TResType = ImgList.rtBitmap; // Reference for duplicate identifier
- ImageMap: array[TResourceType] of Byte = (2,4,5,3,2,2,2,2,2,2,2,2,2,2,2,2,2);
- ResFiltMap: array[TResourceType] of Byte = (1,4,2,3,1,1,1,1,1,1,1,1,1,1,1,1,1);
-
- SNoResSelected = 'No resource selected';
- SFormCaption = 'Resource Explorer';
- SSaveFilter = 'Other Resource (*.*)|*.*|Bitmaps (*.BMP)|*.BMP|'+
- 'Icons (*.ICO)|*.ICO|Cursor (*.CUR)|*.CUR';
- SOpenFilter = 'Executable File Images (*.EXE;*.DLL)|*.EXE;*.DLL|'+
- 'All Files (*.*)|*.*';
-
- { Utility Functions }
-
- procedure Error(const ErrMsg: string);
- begin
- raise Exception.Create(ErrMsg);
- end;
-
- procedure ErrorFmt(const ErrMsg: string; Params: array of const);
- begin
- raise Exception.Create(format(ErrMsg, Params));
- end;
-
- function Confirm(const AMsg: String): Boolean;
- begin
- Result := MessageDlg(AMsg, mtConfirmation, mbYesNoCancel, 0) = idYes;
- end;
-
- { Non Event Handlers }
-
- procedure TMainForm.LoadResources(ResList: TResourceList; Node: TTreeNode);
- var
- I: Integer;
- CNode: TTreeNode;
- begin
- for I := 0 to ResList.Count - 1 do
- with ResList[I] do
- begin
- CNode := TreeView.Items.AddChildObject(Node, Name, ResList[I]);
- if IsList then
- begin
- CNode.SelectedIndex := 1;
- LoadResources(List, CNode);
- end else
- begin
- CNode.ImageIndex := ImageMap[ResList[I].ResType];
- CNode.SelectedIndex := CNode.ImageIndex;
- end;
-
- end;
- end;
-
- procedure TMainForm.DisplayResources;
- begin
- ListView.Items.Clear;
- TreeView.Selected := nil;
- TreeView.Items.Clear;
- LoadResources(FExeFile.Resources, nil);
- Caption := Format('%s - %s', [SFormCaption, AnsiLowerCaseFileName(FExeFile.FileName)]);
- with TreeView do
- begin
- SetFocus;
- Selected := Items[0];
- end;
- end;
-
- procedure TMainForm.UpdateViewPanel;
- var
- R: TResourceItem;
- begin
- with TreeView do
- begin
- if Visible and Assigned(Selected) then
- begin
- R := TResourceItem(Selected.Data);
- if R.IsList then UpdateListView(R.List) else
- begin
- case R.ResType of
- rtBitmap, rtIconEntry, rtCursorEntry:
- begin
- ImageViewer.Picture.Assign(R);
- Notebook.PageIndex := 1;
- end;
- rtString, rtMenu:
- begin
- StringViewer.Lines.Assign(R);
- StringViewer.SelStart := 0;
- Notebook.PageIndex := 2;
- end
- else
- begin
- HexDump.Address := R.RawData;
- HexDump.DataSize := R.Size;
- Notebook.PageIndex := 3;
- end;
- end;
- end;
- UpdateStatusLine(R);
- end;
- end;
- end;
-
- procedure TMainForm.UpdateListView(ResList: TResourceList);
- var
- I: Integer;
- begin
- ListView.Items.Clear;
- for I := 0 to ResList.Count-1 do
- with ResList[I], ListView.Items.Add do
- begin
- Data := ResList[I];
- Caption := Name;
- SubItems.Add(Format('%.7x', [Offset]));
- SubItems.Add(Format('%.5x', [Size]));
- ImageIndex := ImageMap[ResType];
- end;
- Notebook.PageIndex := 0;
- end;
-
- procedure TMainForm.UpdateStatusLine(ResItem: TResourceItem);
- begin
- if ResItem.IsList then
- begin
- ListViewCaption.Caption := ' '+TreeView.Selected.Text;
- StatusBar.Panels[0].Text := Format(' %d object(s)', [ListView.Items.Count]);
- StatusBar.Panels[1].Text := Format(' Offset: %x', [ResItem.Offset]);
- end else
- with ResItem do
- begin
- ListViewCaption.Caption := Format(' %s: %s', [ResTypeStr, Name]);
- StatusBar.Panels[0].Text := '';
- StatusBar.Panels[1].Text := Format(' Offset: %x Size: %x', [Offset, Size]);
- end;
- end;
-
- { Form Initialization }
-
- procedure TMainForm.FormCreate(Sender: TObject);
- begin
- SplitControl := TSplitControl.Create(Self);
- HexDump := CreateHexDump(TWinControl(NoteBook.Pages.Objects[3]));
- FileOpenDialog.Filter := SOpenFilter;
- FileSaveDialog.Filter := SSaveFilter;
- Small.ResourceLoad(itBitmap, 'SmallImages', clOlive);
- Large.ResourceLoad(itBitmap, 'LargeImages', clOlive);
- Notebook.PageIndex := 0;
- if (ParamCount > 0) and FileExists(ParamStr(1)) then
- begin
- Show;
- FExeFile := TExeImage.CreateImage(Self, ParamStr(1));
- DisplayResources;
- end;
- end;
-
- { Menu Event Handlers }
-
- procedure TMainForm.FileOpen(Sender: TObject);
- var
- TmpExeFile: TExeImage;
- begin
- with FileOpenDialog do
- begin
- if not Execute then Exit;
- TmpExeFile := TExeImage.CreateImage(Self, FileName);
- if Assigned(FExeFile) then FExeFile.Destroy;
- FExeFile := TmpExeFile;
- DisplayResources;
- end;
- end;
-
- procedure TMainForm.FileExit(Sender: TObject);
- begin
- Close;
- end;
-
- procedure TMainForm.ListViewEnter(Sender: TObject);
- begin
- with ListView do
- if (Items.Count > 1) and (Selected = nil) then
- begin
- Selected := Items[0];
- ItemFocused := Selected;
- end;
- end;
-
- procedure TMainForm.SaveResource(Sender: TObject);
- var
- ResItem: TResourceitem;
-
- function TreeViewResourceSelected: Boolean;
- begin
- Result := Assigned(TreeView.Selected) and
- Assigned(TreeView.Selected.Data) and
- not TResourceItem(TreeView.Selected.Data).IsList;
- if Result then ResItem := TResourceItem(TreeView.Selected.Data);
- end;
-
- function ListViewResourceSelected: Boolean;
- begin
- Result := Assigned(ListView.Selected) and
- Assigned(ListView.Selected.Data) and
- not TResourceItem(ListView.Selected.Data).IsList;
- if Result then ResItem := TResourceItem(ListView.Selected.Data);
- end;
-
- begin
- if TreeViewResourceSelected or ListViewResourceSelected then
- with FileSaveDialog do
- begin
- FilterIndex := ResFiltMap[ResItem.ResType];
- if Execute then
- ResItem.SaveToFile(FileName)
- end
- else
- Error(SNoResSelected);
- end;
-
- procedure TMainForm.SelectListViewType(Sender: TObject);
- begin
- ListView.ViewStyle := TViewStyle(TComponent(Sender).Tag);
- end;
-
- procedure TMainForm.ShowAboutBox(Sender: TObject);
- begin
- About.ShowAboutBox;
- end;
-
- procedure TMainForm.ToggleStatusBar(Sender: TObject);
- begin
- StatusBar.Visible := not StatusBar.Visible;
- end;
-
- procedure TMainForm.TreeViewChange(Sender: TObject; Node: TTreeNode);
- begin
- UpdateViewPanel;
- end;
-
- procedure TMainForm.ViewMenuDropDown(Sender: TObject);
- var
- I: Integer;
- begin
- miViewStatusBar.Checked := StatusBar.Visible;
- for I := 0 to miView.Count-1 do
- with miView.Items[I] do
- if GroupIndex = 1 then
- Checked := (Tag = Ord(ListView.ViewStyle));
- end;
-
- procedure TMainForm.SplitterMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if (Button = mbLeft) and (Shift = [ssLeft]) then
- SplitControl.BeginSizing(Splitter, TreeViewPanel);
- end;
-
- procedure TMainForm.SplitterMouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- begin
- with SplitControl do if Sizing then ChangeSizing(X, Y);
- end;
-
- procedure TMainForm.SplitterMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- with SplitControl do if Sizing then EndSizing;
- end;
-
- procedure TMainForm.NotebookEnter(Sender: TObject);
- var
- Page: TWinControl;
- begin
- with NoteBook do
- begin
- Page := TWinControl(Pages.Objects[PageIndex]);
- if (Page.ControlCount > 0) and (Page.Controls[0] is TWinControl) then
- TWinControl(Page.Controls[0]).SetFocus;
- end;
- end;
-
- procedure TMainForm.FormDestroy(Sender: TObject);
- begin
- SplitControl.Free;
- end;
-
- end.
-