unit ResXChildForm;

interface

uses
  System.Drawing, System.Collections, System.ComponentModel,
  System.Windows.Forms, System.Data, System.Resources, System.IO,
  System.Runtime.InteropServices;

type
  TResXChildForm = class(System.Windows.Forms.Form)
  {$REGION 'Designer Managed Code'}
  strict private
    /// <summary>
    /// Required designer variable.
    /// </summary>
    Components: System.ComponentModel.Container;
    MainMenu1: System.Windows.Forms.MainMenu;
    mniFile: System.Windows.Forms.MenuItem;
    mniResources: System.Windows.Forms.MenuItem;
    mniSave: System.Windows.Forms.MenuItem;
    mniSaveAs: System.Windows.Forms.MenuItem;
    mniCursor: System.Windows.Forms.MenuItem;
    mniBitmap: System.Windows.Forms.MenuItem;
    mniIcon: System.Windows.Forms.MenuItem;
    mniBinary: System.Windows.Forms.MenuItem;
    StatusBar1: System.Windows.Forms.StatusBar;
    OpenFileDialog1: System.Windows.Forms.OpenFileDialog;
    ContextMenu1: System.Windows.Forms.ContextMenu;
    SaveFileDialog1: System.Windows.Forms.SaveFileDialog;
    Panel1: System.Windows.Forms.Panel;
    TreeView1: System.Windows.Forms.TreeView;
    Panel2: System.Windows.Forms.Panel;
    Label1: System.Windows.Forms.Label;
    PictureBox1: System.Windows.Forms.PictureBox;
    FFileName: string;
    FModified: Boolean;
    Splitter1: System.Windows.Forms.Splitter;
    MenuItem1: System.Windows.Forms.MenuItem;
    cmniRename: System.Windows.Forms.MenuItem;
    cmniDelete: System.Windows.Forms.MenuItem;
    MenuItem4: System.Windows.Forms.MenuItem;
    MenuItem2: System.Windows.Forms.MenuItem;
    mniExpand: System.Windows.Forms.MenuItem;
    mniCollapse: System.Windows.Forms.MenuItem;
    MenuItem3: System.Windows.Forms.MenuItem;
    MenuItem5: System.Windows.Forms.MenuItem;
    MenuItem6: System.Windows.Forms.MenuItem;
    MenuItem7: System.Windows.Forms.MenuItem;
    mniRename: System.Windows.Forms.MenuItem;
    mniDelete: System.Windows.Forms.MenuItem;
    mniOther: System.Windows.Forms.MenuItem;
    MenuItem9: System.Windows.Forms.MenuItem;
    MainPanel: System.Windows.Forms.StatusBarPanel;
    ModifiedPanel: System.Windows.Forms.StatusBarPanel;
    MenuItem8: System.Windows.Forms.MenuItem;
    MenuItem11: System.Windows.Forms.MenuItem;
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    procedure InitializeComponent;
    procedure mniIcon_Click(sender: System.Object; e: System.EventArgs);
    procedure mniBitmap_Click(sender: System.Object; e: System.EventArgs);
    procedure mniBinary_Click(sender: System.Object; e: System.EventArgs);
    procedure mniResources_Select(sender: System.Object; e: System.EventArgs);
    procedure mniRename_Click(sender: System.Object; e: System.EventArgs);
    procedure mniDelete_Click(sender: System.Object; e: System.EventArgs);
    procedure StatusBar1_Resize(sender: System.Object; e: System.EventArgs);
    procedure mniSave_Click(sender: System.Object; e: System.EventArgs);
    procedure mniSaveAs_Click(sender: System.Object; e: System.EventArgs);
    procedure TResXChildForm_Closing(sender: System.Object; e: System.ComponentModel.CancelEventArgs);
    procedure ContextMenu1_Popup(sender: System.Object; e: System.EventArgs);
    procedure mniCursor_Click(sender: System.Object; e: System.EventArgs);
    procedure TResXChildForm_Load(sender: System.Object; e: System.EventArgs);
    procedure TreeView1_AfterSelect(sender: System.Object; e: System.Windows.Forms.TreeViewEventArgs);
    procedure TreeView1_DragDrop(sender: System.Object; e: System.Windows.Forms.DragEventArgs);
    procedure TreeView1_DragEnter(sender: System.Object; e: System.Windows.Forms.DragEventArgs);
    procedure TreeView1_AfterLabelEdit(sender: System.Object; e: System.Windows.Forms.NodeLabelEditEventArgs);
    procedure TreeView1_BeforeLabelEdit(sender: System.Object; e: System.Windows.Forms.NodeLabelEditEventArgs);
   {$ENDREGION}
    function ItemNameExists(ItemName: string; Node: TreeNode): Boolean;
    function CreateUniqueName(ItemName: string; Node: TreeNode): string;
    procedure AddIcon(FileName: string);
    procedure AddCursor(FileName: string);
    procedure AddImage(FileName: string);
    procedure AddBinary(FileName: string);
    procedure TreeView1_KeyDown(sender: System.Object; e: System.Windows.Forms.KeyEventArgs);
    procedure mniExpand_Click(sender: System.Object; e: System.EventArgs);
    procedure mniCollapse_Click(sender: System.Object; e: System.EventArgs);
    procedure mniString_Click(sender: System.Object; e: System.EventArgs);
    procedure MenuItem8_Click(sender: System.Object; e: System.EventArgs);
  strict protected
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    procedure Dispose(Disposing: Boolean); override;
  public
    constructor Create;
    procedure OpenFile(FileName: string);
    procedure SaveFile;
    procedure SaveFileAs(FileName: string);
    procedure AddResource(ItemName: string; ItemType: System.Type; Value: TObject);
  end;

  [assembly: RuntimeRequiredAttribute(TypeOf(TResXChildForm))]

implementation

uses
  SysUtils,
  System.Globalization,
  System.Diagnostics,
  AddResForm;

const
  SModified = 'Modified';

type
  TBytes = array of System.Byte;

{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TResXChildForm.InitializeComponent;
type
  TSystem_Windows_Forms_MenuItemArray = array of System.Windows.Forms.MenuItem;
  TSystem_Windows_Forms_StatusBarPanelArray = array of System.Windows.Forms.StatusBarPanel;
var
  resources: System.Resources.ResourceManager;
begin
  resources := System.Resources.ResourceManager.Create(TypeOf(TResXChildForm));
  Self.MainMenu1 := System.Windows.Forms.MainMenu.Create;
  Self.mniFile := System.Windows.Forms.MenuItem.Create;
  Self.mniSave := System.Windows.Forms.MenuItem.Create;
  Self.mniSaveAs := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem8 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem11 := System.Windows.Forms.MenuItem.Create;
  Self.mniResources := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem1 := System.Windows.Forms.MenuItem.Create;
  Self.mniBitmap := System.Windows.Forms.MenuItem.Create;
  Self.mniIcon := System.Windows.Forms.MenuItem.Create;
  Self.mniCursor := System.Windows.Forms.MenuItem.Create;
  Self.mniBinary := System.Windows.Forms.MenuItem.Create;
  Self.mniOther := System.Windows.Forms.MenuItem.Create;
  Self.mniRename := System.Windows.Forms.MenuItem.Create;
  Self.mniDelete := System.Windows.Forms.MenuItem.Create;
  Self.cmniRename := System.Windows.Forms.MenuItem.Create;
  Self.cmniDelete := System.Windows.Forms.MenuItem.Create;
  Self.StatusBar1 := System.Windows.Forms.StatusBar.Create;
  Self.MainPanel := System.Windows.Forms.StatusBarPanel.Create;
  Self.ModifiedPanel := System.Windows.Forms.StatusBarPanel.Create;
  Self.OpenFileDialog1 := System.Windows.Forms.OpenFileDialog.Create;
  Self.ContextMenu1 := System.Windows.Forms.ContextMenu.Create;
  Self.MenuItem2 := System.Windows.Forms.MenuItem.Create;
  Self.mniExpand := System.Windows.Forms.MenuItem.Create;
  Self.mniCollapse := System.Windows.Forms.MenuItem.Create;
  Self.SaveFileDialog1 := System.Windows.Forms.SaveFileDialog.Create;
  Self.Panel1 := System.Windows.Forms.Panel.Create;
  Self.Panel2 := System.Windows.Forms.Panel.Create;
  Self.PictureBox1 := System.Windows.Forms.PictureBox.Create;
  Self.Splitter1 := System.Windows.Forms.Splitter.Create;
  Self.TreeView1 := System.Windows.Forms.TreeView.Create;
  Self.Label1 := System.Windows.Forms.Label.Create;
  Self.MenuItem4 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem3 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem5 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem6 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem7 := System.Windows.Forms.MenuItem.Create;
  Self.MenuItem9 := System.Windows.Forms.MenuItem.Create;
  (System.ComponentModel.ISupportInitialize(Self.MainPanel)).BeginInit;
  (System.ComponentModel.ISupportInitialize(Self.ModifiedPanel)).BeginInit;
  Self.Panel1.SuspendLayout;
  Self.Panel2.SuspendLayout;
  Self.SuspendLayout;
  // 
  // MainMenu1
  // 
  Self.MainMenu1.MenuItems.AddRange(TSystem_Windows_Forms_MenuItemArray.Create(Self.mniFile, 
          Self.mniResources));
  // 
  // mniFile
  // 
  Self.mniFile.Index := 0;
  Self.mniFile.MenuItems.AddRange(TSystem_Windows_Forms_MenuItemArray.Create(Self.mniSave, 
          Self.mniSaveAs, Self.MenuItem8, Self.MenuItem11));
  Self.mniFile.MergeType := System.Windows.Forms.MenuMerge.MergeItems;
  Self.mniFile.Text := '&File';
  // 
  // mniSave
  // 
  Self.mniSave.Index := 0;
  Self.mniSave.MergeOrder := 1;
  Self.mniSave.Text := '&Save';
  Include(Self.mniSave.Click, Self.mniSave_Click);
  // 
  // mniSaveAs
  // 
  Self.mniSaveAs.Index := 1;
  Self.mniSaveAs.MergeOrder := 1;
  Self.mniSaveAs.Text := 'Save &As...';
  Include(Self.mniSaveAs.Click, Self.mniSaveAs_Click);
  // 
  // MenuItem8
  // 
  Self.MenuItem8.Index := 2;
  Self.MenuItem8.MergeOrder := 1;
  Self.MenuItem8.Text := '&Compile';
  Include(Self.MenuItem8.Click, Self.MenuItem8_Click);
  // 
  // MenuItem11
  // 
  Self.MenuItem11.Index := 3;
  Self.MenuItem11.Text := '-';
  // 
  // mniResources
  // 
  Self.mniResources.Index := 1;
  Self.mniResources.MenuItems.AddRange(TSystem_Windows_Forms_MenuItemArray.Create(Self.MenuItem1, 
          Self.mniRename, Self.mniDelete));
  Self.mniResources.MergeOrder := 3;
  Self.mniResources.Text := '&Resources';
  Include(Self.mniResources.Select, Self.mniResources_Select);
  // 
  // MenuItem1
  // 
  Self.MenuItem1.Index := 0;
  Self.MenuItem1.MenuItems.AddRange(TSystem_Windows_Forms_MenuItemArray.Create(Self.mniBitmap, 
          Self.mniIcon, Self.mniCursor, Self.mniBinary, Self.mniOther));
  Self.MenuItem1.Text := '&Add';
  // 
  // mniBitmap
  // 
  Self.mniBitmap.Index := 0;
  Self.mniBitmap.Text := '&Bitmap...';
  Include(Self.mniBitmap.Click, Self.mniBitmap_Click);
  // 
  // mniIcon
  // 
  Self.mniIcon.Index := 1;
  Self.mniIcon.Text := '&Icon...';
  Include(Self.mniIcon.Click, Self.mniIcon_Click);
  // 
  // mniCursor
  // 
  Self.mniCursor.Index := 2;
  Self.mniCursor.Text := '&Cursor...';
  Include(Self.mniCursor.Click, Self.mniCursor_Click);
  // 
  // mniBinary
  // 
  Self.mniBinary.Index := 3;
  Self.mniBinary.Text := 'Binar&y...';
  Include(Self.mniBinary.Click, Self.mniBinary_Click);
  // 
  // mniOther
  // 
  Self.mniOther.Index := 4;
  Self.mniOther.Text := '&Other...';
  Include(Self.mniOther.Click, Self.mniString_Click);
  // 
  // mniRename
  // 
  Self.mniRename.Index := 1;
  Self.mniRename.Text := '&Rename';
  Include(Self.mniRename.Click, Self.mniRename_Click);
  // 
  // mniDelete
  // 
  Self.mniDelete.Index := 2;
  Self.mniDelete.Text := '&Delete';
  Include(Self.mniDelete.Click, Self.mniDelete_Click);
  // 
  // cmniRename
  // 
  Self.cmniRename.Index := 0;
  Self.cmniRename.Text := '&Rename';
  Include(Self.cmniRename.Click, Self.mniRename_Click);
  // 
  // cmniDelete
  // 
  Self.cmniDelete.Index := 1;
  Self.cmniDelete.Text := '&Delete';
  Include(Self.cmniDelete.Click, Self.mniDelete_Click);
  // 
  // StatusBar1
  // 
  Self.StatusBar1.Location := System.Drawing.Point.Create(0, 284);
  Self.StatusBar1.Name := 'StatusBar1';
  Self.StatusBar1.Panels.AddRange(TSystem_Windows_Forms_StatusBarPanelArray.Create(Self.MainPanel, 
          Self.ModifiedPanel));
  Self.StatusBar1.ShowPanels := True;
  Self.StatusBar1.Size := System.Drawing.Size.Create(472, 22);
  Self.StatusBar1.TabIndex := 0;
  Self.StatusBar1.Text := 'StatusBar1';
  Include(Self.StatusBar1.Resize, Self.StatusBar1_Resize);
  // 
  // MainPanel
  // 
  Self.MainPanel.Width := 350;
  // 
  // ContextMenu1
  // 
  Self.ContextMenu1.MenuItems.AddRange(TSystem_Windows_Forms_MenuItemArray.Create(Self.cmniRename, 
          Self.cmniDelete, Self.MenuItem2, Self.mniExpand, Self.mniCollapse));
  Include(Self.ContextMenu1.Popup, Self.ContextMenu1_Popup);
  // 
  // MenuItem2
  // 
  Self.MenuItem2.Index := 2;
  Self.MenuItem2.Text := '-';
  // 
  // mniExpand
  // 
  Self.mniExpand.Index := 3;
  Self.mniExpand.Text := '&Expand All...';
  Include(Self.mniExpand.Click, Self.mniExpand_Click);
  // 
  // mniCollapse
  // 
  Self.mniCollapse.Index := 4;
  Self.mniCollapse.Text := '&Collapse All...';
  Include(Self.mniCollapse.Click, Self.mniCollapse_Click);
  // 
  // Panel1
  // 
  Self.Panel1.Controls.Add(Self.Panel2);
  Self.Panel1.Dock := System.Windows.Forms.DockStyle.Fill;
  Self.Panel1.Location := System.Drawing.Point.Create(0, 0);
  Self.Panel1.Name := 'Panel1';
  Self.Panel1.Size := System.Drawing.Size.Create(472, 284);
  Self.Panel1.TabIndex := 1;
  // 
  // Panel2
  // 
  Self.Panel2.BorderStyle := System.Windows.Forms.BorderStyle.Fixed3D;
  Self.Panel2.Controls.Add(Self.PictureBox1);
  Self.Panel2.Controls.Add(Self.Splitter1);
  Self.Panel2.Controls.Add(Self.TreeView1);
  Self.Panel2.Controls.Add(Self.Label1);
  Self.Panel2.Dock := System.Windows.Forms.DockStyle.Fill;
  Self.Panel2.Location := System.Drawing.Point.Create(0, 0);
  Self.Panel2.Name := 'Panel2';
  Self.Panel2.Size := System.Drawing.Size.Create(472, 284);
  Self.Panel2.TabIndex := 1;
  // 
  // PictureBox1
  // 
  Self.PictureBox1.BackColor := System.Drawing.SystemColors.Info;
  Self.PictureBox1.Dock := System.Windows.Forms.DockStyle.Fill;
  Self.PictureBox1.Location := System.Drawing.Point.Create(195, 0);
  Self.PictureBox1.Name := 'PictureBox1';
  Self.PictureBox1.Size := System.Drawing.Size.Create(273, 280);
  Self.PictureBox1.SizeMode := System.Windows.Forms.PictureBoxSizeMode.CenterImage;
  Self.PictureBox1.TabIndex := 9;
  Self.PictureBox1.TabStop := False;
  // 
  // Splitter1
  // 
  Self.Splitter1.Location := System.Drawing.Point.Create(192, 0);
  Self.Splitter1.Name := 'Splitter1';
  Self.Splitter1.Size := System.Drawing.Size.Create(3, 280);
  Self.Splitter1.TabIndex := 8;
  Self.Splitter1.TabStop := False;
  // 
  // TreeView1
  // 
  Self.TreeView1.AllowDrop := True;
  Self.TreeView1.ContextMenu := Self.ContextMenu1;
  Self.TreeView1.Dock := System.Windows.Forms.DockStyle.Left;
  Self.TreeView1.HotTracking := True;
  Self.TreeView1.ImageIndex := -1;
  Self.TreeView1.LabelEdit := True;
  Self.TreeView1.Location := System.Drawing.Point.Create(0, 0);
  Self.TreeView1.Name := 'TreeView1';
  Self.TreeView1.SelectedImageIndex := -1;
  Self.TreeView1.Size := System.Drawing.Size.Create(192, 280);
  Self.TreeView1.TabIndex := 7;
  Include(Self.TreeView1.KeyDown, Self.TreeView1_KeyDown);
  Include(Self.TreeView1.AfterSelect, Self.TreeView1_AfterSelect);
  Include(Self.TreeView1.AfterLabelEdit, Self.TreeView1_AfterLabelEdit);
  Include(Self.TreeView1.DragEnter, Self.TreeView1_DragEnter);
  Include(Self.TreeView1.BeforeLabelEdit, Self.TreeView1_BeforeLabelEdit);
  Include(Self.TreeView1.DragDrop, Self.TreeView1_DragDrop);
  // 
  // Label1
  // 
  Self.Label1.BackColor := System.Drawing.SystemColors.Info;
  Self.Label1.Location := System.Drawing.Point.Create(296, 120);
  Self.Label1.Name := 'Label1';
  Self.Label1.Size := System.Drawing.Size.Create(100, 100);
  Self.Label1.TabIndex := 0;
  // 
  // MenuItem4
  // 
  Self.MenuItem4.Index := -1;
  Self.MenuItem4.Text := 'sdsd';
  // 
  // MenuItem3
  // 
  Self.MenuItem3.Index := -1;
  Self.MenuItem3.Text := '&Rename';
  Include(Self.MenuItem3.Click, Self.mniRename_Click);
  // 
  // MenuItem5
  // 
  Self.MenuItem5.Index := -1;
  Self.MenuItem5.Text := '&Delete';
  Include(Self.MenuItem5.Click, Self.mniDelete_Click);
  // 
  // MenuItem6
  // 
  Self.MenuItem6.Index := -1;
  Self.MenuItem6.Text := '&Rename';
  // 
  // MenuItem7
  // 
  Self.MenuItem7.Index := -1;
  Self.MenuItem7.Text := '&Delete';
  // 
  // MenuItem9
  // 
  Self.MenuItem9.Index := -1;
  Self.MenuItem9.Text := '&Add';
  // 
  // TResXChildForm
  // 
  Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
  Self.ClientSize := System.Drawing.Size.Create(472, 306);
  Self.Controls.Add(Self.Panel1);
  Self.Controls.Add(Self.StatusBar1);
  Self.Icon := (System.Drawing.Icon(resources.GetObject('$this.Icon')));
  Self.Menu := Self.MainMenu1;
  Self.Name := 'TResXChildForm';
  Self.Text := 'WinForm';
  Include(Self.Closing, Self.TResXChildForm_Closing);
  Include(Self.Load, Self.TResXChildForm_Load);
  (System.ComponentModel.ISupportInitialize(Self.MainPanel)).EndInit;
  (System.ComponentModel.ISupportInitialize(Self.ModifiedPanel)).EndInit;
  Self.Panel1.ResumeLayout(False);
  Self.Panel2.ResumeLayout(False);
  Self.ResumeLayout(False);
end;
{$ENDREGION}

procedure TResXChildForm.Dispose(Disposing: Boolean);
begin
  if Disposing then
  begin
    if Components <> nil then
      Components.Dispose();
  end;
  inherited Dispose(Disposing);
end;

constructor TResXChildForm.Create;
begin
  inherited Create;
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent;
  Text := 'Untitled';
  FFileName := '';
  FModified := False;
end;

procedure TResXChildForm.OpenFile(FileName: string);
var
  Reader: System.Resources.ResXResourceReader;
  ResList: IDictionaryEnumerator;
begin
  FFileName := FileName;
  Text := System.IO.Path.GetFileName(FFileName);

  Reader := ResXResourceReader.Create(FileName);
  ResList := Reader.GetEnumerator;

  while (resList.MoveNext) do
    AddResource(resList.Key.ToString, resList.Value.GetType, resList.Value);
end;

procedure TResXChildForm.SaveFileAs(FileName: string);
var
  ParentList, NodeList: IEnumerator;
  Node: TreeNode;
  Writer: ResXResourceWriter;
begin
  Writer := ResXResourceWriter.Create(FileName);
  ParentList := TreeView1.Nodes.GetEnumerator;

  while ParentList.MoveNext do
  begin
    NodeList := TreeNode(ParentList.Current).Nodes.GetEnumerator;
    while NodeList.MoveNext do
    begin
      Node := TreeNode(NodeList.Current);
      if Node.Tag <> nil then
        Writer.AddResource(Node.Text, Node.Tag);
    end;
  end;

  Writer.Close;
  FFileName := FileName;
  Text := System.IO.Path.GetFileName(FFileName);
  FModified := False;
  ModifiedPanel.Text := '';
end;

procedure TResXChildForm.mniString_Click(sender: System.Object; e: System.EventArgs);
var
  AddRes: TAddResForm;
begin
  AddRes := TAddResForm.Create(Self);
  AddRes.ShowDialog;

  if AddRes.DialogResult = System.Windows.Forms.DialogResult.OK then
    FModified := True;
    
  AddRes.Dispose;
end;

procedure TResXChildForm.mniCollapse_Click(sender: System.Object; e: System.EventArgs);
begin
  TreeView1.CollapseAll;
end;

procedure TResXChildForm.mniExpand_Click(sender: System.Object; e: System.EventArgs);
begin
  TreeView1.ExpandAll;
end;

procedure TResXChildForm.TreeView1_KeyDown(sender: System.Object; e: System.Windows.Forms.KeyEventArgs);
begin
  if e.KeyCode = Keys.Delete then
    mniDelete_Click(sender, e);
end;

procedure TResXChildForm.AddIcon(FileName: string);
var
  ErrorMessage, ResName: string;
  aIcon: System.Drawing.Icon;
begin
  ErrorMessage := 'Unable to add icon ''%s''.';
  
  ResName := System.IO.Path.GetFileName(FileName);
  try
    aIcon := System.Drawing.Icon.Create(FileName);
    AddResource(ResName, aIcon.GetType, aIcon);
  except
    ErrorMessage := ErrorMessage.Replace('%s', FileName);
    MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
  end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.AddCursor(FileName: string);
var
  ErrorMessage, ResName: string;
  aCursor: System.Windows.Forms.Cursor;
begin
  ErrorMessage := 'Unable to add cursor ''%s''.';

  ResName := System.IO.Path.GetFileName(FileName);
  try
    aCursor := System.Windows.Forms.Cursor.Create(FileName);
    AddResource(resName, aCursor.GetType, aCursor);
  except
    ErrorMessage := ErrorMessage.Replace('%s', FileName);
    MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
  end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.AddImage(FileName: string);
var
  ErrorMessage, ResName: string;
  aImage: System.Drawing.Image;
begin
  ErrorMessage := 'Unable to add image ''%s''.';

  ResName := System.IO.Path.GetFileName(FileName);
  try
    aImage := System.Drawing.Image.FromFile(FileName);
    AddResource(ResName, aImage.GetType, aImage);
  except
    ErrorMessage := ErrorMessage.Replace('%s', FileName);
    MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
  end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.AddBinary(FileName: string);
var
  ErrorMessage, ResName: string;
  Stream: FileStream;
  Buffer: array of Byte;
begin
  ErrorMessage := 'Unable to add resource ''%s''.';

  ResName := System.IO.Path.GetFileName(FileName);
  try
    Stream := FileStream.Create(FileName, FileMode.Open, FileAccess.Read);
    SetLength(Buffer, Stream.Length);
    Stream.Read(Buffer, 0, Length(Buffer));
    AddResource(ResName, TypeOf(Buffer), AnsiString(Buffer));
  except
    ErrorMessage := ErrorMessage.Replace('%s', FileName);
    MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
  end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.TreeView1_DragEnter(sender: System.Object; e: System.Windows.Forms.DragEventArgs);
begin
  // Make sure they're actually dropping files (not text or anything else).
  if( e.Data.GetDataPresent(DataFormats.FileDrop, false) = true ) then
  // Allow them to continue (without this, the cursor stays a "NO" symbol
    e.Effect := DragDropEffects.All;
end;

procedure TResXChildForm.TreeView1_DragDrop(sender: System.Object; e: System.Windows.Forms.DragEventArgs);
type
  TArrayString = array of string;
var
  files: TArrayString;
  i: Integer;
const
  Extensions: array[0..4] of string = ('.ico','.cur','.bmp','.png','.jpg');

  function GetExtType(ext: string): Integer;
  var
    i: Integer;
  begin
    Result := -1;

    for i:= 0 to Length(Extensions) -1 do
      if ext = Extensions[i] then
      begin
        Result := i;
        Break;
      end;
  end;

begin
  // Transfer the filenames to a string array
  // (yes, everything to the left of the "=" can be put in the
  // foreach loop in place of "files", but this is easier to understand.)
  files := TArrayString(e.Data.GetData(DataFormats.FileDrop));

  for i:= 0 to Length(files) -1 do
  begin
    case GetExtType(System.IO.Path.GetExtension(files[i])) of
      0: AddIcon(files[i]);
      1: AddCursor(files[i]);
      2..4: AddImage(files[i]);
    else
      AddBinary(files[i]);
    end;
  end;

end;

procedure TResXChildForm.TResXChildForm_Load(sender: System.Object;
  e: System.EventArgs);
begin
  Label1.Dock := DockStyle.Fill;
  PictureBox1.Dock := DockStyle.Fill;
end;

procedure TResXChildForm.ContextMenu1_Popup(sender: System.Object;
  e: System.EventArgs);
begin
  cmniDelete.Enabled := TreeView1.SelectedNode <> nil;

  cmniRename.Enabled :=
    (TreeView1.SelectedNode <> nil) and (TreeView1.SelectedNode.Tag <> nil);
end;

procedure TResXChildForm.TreeView1_AfterLabelEdit(sender: System.Object;
  e: System.Windows.Forms.NodeLabelEditEventArgs);
begin
  if e.&Label <> '' then
  begin
    FModified := not itemNameExists(e.&Label, TreeView1.SelectedNode.Parent);
    if not FModified then
    begin
      MessageBox.Show('Resource name already exists.', 'Error',
        MessageBoxButtons.OK, MessageBoxIcon.Error);
        e.CancelEdit := True;
    end
    else
      ModifiedPanel.Text := SModified;
  end;
end;

procedure TResXChildForm.TResXChildForm_Closing(sender: System.Object;
  e: System.ComponentModel.CancelEventArgs);
var
  Result: System.Windows.Forms.DialogResult;
begin
  if FModified then
  begin
    Result := MessageBox.Show(System.String.Format('Save changes to {0}?', Text),
      'Confirm', MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

    case result of
      System.Windows.Forms.DialogResult.No: Exit;
      System.Windows.Forms.DialogResult.Cancel: e.Cancel := True;
    end;
    mniSave_Click(nil, nil);
    e.Cancel := FModified;
  end;
end;

procedure TResXChildForm.mniSaveAs_Click(sender: System.Object;
  e: System.EventArgs);
begin
  SaveFileDialog1.FileName := '';
  SaveFileDialog1.Filter := 'Resources (*.resx)|*.resx|All Files (*.*)|*.*';
  SaveFileDialog1.DefaultExt := 'resx';

  SaveFileDialog1.FileName := '';
  if SaveFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK then
    SaveFileAs(saveFileDialog1.FileName);

  ModifiedPanel.Text := '';
end;

procedure TResXChildForm.mniSave_Click(sender: System.Object;
  e: System.EventArgs);
begin
  if FFileName = '' then
    mniSaveAs_Click(sender, e)
  else
    SaveFile();
end;

procedure TResXChildForm.StatusBar1_Resize(sender: System.Object;
  e: System.EventArgs);
begin
  MainPanel.Width := StatusBar1.Width;
end;

procedure TResXChildForm.mniDelete_Click(sender: System.Object;
  e: System.EventArgs);
var
  Msg, DeleteItem, DeleteGroup: string;
  Result: System.Windows.Forms.DialogResult;
  TagType: System.Type;
  Node: TreeNode;
begin
  DeleteItem := 'Are you sure you want to delete the resource ''%s''?';
  DeleteGroup := 'Are you sure you want to delete all resources of type ''%s''?';
  Node := TreeView1.SelectedNode;

  if Node.Tag = nil then
    Msg := DeleteGroup.Replace('%s', Node.Text)
  else
    Msg := DeleteItem.Replace('%s', Node.Text);

  Result := MessageBox.Show(Msg, 'Delete Resource', MessageBoxButtons.YesNo);
  if Result = System.Windows.Forms.DialogResult.Yes then
  begin
    Node.Remove;
    TagType := Node.Tag.GetType;
    if not TagType.IsSubclassOf(TypeOf(System.Drawing.Image)) then
      Label1.Text := '';

    Node := TreeView1.SelectedNode;

    if Node <> nil then
    begin
      if Node.Tag = nil then
      begin
        if Node.Nodes.Count = 0 then
        begin
          MainPanel.Text := '';
          Node.Remove;
        end;
      end
      else
        TreeView1_AfterSelect(TreeView1, nil);
    end;
    
  end;
  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.TreeView1_BeforeLabelEdit(sender: System.Object;
  e: System.Windows.Forms.NodeLabelEditEventArgs);
begin
  if e.Node.Tag = nil then
    e.CancelEdit := True;
end;

procedure TResXChildForm.mniRename_Click(sender: System.Object;
  e: System.EventArgs);
begin
  TreeView1.SelectedNode.BeginEdit;
end;

procedure TResXChildForm.mniResources_Select(sender: System.Object;
  e: System.EventArgs);
begin
  mniDelete.Enabled := TreeView1.SelectedNode <> nil;
  mniRename.Enabled := (TreeView1.SelectedNode <> nil) and (TreeView1.SelectedNode.Tag <> nil);
end;

procedure TResXChildForm.mniBinary_Click(sender: System.Object;
  e: System.EventArgs);
var
  i: Integer;
  ErrorMessage, ResName: string;
  Stream: FileStream;
  Buffer: array of Byte;
begin
  ErrorMessage := 'Unable to add resource ''%s''.';

  OpenFileDialog1.FileName := '';
  OpenFileDialog1.Filter := 'All Files (*.*)|*.*';
  OpenFileDialog1.DefaultExt := '';

  if OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK then
    for i := 0 to Length(OpenFileDialog1.FileNames) - 1 do
    begin
      ResName := System.IO.Path.GetFileName(OpenFileDialog1.FileNames[i]);
      try
        Stream := FileStream.Create(OpenFileDialog1.FileNames[i], FileMode.Open, FileAccess.Read);
        SetLength(Buffer, Stream.Length);

        Stream.Read(Buffer, 0, Length(Buffer));
        AddResource(ResName, TypeOf(Buffer), Buffer);
      except
        ErrorMessage := ErrorMessage.Replace('%s', OpenFileDialog1.FileNames[i]);
        MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
      end;
    end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.mniBitmap_Click(sender: System.Object;
  e: System.EventArgs);
var
  i: Integer;
  ErrorMessage, ResName: string;
  aImage: System.Drawing.Image;
begin
  ErrorMessage := 'Unable to add image ''%s''.';

  OpenFileDialog1.FileName := '';
  OpenFileDialog1.Filter := 'Images (*.bmp;*.png;*.jpg)|*.bmp;*.png;*.jpg|All Files (*.*)|*.*';
  OpenFileDialog1.DefaultExt := 'bmp';

  if OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK then
    for i := 0 to Length(OpenFileDialog1.FileNames) - 1 do
    begin
      ResName := System.IO.Path.GetFileName(OpenFileDialog1.FileNames[i]);
      try
        aImage := System.Drawing.Image.FromFile(OpenFileDialog1.FileNames[i]);
        AddResource(ResName, aImage.GetType, aImage);
      except
        ErrorMessage := ErrorMessage.Replace('%s', OpenFileDialog1.FileNames[i]);
        MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
      end;
    end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.mniIcon_Click(sender: System.Object;
  e: System.EventArgs);
var
  i: Integer;
  ErrorMessage, ResName: string;
  aIcon: System.Drawing.Icon;
begin
  ErrorMessage := 'Unable to add icon ''%s''.';

  OpenFileDialog1.FileName := '';
  OpenFileDialog1.Filter := 'Icons (*.ico)|*.ico|All Files (*.*)|*.*';
  OpenFileDialog1.DefaultExt := 'ico';

  if OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK then
    for i := 0 to Length(OpenFileDialog1.FileNames) - 1 do
    begin
      ResName := System.IO.Path.GetFileName(OpenFileDialog1.FileNames[i]);
      try
        aIcon := System.Drawing.Icon.Create(OpenFileDialog1.FileNames[i]);
        AddResource(ResName, aIcon.GetType, aIcon);
      except
        ErrorMessage := ErrorMessage.Replace('%s', OpenFileDialog1.FileNames[i]);
        MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
      end;
    end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.mniCursor_Click(sender: System.Object; e: System.EventArgs);
var
  i: Integer;
  ErrorMessage, ResName: string;
  aCursor: System.Windows.Forms.Cursor;
begin
  ErrorMessage := 'Unable to add cursor ''%s''.';

  OpenFileDialog1.FileName := '';
  OpenFileDialog1.Filter := 'Cursors (*.cur)|*.cur|All Files (*.*)|*.*';
  OpenFileDialog1.DefaultExt := 'cur';

  if OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK then
    for i := 0 to Length(OpenFileDialog1.FileNames) - 1 do
    begin
      ResName := System.IO.Path.GetFileName(OpenFileDialog1.FileNames[i]);
      try
        aCursor := System.Windows.Forms.Cursor.Create(OpenFileDialog1.FileNames[i]);
        AddResource(resName, aCursor.GetType, aCursor);
      except
        ErrorMessage := ErrorMessage.Replace('%s', OpenFileDialog1.FileNames[i]);
        MessageBox.Show(ErrorMessage, 'Error', MessageBoxButtons.OK);
      end;
    end;

  FModified := True;
  ModifiedPanel.Text := SModified;
end;

procedure TResXChildForm.TreeView1_AfterSelect(sender: System.Object;
  e: System.Windows.Forms.TreeViewEventArgs);
var
  Node: TreeNode;
  TagType: System.Type;
  TypeName, Format: string;
  g: Graphics;
  c: System.Windows.Forms.Cursor;
begin
  PictureBox1.Image := nil;
  Node := TreeView(Sender).SelectedNode;
  Format := '{0}, {1}';

  if (node <> nil) then
  begin
    if (node.Tag <> nil) then
    begin
      MainPanel.Text := '';
      TagType := Node.Tag.GetType;

      if TagType.IsSubclassOf(TypeOf(System.Drawing.Image)) then
      begin
        PictureBox1.Image := System.Drawing.Bitmap(Node.Tag);
        PictureBox1.BringToFront;
        MainPanel.Text :=
          System.String.Format(Format, TObject('Name = ' + Node.Text),
            TObject('Type = System.Drawing.Image'));
        Exit;
      end
      else if TagType = TypeOf(System.Drawing.Icon) then
      begin
        PictureBox1.Image := System.Drawing.Icon(Node.Tag).ToBitmap;
        PictureBox1.BringToFront;
        MainPanel.Text :=
          System.String.Format(Format, TObject('Name = ' + Node.Text),
            TObject('Type = System.Drawing.Icon'));
        Exit;
      end
      else if TagType = (typeof(System.Windows.Forms.Cursor)) then
      begin
        PictureBox1.Image := Bitmap.Create(
          System.Windows.Forms.Cursor(Node.Tag).Size.Width,
          System.Windows.Forms.Cursor(Node.Tag).Size.Height);

        g := Graphics.FromImage(PictureBox1.Image);
        c := System.Windows.Forms.Cursor(Node.Tag);
        c.Draw(g, PictureBox1.ClientRectangle);

        PictureBox1.BringToFront;

        MainPanel.Text :=
          System.String.Format(Format, TObject('Name = ' + Node.Text),
            TObject('Type = System.Windows.Forms.Cursor'));
        Exit;
      end
      else if TagType = (typeof(TBytes)) then
      begin
        Label1.TextAlign := ContentAlignment.TopLeft;
        Label1.Text := StringOf(TBytes(Node.Tag));

        MainPanel.Text :=
          System.String.Format(Format, TObject('Name = ' + Node.Text),
            TObject('Type = System.Byte[]'));

        Label1.BringToFront;
        Exit;
      end
      else
      begin
        // All other types...
        Label1.TextAlign := ContentAlignment.MiddleCenter;
        TypeName := Node.Tag.ToString;

        if TypeName <> TagType.ToString then
          Label1.Text := TypeName
        else
          Label1.Text := TagType.ToString;

        Label1.BringToFront;

        MainPanel.Text :=
          System.String.Format(Format, TObject('Name = ' + Node.Text),
            TObject('Value = ' + TypeName));
      end;
    end
    else
    begin
      Format := '{0}: {1} item(s)';
      MainPanel.Text :=
        System.String.Format(Format, TObject(Node.Text), TObject(Node.Nodes.Count));
    end;
  end;
end;

procedure TResXChildForm.SaveFile;
begin
  SaveFileAs(FFileName);
end;

function TResXChildForm.ItemNameExists(ItemName: string; Node: TreeNode): Boolean;
var
  i: Integer;
begin
  for i := 0 to Node.Nodes.Count - 1 do
    if (Node.Nodes[i].Text = ItemName) then
    begin
      Result := True;
      Exit;
    end;
  Result := False;
end;

function TResXChildForm.CreateUniqueName(ItemName: string; Node: TreeNode): string;
var
  i, j: Integer;
  Format, ext, temp: string;
begin
  if ItemNameExists(ItemName, Node) then
  begin
    i := 1;

    Format := '{0}_{1}';
    ext := '';

    j := System.String(ItemName).LastIndexOf('.');
    if j <> -1 then
    begin
      temp := System.String(ItemName).Substring(0, j);
      ext := System.String(ItemName).Substring(j);
    end;

    while ItemNameExists(System.String.Format(Format, TObject(temp),
      TObject(i.ToString + ext)), Node) do
      Inc(i);

    Result := System.String.Format(Format, TObject(temp), TObject(i.ToString + ext));
  end
  else
    Result := ItemName;
end;

procedure TResXChildForm.AddResource(ItemName: string; ItemType: System.Type; Value: TObject);
var
  node: TreeNode;
  nodeList: IEnumerator;
begin
  node := nil;
  nodeList := treeView1.Nodes.GetEnumerator;

  while (nodeList.MoveNext) do
    if (TreeNode(nodeList.Current).Text = ItemType.ToString) then
      node := TreeNode(nodeList.Current);

  if (node = nil) then
  begin
    node := treeView1.Nodes.Add(itemType.ToString());
    node := node.Nodes.Add(itemName);
  end
  else
    node := node.Nodes.Add(createUniqueName(ItemName, node));

  Node.Tag := Value;
end;

procedure TResXChildForm.MenuItem8_Click(sender: System.Object; e: System.EventArgs);
var
  node: TreeNode;
  nodeList: IEnumerator;
  rw: ResourceWriter;
  temp: string;
  i: Integer;
begin
  node := nil;
  nodeList := treeView1.Nodes.GetEnumerator;

  temp := System.IO.Path.ChangeExtension(FFileName, '.resources');
  rw := ResourceWriter.Create(temp);

  while (nodeList.MoveNext) do
  begin
     node := TreeNode(nodeList.Current);
     for i:= 0 to node.Nodes.Count - 1 do
       rw.AddResource(node.Nodes[i].Text,node.Nodes[i].Tag);
  end;
  rw.Close;
end;

end.
