home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Demos / Resxplor / rxmain.pas < prev    next >
Pascal/Delphi Source File  |  1999-08-11  |  10KB  |  370 lines

  1. unit RXMain;
  2.  
  3. { This program provides an example of how to use the TreeView and ListView
  4.   components in a fashion similar to the Microsoft Windows Explorer.
  5.  
  6.   It is not intended to be a fully functional resource viewer. }
  7.  
  8. interface
  9.  
  10. uses
  11.   SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  12.   ExeImage, StdCtrls, Buttons, ExtCtrls, ComCtrls, Menus, RXMisc, HexDump,
  13.   ImgList;
  14.  
  15. type
  16.   TMainForm = class(TForm)
  17.     StatusBar: TStatusBar;
  18.     TreeViewPanel: TPanel;
  19.     Panel1: TPanel;
  20.     ImageViewer: TImage;
  21.     ListView: TListView;
  22.     TreeView: TTreeView;
  23.     Splitter: TPanel;
  24.     Notebook: TNotebook;
  25.     ListViewPanel: TPanel;
  26.     ListViewCaption: TPanel;
  27.     FileOpenDialog: TOpenDialog;
  28.     FileSaveDialog: TSaveDialog;
  29.     MainMenu: TMainMenu;
  30.     miFile: TMenuItem;
  31.     miFileExit: TMenuItem;
  32.     miFileSave: TMenuItem;
  33.     miFileOpen: TMenuItem;
  34.     miView: TMenuItem;
  35.     miViewStatusBar: TMenuItem;
  36.     miViewLargeIcons: TMenuItem;
  37.     miViewSmallIcons: TMenuItem;
  38.     miViewList: TMenuItem;
  39.     miViewDetails: TMenuItem;
  40.     miHelp: TMenuItem;
  41.     miHelpAbout: TMenuItem;
  42.     Small: TImageList;
  43.     Large: TImageList;
  44.     StringViewer: TMemo;
  45.     procedure FileExit(Sender: TObject);
  46.     procedure FileOpen(Sender: TObject);
  47.     procedure FormCreate(Sender: TObject);
  48.     procedure ListViewEnter(Sender: TObject);
  49.     procedure SaveResource(Sender: TObject);
  50.     procedure SelectListViewType(Sender: TObject);
  51.     procedure ShowAboutBox(Sender: TObject);
  52.     procedure ToggleStatusBar(Sender: TObject);
  53.     procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
  54.     procedure SplitterMouseDown(Sender: TObject; Button: TMouseButton;
  55.       Shift: TShiftState; X, Y: Integer);
  56.     procedure SplitterMouseMove(Sender: TObject; Shift: TShiftState; X,
  57.       Y: Integer);
  58.     procedure SplitterMouseUp(Sender: TObject; Button: TMouseButton;
  59.       Shift: TShiftState; X, Y: Integer);
  60.     procedure ViewMenuDropDown(Sender: TObject);
  61.     procedure NotebookEnter(Sender: TObject);
  62.     procedure FormDestroy(Sender: TObject);
  63.   private
  64.     FExeFile: TExeImage;
  65.     HexDump: THexDump;
  66.     SplitControl: TSplitControl;
  67.     procedure LoadResources(ResList: TResourceList; Node: TTreeNode);
  68.     procedure DisplayResources;
  69.     procedure UpdateViewPanel;
  70.     procedure UpdateListView(ResList: TResourceList);
  71.     procedure UpdateStatusLine(ResItem: TResourceItem);
  72.   end;
  73.  
  74. var
  75.   MainForm: TMainForm;
  76.  
  77. implementation
  78.  
  79. uses About, RXTypes;
  80.  
  81. {$R *.DFM}
  82. {$R RXIMAGES.RES}
  83.  
  84. const
  85.   itBitmap: TResType = ImgList.rtBitmap; // Reference for duplicate identifier
  86.   ImageMap: array[TResourceType] of Byte = (2,4,5,3,2,2,2,2,2,2,2,2,2,2,2,2,2);
  87.   ResFiltMap: array[TResourceType] of Byte = (1,4,2,3,1,1,1,1,1,1,1,1,1,1,1,1,1);
  88.  
  89.   SNoResSelected = 'No resource selected';
  90.   SFormCaption   = 'Resource Explorer';
  91.   SSaveFilter    = 'Other Resource (*.*)|*.*|Bitmaps (*.BMP)|*.BMP|'+
  92.                    'Icons (*.ICO)|*.ICO|Cursor (*.CUR)|*.CUR';
  93.   SOpenFilter    = 'Executable File Images (*.EXE;*.DLL)|*.EXE;*.DLL|'+
  94.                    'All Files (*.*)|*.*';
  95.  
  96. { Utility Functions }
  97.  
  98. procedure Error(const ErrMsg: string);
  99. begin
  100.   raise Exception.Create(ErrMsg);
  101. end;
  102.  
  103. procedure ErrorFmt(const ErrMsg: string; Params: array of const);
  104. begin
  105.   raise Exception.Create(format(ErrMsg, Params));
  106. end;
  107.  
  108. function Confirm(const AMsg: String): Boolean;
  109. begin
  110.   Result := MessageDlg(AMsg, mtConfirmation, mbYesNoCancel, 0) = idYes;
  111. end;
  112.  
  113. { Non Event Handlers }
  114.  
  115. procedure TMainForm.LoadResources(ResList: TResourceList; Node: TTreeNode);
  116. var
  117.   I: Integer;
  118.   CNode: TTreeNode;
  119. begin
  120.   for I := 0 to ResList.Count - 1 do
  121.     with ResList[I] do
  122.     begin
  123.       CNode := TreeView.Items.AddChildObject(Node, Name, ResList[I]);
  124.       if IsList then
  125.       begin
  126.         CNode.SelectedIndex := 1;
  127.         LoadResources(List, CNode);
  128.       end else
  129.       begin
  130.         CNode.ImageIndex := ImageMap[ResList[I].ResType];
  131.         CNode.SelectedIndex := CNode.ImageIndex;
  132.       end;
  133.  
  134.     end;
  135. end;
  136.  
  137. procedure TMainForm.DisplayResources;
  138. begin
  139.   ListView.Items.Clear;
  140.   TreeView.Selected := nil;
  141.   TreeView.Items.Clear;
  142.   LoadResources(FExeFile.Resources, nil);
  143.   Caption := Format('%s - %s', [SFormCaption, AnsiLowerCaseFileName(FExeFile.FileName)]);
  144.   with TreeView do
  145.   begin
  146.     SetFocus;
  147.     Selected := Items[0];
  148.   end;
  149. end;
  150.  
  151. procedure TMainForm.UpdateViewPanel;
  152. var
  153.   R: TResourceItem;
  154. begin
  155.   with TreeView do
  156.   begin
  157.     if Visible and Assigned(Selected) then
  158.     begin
  159.       R := TResourceItem(Selected.Data);
  160.       if R.IsList then UpdateListView(R.List) else
  161.       begin
  162.         case R.ResType of
  163.           rtBitmap, rtIconEntry, rtCursorEntry:
  164.             begin
  165.               ImageViewer.Picture.Assign(R);
  166.               Notebook.PageIndex := 1;
  167.             end;
  168.           rtString, rtMenu:
  169.             begin
  170.               StringViewer.Lines.Assign(R);
  171.               StringViewer.SelStart := 0;
  172.               Notebook.PageIndex := 2;
  173.             end
  174.           else
  175.             begin
  176.               HexDump.Address := R.RawData;
  177.               HexDump.DataSize := R.Size;
  178.               Notebook.PageIndex := 3;
  179.             end;
  180.          end;
  181.       end;
  182.       UpdateStatusLine(R);
  183.     end;
  184.   end;
  185. end;
  186.  
  187. procedure TMainForm.UpdateListView(ResList: TResourceList);
  188. var
  189.   I: Integer;
  190. begin
  191.   ListView.Items.Clear;
  192.   for I := 0 to ResList.Count-1 do
  193.     with ResList[I], ListView.Items.Add do
  194.     begin
  195.       Data := ResList[I];
  196.       Caption := Name;
  197.       SubItems.Add(Format('%.7x', [Offset]));
  198.       SubItems.Add(Format('%.5x', [Size]));
  199.       ImageIndex := ImageMap[ResType];
  200.     end;
  201.   Notebook.PageIndex := 0;
  202. end;
  203.  
  204. procedure TMainForm.UpdateStatusLine(ResItem: TResourceItem);
  205. begin
  206.   if ResItem.IsList then
  207.   begin
  208.     ListViewCaption.Caption := ' '+TreeView.Selected.Text;
  209.     StatusBar.Panels[0].Text := Format(' %d object(s)', [ListView.Items.Count]);
  210.     StatusBar.Panels[1].Text := Format(' Offset: %x', [ResItem.Offset]);
  211.   end else
  212.   with ResItem do
  213.   begin
  214.     ListViewCaption.Caption := Format(' %s: %s', [ResTypeStr, Name]);
  215.     StatusBar.Panels[0].Text := '';
  216.     StatusBar.Panels[1].Text := Format(' Offset: %x  Size: %x', [Offset, Size]);
  217.   end;
  218. end;
  219.  
  220. { Form Initialization }
  221.  
  222. procedure TMainForm.FormCreate(Sender: TObject);
  223. begin
  224.   SplitControl := TSplitControl.Create(Self);
  225.   HexDump := CreateHexDump(TWinControl(NoteBook.Pages.Objects[3]));
  226.   FileOpenDialog.Filter := SOpenFilter;
  227.   FileSaveDialog.Filter := SSaveFilter;
  228.   Small.ResourceLoad(itBitmap, 'SmallImages', clOlive);
  229.   Large.ResourceLoad(itBitmap, 'LargeImages', clOlive);
  230.   Notebook.PageIndex := 0;
  231.   if (ParamCount > 0) and FileExists(ParamStr(1)) then
  232.   begin
  233.     Show;
  234.     FExeFile := TExeImage.CreateImage(Self, ParamStr(1));
  235.     DisplayResources;
  236.   end;
  237. end;
  238.  
  239. { Menu Event Handlers }
  240.  
  241. procedure TMainForm.FileOpen(Sender: TObject);
  242. var
  243.   TmpExeFile: TExeImage;
  244. begin
  245.   with FileOpenDialog do
  246.   begin
  247.     if not Execute then Exit;
  248.     TmpExeFile := TExeImage.CreateImage(Self, FileName);
  249.     if Assigned(FExeFile) then FExeFile.Destroy;
  250.     FExeFile := TmpExeFile;
  251.     DisplayResources;
  252.   end;
  253. end;
  254.  
  255. procedure TMainForm.FileExit(Sender: TObject);
  256. begin
  257.   Close;
  258. end;
  259.  
  260. procedure TMainForm.ListViewEnter(Sender: TObject);
  261. begin
  262.   with ListView do
  263.     if (Items.Count > 1) and (Selected = nil) then
  264.     begin
  265.       Selected := Items[0];
  266.       ItemFocused := Selected;
  267.     end;
  268. end;
  269.  
  270. procedure TMainForm.SaveResource(Sender: TObject);
  271. var
  272.   ResItem: TResourceitem;
  273.  
  274.   function TreeViewResourceSelected: Boolean;
  275.   begin
  276.     Result := Assigned(TreeView.Selected) and
  277.               Assigned(TreeView.Selected.Data) and
  278.               not TResourceItem(TreeView.Selected.Data).IsList;
  279.     if Result then ResItem := TResourceItem(TreeView.Selected.Data);
  280.   end;
  281.  
  282.   function ListViewResourceSelected: Boolean;
  283.   begin
  284.     Result := Assigned(ListView.Selected) and
  285.               Assigned(ListView.Selected.Data) and
  286.               not TResourceItem(ListView.Selected.Data).IsList;
  287.     if Result then ResItem := TResourceItem(ListView.Selected.Data);
  288.   end;
  289.  
  290. begin
  291.   if TreeViewResourceSelected or ListViewResourceSelected then
  292.   with FileSaveDialog do
  293.   begin
  294.     FilterIndex := ResFiltMap[ResItem.ResType];
  295.     if Execute then
  296.       ResItem.SaveToFile(FileName)
  297.   end
  298.   else
  299.     Error(SNoResSelected);
  300. end;
  301.  
  302. procedure TMainForm.SelectListViewType(Sender: TObject);
  303. begin
  304.   ListView.ViewStyle := TViewStyle(TComponent(Sender).Tag);
  305. end;
  306.  
  307. procedure TMainForm.ShowAboutBox(Sender: TObject);
  308. begin
  309.   About.ShowAboutBox;
  310. end;
  311.  
  312. procedure TMainForm.ToggleStatusBar(Sender: TObject);
  313. begin
  314.   StatusBar.Visible := not StatusBar.Visible;
  315. end;
  316.  
  317. procedure TMainForm.TreeViewChange(Sender: TObject; Node: TTreeNode);
  318. begin
  319.   UpdateViewPanel;
  320. end;
  321.  
  322. procedure TMainForm.ViewMenuDropDown(Sender: TObject);
  323. var
  324.   I: Integer;
  325. begin
  326.   miViewStatusBar.Checked := StatusBar.Visible;
  327.   for I := 0 to miView.Count-1 do
  328.     with miView.Items[I] do
  329.       if GroupIndex = 1 then
  330.         Checked := (Tag = Ord(ListView.ViewStyle));
  331. end;
  332.  
  333. procedure TMainForm.SplitterMouseDown(Sender: TObject;
  334.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  335. begin
  336.   if (Button = mbLeft) and (Shift = [ssLeft]) then
  337.     SplitControl.BeginSizing(Splitter, TreeViewPanel);
  338. end;
  339.  
  340. procedure TMainForm.SplitterMouseMove(Sender: TObject; Shift: TShiftState;
  341.   X, Y: Integer);
  342. begin
  343.   with SplitControl do if Sizing then ChangeSizing(X, Y);
  344. end;
  345.  
  346. procedure TMainForm.SplitterMouseUp(Sender: TObject; Button: TMouseButton;
  347.   Shift: TShiftState; X, Y: Integer);
  348. begin
  349.   with SplitControl do if Sizing then EndSizing;
  350. end;
  351.  
  352. procedure TMainForm.NotebookEnter(Sender: TObject);
  353. var
  354.   Page: TWinControl;
  355. begin
  356.   with NoteBook do
  357.   begin
  358.     Page := TWinControl(Pages.Objects[PageIndex]);
  359.     if (Page.ControlCount > 0) and (Page.Controls[0] is TWinControl) then
  360.       TWinControl(Page.Controls[0]).SetFocus;
  361.   end;
  362. end;
  363.  
  364. procedure TMainForm.FormDestroy(Sender: TObject);
  365. begin
  366.   SplitControl.Free;
  367. end;
  368.  
  369. end.
  370.