Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Drawing, moving, and resizing boxes on an image 1

Status
Not open for further replies.

djjd47130

Programmer
Nov 1, 2010
480
US
I have a little project I'm working on in Delphi 7, and I got to a point where I'm stumped how to continue. The full source to just this project is below, but this project is using a set of components for parsing HTML: however, with how I have this, you can ignore and remove these components, and in the procedure where I do the parsing, you can replace it with adding a few fake values (ignoring the HTML all together). That procedure is towards the end (called cmdParseClick).

The project's concept is fairly simple, it's an editor for HTML image maps. It consists of two main parts: HTML Editor, and Image Editor. The HTML Editor is only holding the relevant block of HTML code for the map and image, whereas the image editor is showing the image with the ability to draw, move, and resize each 'hotspot' area on the image. The image and the back-end array of hotspot records should be directly synchronized with each other.

My problem is figuring out how to recognize when the user is trying to resize one of the boxes on the image. I have it to the point where I can recognize where the user is pointing the mouse on the image, and changing the cursor accordingly. So here's the sequence of what is already working:

1) Load image into back-end image (fImgMain) where original image is always maintained.
2) Copy image to back-end temp image (fImgTemp) where temporary drawing is done to image before display
3) Copy image to TImage component from the temp image to display the image with the drawn areas
4) Paste or write HTML code for an image map (<map>, <area>, and <img> tags involved)
5) Parse HTML and build a virtual list of these 'hotspots' - or "array of THotspot" records
6) Copy main image to temp image
7) Go through the virtual list and draw each box on the temp image
8) Copy temp image with drawn boxes to the image display
9) Recognize when user points mouse over certain areas of image
10) Change cursor of image if mouse is over hotspot (to move), the edge (to resize), or no hotspot (to draw new hotspot)

And at this point, how to actually accept user's mouse actions is way over my head.

Now when an area is being moved or resized (while mouse is down), the changes on the image need to be updated in the corresponding record in the array. Meaning, as long as user is moving mouse while mouse button is down, any change is recorded in the virtual list of records. After each movement of the mouse in this case, it needs to a) update the record in the array, b) copy main image over to temp image, c) draw new boxes on temp image, and d) copy temp image to image display.

At no point shall the main image (fImgMain) ever be changed or drawn to (unless a new image is loaded).

Note the type "TMouseDownState" which is a record to recognize what action is to be done while the mouse is down (moving hotspot, resizing left edge, resizing bottom-right edge, etc.). Two important functions are "HotspotAtCursor" and "MouseStateAtCursor" which recognize the position of the mouse over the display image (Img: TImage).

The project is simple, just 1 main form only. I tried to put as many comments as possible. Here's the code:

Code:
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, XPMan, ExtCtrls, Jpeg, ExtDlgs, Menus, Buttons,
  DIUnicode, DIHtmlParser;
     
const
  //GripSize = size of resizable border around each hotspot
  GripSize = 3;

type
  //Represents one single 'hotspot' or 'area' on the 'map'
  THotspot = record
    Area: TRect;
    URL: String;
    Shape: String;
  end;

  //Represents current mouse status of a hotspot
  TMouseHotspot = record
    Hotspot: THotspot;
    Active: Bool;
    DownPos: TPoint;
    UpPos: TPoint;
    CurrPos: TPoint;
  end;

  //Primary storage of all hotspot records
  THotspots = array of THotspot;

  //Represents what mouse is doing if mouse button is down
  TMouseDownState = (msNone, msMove, msSizeW, msSizeN, msSizeE, msSizeS,
    msSizeNW, msSizeNE, msSizeSW, msSizeSE);

  TForm1 = class(TForm)
    HParser: TDIHtmlParser;
    dlgOpen: TOpenPictureDialog;
    pRight: TPanel;
    Tags: TMemo;
    Splitter1: TSplitter;
    pMain: TPanel;
    pHTML: TPanel;
    HTML: TMemo;
    pImage: TPanel;
    Box: TScrollBox;
    Img: TImage;
    Splitter2: TSplitter;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    New1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    SaveAs1: TMenuItem;
    Close1: TMenuItem;
    N1: TMenuItem;
    Exit1: TMenuItem;
    Edit1: TMenuItem;
    Cut1: TMenuItem;
    Copy1: TMenuItem;
    Paste1: TMenuItem;
    View1: TMenuItem;
    Image1: TMenuItem;
    HTML1: TMenuItem;
    HotspotImage1: TMenuItem;
    cmdParse: TBitBtn;
    procedure cmdParseClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ImgMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ImgMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImgMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Exit1Click(Sender: TObject);
    procedure Close1Click(Sender: TObject);
  private
    fImgMain: TBitmap;
    fImgTemp: TBitmap;  
    fHotspots: THotspots;
    fMouseDownState: TMouseDownState;
    fSelHotspot: Integer;
    fPosDown: TPoint;
    function GetHotspot(Index: Integer): THotspot;
    procedure SetHotspot(Index: Integer; const Value: THotspot);
    procedure DrawHotspot(const H: THotspot);
    procedure CodeToImage;
    procedure ImageToCode;
  public
    function LoadFile(const Filename: TFilename): Bool;
    procedure CloseFile;
    function HotspotAtCursor: TMouseHotspot;
    function MouseStateAtCursor: TMouseDownState;
    property MouseDownState: TMouseDownState read fMouseDownState;
    property SelHotspot: Integer read fSelHotspot;
    property Hotspots[Index: Integer]: THotspot read GetHotspot write SetHotspot;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//Draws a single hotspot to the temporary bitmap
procedure TForm1.DrawHotspot(const H: THotspot);
var
  C: TCanvas;
begin
  C:= fImgTemp.Canvas;
  C.Brush.Style:= bsClear;
  C.Pen.Style:= psSolid;
  C.Pen.Color:= clGray;
  C.Pen.Width:= 2;
  C.Rectangle(H.Area);
end;

//Acquires a single hotspot from global list by index
function TForm1.GetHotspot(Index: Integer): THotspot;
begin
  Result:= fHotspots[Index];
end;

//Assigns a single hotspot in global list by index
procedure TForm1.SetHotspot(Index: Integer; const Value: THotspot);
begin
  fHotspots[Index]:= Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //Create objects
  fImgMain:= TBitmap.Create;
  fImgTemp:= TBitmap.Create;
  //Set default values
  SetLength(fHotspots, 0);
  fSelHotspot:= -1;
  fMouseDownState:= msNone;
  //Prepare controls
  pMain.Align:= alClient;
  pImage.Align:= alClient;
  HTML.Align:= alClient;
  Box.Align:= alClient;
  //Forcefully show main form
  Show;
  BringToFront;
  Application.ProcessMessages;
  //Automatically prompt to open an image (not necessary)
  if dlgOpen.Execute then begin
    LoadFile(dlgOpen.FileName);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  //Free objects
  fImgMain.Free;
  fImgTemp.Free;
end;

//Loads a single image file to be primary image to work with
function TForm1.LoadFile(const Filename: TFilename): Bool;
var
  Ext: String;
  J: TJpegImage;
begin
  Result:= False;
  if FileExists(Filename) then begin
    Ext:= LowerCase(ExtractFileExt(Filename));
    if (Ext = '.jpg') or (Ext = '.jpeg') then begin
      J:= TJpegImage.Create;
      try
        J.LoadFromFile(Filename);
        fImgMain.Assign(J);
        Result:= True;
      finally
        J.Free;
      end;
    end else
    if (Ext = '.bmp') then begin
      fImgMain.LoadFromFile(Filename);
      Result:= True;
    end else begin
      raise Exception.Create('Invalid file format "'+Ext+'"');
    end;
  end;
  if Result then begin
    fImgTemp.Assign(fImgMain);
    Img.Picture.Assign(fImgMain);
  end;
end;

//Closes the currently opened file
procedure TForm1.CloseFile;
begin

end;

//Detect mouse movement on image
procedure TForm1.ImgMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  H: TMouseHotspot;
begin
  //Identify current mouse state
  case Self.fMouseDownState of
    msNone: begin
      //Mouse button is NOT down - change cursor
      H:= HotspotAtCursor;
      if H.Active then begin
        //Mouse is over a hotspot
        case MouseStateAtCursor of
          msMove: Img.Cursor:= crSizeAll;
          msSizeN, msSizeS: Img.Cursor:= crSizeNS;
          msSizeW, msSizeE: Img.Cursor:= crSizeWE;
          msSizeNW, msSizeSE: Img.Cursor:= crSizeNWSE;
          msSizeSW, msSizeNE: Img.Cursor:= crSizeNESW;
        end;
      end else begin
        //Mouse is NOT over a hotspot
        Img.Cursor:= crCross;
      end;
    end;
    //The following events update Rect values within fHotspots
    //  With these, the mouse button IS down
    msMove: begin
      //Mouse is moving selected hotspot

    end;
    msSizeW: begin
      //Mouse is sizing left side of hotspot

    end;
    msSizeN: begin
      //Mouse is sizing top side of hotspot

    end;
    msSizeE: begin
      //Mouse is sizing right side of hotspot

    end;
    msSizeS: begin
      //Mouse is sizing bottom side of hotspot
      
    end;
    msSizeNW: begin
      //Mouse is sizing top-left corner of hotspot

    end;
    msSizeNE: begin
      //Mouse is sizing top-right corner of hotspot

    end;
    msSizeSW: begin
      //Mouse is sizing bottom-left corner of hotspot

    end;
    msSizeSE: begin
      //Mouse is sizing bottom-right corner of hotspot
      
    end;
  end;
end;

procedure TForm1.ImgMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  H: TMouseHotspot;
begin
  fPosDown:= Point(X, Y); //Record current mouse position for calculations
  H:= HotspotAtCursor;
  if H.Active then begin
    //Mouse clicked on a hotspot
    fMouseDownState:= MouseStateAtCursor; //Record what mouse is doing
    //Record currently active hotspot

  end else begin
    //Mouse clicked where there is no hotspot - draw new?
  end;
end;
     
procedure TForm1.ImgMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  I: Integer;
  H: THotspot;
  XM, YM: Integer;
  L: TStringList;
begin
  L:= TStringList.Create;
  try
    //Update code with new value(s)
    for I:= 0 to Length(fHotspots) - 1 do begin
      H:= fHotspots[I];

      L.Append('  <area shape="'+H.Shape+'" coords="'+'" href="'+'" alt="'+'" />');

      fHotspots[I]:= H;
    end;
  finally
    L.Free;
  end;

  //Re-parse HTML with new values

  //Re-draw hotspots on image

  fMouseDownState:= msNone;
end;

//Acquires hotspot info at current mouse position
//  Returns with 'Active = False' if no hotspot is present
function TForm1.HotspotAtCursor: TMouseHotspot;
var
  I: Integer;
  H: THotspot;
  X, Y: Integer;
begin
  X:= Img.ScreenToClient(Mouse.CursorPos).X;
  Y:= Img.ScreenToClient(Mouse.CursorPos).Y;
  Result.Active:= False;
  for I:= 0 to Length(fHotspots)-1 do begin
    H:= fHotspots[I];
    //Detect if mouse is at an edge of hotspot (to resize)
    if (X >= H.Area.Left) and (X <= H.Area.Right) and
      (Y >= H.Area.Top) and (Y <= H.Area.Bottom) then
    begin
      Result.Hotspot:= H;
      Result.Active:= True;
      Result.DownPos:= fPosDown;
      Result.CurrPos:= Point(X, Y);
      Break;
    end;
  end;
end;

//Acquires mouse down state info at current mouse position
//  In other words, with mouse where it is now, what would be done if clicked?
function TForm1.MouseStateAtCursor: TMouseDownState;
var
  X, Y: Integer;
  H: TMouseHotspot;
begin
  Result:= msNone;
  X:= Img.ScreenToClient(Mouse.CursorPos).X;
  Y:= Img.ScreenToClient(Mouse.CursorPos).Y;
  H:= Self.HotspotAtCursor;
  if H.Active then begin
    //Mouse is over a hotspot
    if (X >= H.Hotspot.Area.Right - GripSize) and (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeSE;
    end else
    if (X >= H.Hotspot.Area.Right - GripSize) and (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeNE;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) and (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeSW;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) and (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeNW;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) then begin
      Result:= msSizeW;
    end else
    if (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeN;
    end else
    if (X >= H.Hotspot.Area.Right - GripSize) then begin
      Result:= msSizeE;
    end else
    if (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeS;
    end else begin
      //Mouse is directly over hotspot, move, not resize
      Result:= msMove;
    end;
  end;
end;

//Exit the application
procedure TForm1.Exit1Click(Sender: TObject);
begin
  Close;
end;

//Close currently opened image
procedure TForm1.Close1Click(Sender: TObject);
begin
  Self.CloseFile;
end;

//Main parsing procedure - need to migrate to 'CodeToImage' procedure
procedure TForm1.cmdParseClick(Sender: TObject);
var
  X: Integer;
  H: THotspot;
  T: String;
  ID: String;
  procedure Add(const Hotspot: THotspot);
  begin
    SetLength(fHotspots, Length(fHotspots)+1);
    fHotspots[Length(fHotspots)-1]:= Hotspot;
  end;
begin
  Tags.Lines.Clear;
  HParser.SourceBufferAsStr:= HTML.Text;
  ID:= '';
  SetLength(fHotspots, 0);
  while HParser.ParseNextPiece do begin
    case HParser.PieceType of
      ptHTMLTag: begin
        T:= LowerCase(HParser.HtmlTag.TagName);
        if T = 'map' then begin
          ID:= HParser.HtmlTag.ValueOfNameCS['id'];
          if ID = '' then
            ID:= HParser.HtmlTag.ValueOfNameCI['name'];
          if ID <> '' then begin
            Tags.Lines.Append('Map: "'+ID+'"');
          end;
        end else
        if T = 'area' then begin
          H.URL:= HParser.HtmlTag.ValueOfNameCI['href'];
          H.Shape:= HParser.HtmlTag.ValueOfNameCI['shape'];
          T:= HParser.HtmlTag.ValueOfNameCI['coords']+',';
          X:= 0;
          while Length(T) > 0 do begin
            if Pos(',', T) > 1 then begin
              case X of
                0: H.Area.Left:=   StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
                1: H.Area.Top:=    StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
                2: H.Area.Right:=  StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
                3: H.Area.Bottom:= StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
                else T:= '';
              end;
              Delete(T, 1, Pos(',', T));
            end else begin
              T:= '';
            end;
            Inc(X);
          end;
          Add(H);
          Tags.Lines.Append('    Area: '+
            IntToStr(H.Area.Left)+'x'+IntToStr(H.Area.Top));
        end else
        if T = 'img' then begin
          Tags.Lines.Append('Image: '+HParser.HtmlTag.ValueOfNameCS['src']);
        end;
      end;
    end;
  end;

  fImgTemp.Assign(fImgMain);
  for X:= 0 to Length(fHotspots)-1 do begin
    DrawHotspot(fHotspots[X]);
  end;
  Img.Picture.Assign(fImgTemp);
end;

//Converts HTML code to list of hotspots, then draws image
procedure TForm1.CodeToImage;
begin

end;

//Converts list of hotspots (updated by image) to HTML code
procedure TForm1.ImageToCode;
begin

end;

end.

And here's the DFM (form) code:

Code:
object Form1: TForm1
  Left = 407
  Top = 245
  Width = 810
  Height = 779
  Caption = 'Image Map Editor'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Splitter1: TSplitter
    Left = 611
    Top = 0
    Width = 5
    Height = 721
    Align = alRight
  end
  object pRight: TPanel
    Left = 616
    Top = 0
    Width = 178
    Height = 721
    Align = alRight
    TabOrder = 0
    DesignSize = (
      178
      721)
    object Tags: TMemo
      Left = 6
      Top = 16
      Width = 166
      Height = 666
      Anchors = [akLeft, akTop, akRight, akBottom]
      TabOrder = 0
    end
    object cmdParse: TBitBtn
      Left = 8
      Top = 688
      Width = 163
      Height = 25
      Anchors = [akLeft, akRight, akBottom]
      Caption = 'Parse'
      TabOrder = 1
      OnClick = cmdParseClick
    end
  end
  object pMain: TPanel
    Left = 0
    Top = 0
    Width = 569
    Height = 721
    Align = alLeft
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 1
    object Splitter2: TSplitter
      Left = 1
      Top = 225
      Width = 567
      Height = 5
      Cursor = crVSplit
      Align = alTop
    end
    object pHTML: TPanel
      Left = 1
      Top = 1
      Width = 567
      Height = 224
      Align = alTop
      TabOrder = 0
      object HTML: TMemo
        Left = 1
        Top = 1
        Width = 510
        Height = 222
        Align = alLeft
        Anchors = [akLeft, akTop, akRight, akBottom]
        Font.Charset = DEFAULT_CHARSET
        Font.Color = clWindowText
        Font.Height = -13
        Font.Name = 'Consolas'
        Font.Style = []
        Lines.Strings = (
          '<MAP NAME="bm10">'
          
            '  <AREA SHAPE="RECT" COORDS="8,29,55,48" HREF="the_list_tab.htm"' +
            '>'
          
            '  <AREA SHAPE="RECT" COORDS="56,29,111,48" HREF="the_general_tab' +
            '.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="112,29,198,47" HREF="the_general_de' +
            'fault_tab.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="200,29,257,47" HREF="the_price_setu' +
            'p_tab.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="258,30,345,47" HREF="the_customer_p' +
            'rice_setup_tab.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="346,28,421,48" HREF="the_measuremen' +
            't_tab.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="422,29,471,49" HREF="reports_tab.ht' +
            'm">'
          '  <AREA SHAPE="RECT" COORDS="12,52,134,72" HREF="hs204.htm">'
          '  <AREA SHAPE="RECT" COORDS="134,52,251,71" HREF="hs205.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="324,89,534,232" HREF="purchase_orde' +
            'r_view_summary_tab.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="82,112,159,124" HREF="purchase_orde' +
            'rs_vendor_invoice.htm">'
          
            '  <AREA SHAPE="RECT" COORDS="69,128,110,144" HREF="inventory_bat' +
            'ch_transfer.htm">'
          '  <AREA SHAPE="RECT" COORDS="471,31,536,50" HREF="hs219.htm">'
          '</MAP>'
          
            '<IMG border=0 src="../images/bm10.png" isMap width=571 height =4' +
            '51 useMap=#bm10 >')
        ParentFont = False
        ScrollBars = ssBoth
        TabOrder = 0
        WordWrap = False
      end
    end
    object pImage: TPanel
      Left = 1
      Top = 272
      Width = 567
      Height = 448
      Align = alBottom
      Anchors = [akLeft, akTop, akRight, akBottom]
      TabOrder = 1
      object Box: TScrollBox
        Left = 1
        Top = 1
        Width = 510
        Height = 446
        HorzScrollBar.Smooth = True
        HorzScrollBar.Tracking = True
        VertScrollBar.Smooth = True
        VertScrollBar.Tracking = True
        Align = alLeft
        Anchors = [akLeft, akTop, akRight, akBottom]
        Color = clWhite
        ParentColor = False
        TabOrder = 0
        object Img: TImage
          Left = 0
          Top = 0
          Width = 200
          Height = 500
          Cursor = crSizeNWSE
          AutoSize = True
          IncrementalDisplay = True
          OnMouseDown = ImgMouseDown
          OnMouseMove = ImgMouseMove
          OnMouseUp = ImgMouseUp
        end
      end
    end
  end
  object HParser: TDIHtmlParser
    FilterHtmlTags.StartTags = fiShow
    Left = 184
    Top = 56
  end
  object dlgOpen: TOpenPictureDialog
    Left = 216
    Top = 88
  end
  object MainMenu1: TMainMenu
    Left = 185
    Top = 89
    object File1: TMenuItem
      Caption = 'File'
      object New1: TMenuItem
        Caption = 'New...'
      end
      object Open1: TMenuItem
        Caption = 'Open'
        object Image1: TMenuItem
          Caption = 'Image...'
        end
        object HTML1: TMenuItem
          Caption = 'HTML...'
        end
        object HotspotImage1: TMenuItem
          Caption = 'Mapped Image...'
        end
      end
      object Save1: TMenuItem
        Caption = 'Save'
      end
      object SaveAs1: TMenuItem
        Caption = 'Save As...'
      end
      object Close1: TMenuItem
        Caption = 'Close'
        OnClick = Close1Click
      end
      object N1: TMenuItem
        Caption = '-'
      end
      object Exit1: TMenuItem
        Caption = 'Exit'
        OnClick = Exit1Click
      end
    end
    object Edit1: TMenuItem
      Caption = 'Edit'
      object Cut1: TMenuItem
        Caption = 'Cut'
      end
      object Copy1: TMenuItem
        Caption = 'Copy'
      end
      object Paste1: TMenuItem
        Caption = 'Paste'
      end
    end
    object View1: TMenuItem
      Caption = 'View'
    end
  end
end



JD Solutions
 
I did it!

Here's the new source below:

Code:
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, XPMan, ExtCtrls, Jpeg, ExtDlgs, Menus, Buttons,
  DIUnicode, DIHtmlParser, ComCtrls;
     
const
  //GripSize = size of resizable border around each hotspot
  GripSize = 2;

type  
  //Represents what mouse is doing if mouse button is down
  TMouseDownState = (msNone, msMove, msSizeW, msSizeN, msSizeE, msSizeS,
    msSizeNW, msSizeNE, msSizeSW, msSizeSE);

  TStatPan = (spStatus, spPosition, spSize, spModify, spFilename);

  //Represents one single 'hotspot' or 'area' on the 'map'
  THotspot = record
    Area: TRect;
    URL: String;
    Shape: String;
  end;

  //Represents current mouse status of a hotspot
  TMouseHotspot = record
    Hotspot: THotspot;
    Active: Bool;
    DownPos: TPoint;
    UpPos: TPoint;
    CurrPos: TPoint;
    Index: Integer;
  end;

  //Primary storage of all hotspot records
  THotspots = array of THotspot;

  TForm1 = class(TForm)
    HParser: TDIHtmlParser;
    dlgOpen: TOpenPictureDialog;
    pMain: TPanel;
    pHTML: TPanel;
    HTML: TMemo;
    pImage: TPanel;
    Box: TScrollBox;
    Img: TImage;
    Splitter2: TSplitter;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    SaveAs1: TMenuItem;
    Close1: TMenuItem;
    N1: TMenuItem;
    Exit1: TMenuItem;
    Edit1: TMenuItem;
    Cut1: TMenuItem;
    Copy1: TMenuItem;
    Paste1: TMenuItem;
    View1: TMenuItem;
    Image1: TMenuItem;
    HotspotImage1: TMenuItem;
    Stat: TStatusBar;
    dlgOpenHTML: TOpenDialog;
    Panel1: TPanel;
    cmdParse: TBitBtn;
    Label1: TLabel;
    txtLeft: TEdit;
    udLeft: TUpDown;
    Label2: TLabel;
    txtTop: TEdit;
    udTop: TUpDown;
    Label3: TLabel;
    txtWidth: TEdit;
    udWidth: TUpDown;
    txtHeight: TEdit;
    Label4: TLabel;
    udHeight: TUpDown;
    Label5: TLabel;
    txtURL: TEdit;
    procedure cmdParseClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ImgMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ImgMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImgMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Exit1Click(Sender: TObject);
    procedure Close1Click(Sender: TObject);
    procedure Image1Click(Sender: TObject);
    procedure HTMLChange(Sender: TObject);
    procedure HotspotImage1Click(Sender: TObject);
    procedure txtLeftChange(Sender: TObject);
    procedure udLeftClick(Sender: TObject; Button: TUDBtnType);
  private
    fChanging: Bool;
    fImgMain: TBitmap;
    fImgTemp: TBitmap;  
    fHotspots: THotspots;
    fMouseDownState: TMouseDownState;
    fSelHotspot: Integer;
    fStartHotspot: THotspot;
    fPosDown: TPoint;
    function GetHotspot(Index: Integer): THotspot;
    procedure SetHotspot(Index: Integer; const Value: THotspot);
    procedure DrawHotspot(const H: THotspot; const Selected: Bool);
    procedure CodeToImage;
    procedure ImageToCode;
    function GetStatus(Pan: TStatPan): String;
    procedure SetStatus(Pan: TStatPan; const Value: String);
    procedure HotspotSelected(const Hotspot: THotspot);
    procedure HotspotUnselected;
    procedure HotspotEdit(const DoEdit: Bool);
    procedure ChangeSelHotspot;
    procedure DrawHotspots;
  public
    function LoadFile(const Filename: TFilename): Bool;
    procedure CloseFile;
    function HotspotAtCursor: TMouseHotspot;
    function MouseStateAtCursor: TMouseDownState;
    property MouseDownState: TMouseDownState read fMouseDownState;
    property SelHotspot: Integer read fSelHotspot;
    property Hotspots[Index: Integer]: THotspot read GetHotspot write SetHotspot;
    property Status[Pan: TStatPan]: String read GetStatus write SetStatus;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//Draws a single hotspot to the temporary bitmap
procedure TForm1.DrawHotspot(const H: THotspot; const Selected: Bool);
var
  C: TCanvas;
begin
  C:= fImgTemp.Canvas;
  C.Brush.Style:= bsClear;
  C.Pen.Style:= psSolid;
  C.Pen.Width:= GripSize;
  if Selected then     
    C.Pen.Color:= clBlue
  else
    C.Pen.Color:= clGray;
  C.Rectangle(H.Area);
end;

//Draws all hotspots to the temporary bitmap - then copies to display
procedure TForm1.DrawHotspots;
var
  X: Integer;
begin   
  fImgTemp.Assign(fImgMain);
  for X:= 0 to Length(fHotspots)-1 do begin
    if X = fSelHotspot then
      DrawHotspot(fHotspots[X], True)
    else
      DrawHotspot(fHotspots[X], False);
  end;
  Img.Picture.Assign(fImgTemp);
end;

//Acquires a single hotspot from global list by index
function TForm1.GetHotspot(Index: Integer): THotspot;
begin
  Result:= fHotspots[Index];
end;

//Assigns a single hotspot in global list by index
procedure TForm1.SetHotspot(Index: Integer; const Value: THotspot);
begin
  fHotspots[Index]:= Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin                
  //Create objects
  fImgMain:= TBitmap.Create;
  fImgTemp:= TBitmap.Create;
  //Set default values
  SetLength(fHotspots, 0);
  fSelHotspot:= -1;
  fMouseDownState:= msNone;
  fChanging:= False;
  //Prepare controls
  Status[spStatus]:= 'Loading...';
  pMain.Align:= alClient;
  pImage.Align:= alClient;
  HTML.Align:= alClient;
  Box.Align:= alClient;
  CloseFile;
  Show;
  BringToFront;
  Application.ProcessMessages;
  //Done loading
  Status[spStatus]:= 'Ready';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  //Free objects
  fImgMain.Free;
  fImgTemp.Free;
end;

//Loads a single image file to be primary image to work with
function TForm1.LoadFile(const Filename: TFilename): Bool;
var
  Ext: String;
  J: TJpegImage;
begin
  Result:= False;
  CloseFile;
  if FileExists(Filename) then begin
    Ext:= LowerCase(ExtractFileExt(Filename));
    if (Ext = '.jpg') or (Ext = '.jpeg') then begin
      J:= TJpegImage.Create;
      try
        J.LoadFromFile(Filename);
        fImgMain.Assign(J);
        Result:= True;
      finally
        J.Free;
      end;
    end else
    if (Ext = '.bmp') then begin
      fImgMain.LoadFromFile(Filename);
      Result:= True;
    end else begin
      raise Exception.Create('Invalid file format "'+Ext+'"');
    end;
  end;
  if Result then begin
    fImgTemp.Assign(fImgMain);
    Img.Picture.Assign(fImgMain);
    Status[spFilename]:= dlgOpen.FileName;
  end;
end;

//Closes the currently opened file
procedure TForm1.CloseFile;
begin
  Status[spFilename]:= '[No Image Open]';
  HotspotUnselected;
end;

//Detect mouse movement on image
procedure TForm1.ImgMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  H: TMouseHotspot;
  HS: THotspot;
begin
  //Identify current mouse state
  if fSelHotspot >= 0 then
    HS:= fHotspots[fSelHotspot];
  Status[spPosition]:= IntToStr(X) + ' x ' + IntToStr(Y);
  case fMouseDownState of
    msNone: begin
      //Mouse button is NOT down - change cursor
      H:= HotspotAtCursor;
      if H.Active then begin
        //Mouse is over a hotspot
        case MouseStateAtCursor of
          msMove: Img.Cursor:= crSizeAll;
          msSizeN, msSizeS: Img.Cursor:= crSizeNS;
          msSizeW, msSizeE: Img.Cursor:= crSizeWE;
          msSizeNW, msSizeSE: Img.Cursor:= crSizeNWSE;
          msSizeSW, msSizeNE: Img.Cursor:= crSizeNESW;
        end;
      end else begin
        //Mouse is NOT over a hotspot
        Img.Cursor:= crCross;
      end;
    end;
    //The following events update Rect values within fHotspots
    //  With these, the mouse button IS down
    msMove: begin
      //Mouse is moving selected hotspot
      HS.Area.Left:= fStartHotspot.Area.Left + (X - fPosDown.X);
      HS.Area.Top:= fStartHotspot.Area.Top + (Y - fPosDown.Y);
      HS.Area.Right:= fStartHotspot.Area.Right + (X - fPosDown.X);
      HS.Area.Bottom:= fStartHotspot.Area.Bottom + (Y - fPosDown.Y);
    end;
    msSizeW: begin
      //Mouse is sizing left side of hotspot
      HS.Area.Left:= fStartHotspot.Area.Left + (X - fPosDown.X);
    end;
    msSizeN: begin
      //Mouse is sizing top side of hotspot
      HS.Area.Top:= fStartHotspot.Area.Top + (Y - fPosDown.Y);
    end;
    msSizeE: begin
      //Mouse is sizing right side of hotspot
      HS.Area.Right:= fStartHotspot.Area.Right + (X - fPosDown.X);
    end;
    msSizeS: begin
      //Mouse is sizing bottom side of hotspot
      HS.Area.Bottom:= fStartHotspot.Area.Bottom + (Y - fPosDown.Y);
    end;
    msSizeNW: begin
      //Mouse is sizing top-left corner of hotspot
      HS.Area.Left:= fStartHotspot.Area.Left + (X - fPosDown.X);
      HS.Area.Top:= fStartHotspot.Area.Top + (Y - fPosDown.Y);
    end;
    msSizeNE: begin
      //Mouse is sizing top-right corner of hotspot
      HS.Area.Top:= fStartHotspot.Area.Top + (Y - fPosDown.Y);
      HS.Area.Right:= fStartHotspot.Area.Right + (X - fPosDown.X);
    end;
    msSizeSW: begin
      //Mouse is sizing bottom-left corner of hotspot
      HS.Area.Bottom:= fStartHotspot.Area.Bottom + (Y - fPosDown.Y);
      HS.Area.Left:= fStartHotspot.Area.Left + (X - fPosDown.X);
    end;
    msSizeSE: begin
      //Mouse is sizing bottom-right corner of hotspot
      HS.Area.Bottom:= fStartHotspot.Area.Bottom + (Y - fPosDown.Y);  
      HS.Area.Right:= fStartHotspot.Area.Right + (X - fPosDown.X);
    end;
  end;
  if fMouseDownState <> msNone then begin
    fHotspots[fSelHotspot]:= HS;
    HotspotSelected(HS);
    DrawHotspots;
  end;
end;

procedure TForm1.ImgMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  H: TMouseHotspot;
begin
  fChanging:= True;
  fPosDown:= Point(X, Y); //Record current mouse position for calculations
  H:= HotspotAtCursor;
  if H.Active then begin
    //Mouse clicked on a hotspot
    fMouseDownState:= MouseStateAtCursor; //Record what mouse is doing
    fSelHotspot:= H.Index;
    fStartHotspot:= H.Hotspot;
    HotspotSelected(H.Hotspot);
  end else begin
    //Mouse clicked where there is no hotspot - draw new?
    fSelHotspot:= -1;
    HotspotUnselected;
  end;
end;
     
procedure TForm1.ImgMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  I: Integer;
  H: THotspot;
  XM, YM: Integer;
  L: TStringList;
begin

  L:= TStringList.Create;
  try
    //Update code with new value(s)
    for I:= 0 to Length(fHotspots) - 1 do begin
      H:= fHotspots[I];

      L.Append('  <area shape="'+H.Shape+'" coords="'+'" href="'+'" alt="'+'" />');

      fHotspots[I]:= H;
    end;
  finally
    L.Free;
  end;

  //Re-parse HTML with new values

  //Re-draw hotspots on image
  fChanging:= False;
  fMouseDownState:= msNone;
  DrawHotspots;
end;

//Acquires hotspot info at current mouse position
//  Returns with 'Active = False' if no hotspot is present
function TForm1.HotspotAtCursor: TMouseHotspot;
var
  I: Integer;
  H: THotspot;
  X, Y: Integer;
begin
  X:= Img.ScreenToClient(Mouse.CursorPos).X;
  Y:= Img.ScreenToClient(Mouse.CursorPos).Y;
  Result.Active:= False;
  for I:= 0 to Length(fHotspots)-1 do begin
    H:= fHotspots[I];
    //Detect if mouse is at an edge of hotspot (to resize)
    if (X >= H.Area.Left) and (X <= H.Area.Right) and
      (Y >= H.Area.Top) and (Y <= H.Area.Bottom) then
    begin
      Result.Hotspot:= H;
      Result.Active:= True;
      Result.DownPos:= fPosDown;
      Result.CurrPos:= Point(X, Y);
      Result.Index:= I;
      Break;
    end;
  end;
end;

//Acquires mouse down state info at current mouse position
//  In other words, with mouse where it is now, what would be done if clicked?
function TForm1.MouseStateAtCursor: TMouseDownState;
var
  X, Y: Integer;
  H: TMouseHotspot;
begin
  Result:= msNone;
  X:= Img.ScreenToClient(Mouse.CursorPos).X;
  Y:= Img.ScreenToClient(Mouse.CursorPos).Y;
  H:= Self.HotspotAtCursor;
  if H.Active then begin
    //Mouse is over a hotspot
    if (X >= H.Hotspot.Area.Right - GripSize) and (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeSE;
    end else
    if (X >= H.Hotspot.Area.Right - GripSize) and (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeNE;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) and (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeSW;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) and (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeNW;
    end else
    if (X <= H.Hotspot.Area.Left + GripSize) then begin
      Result:= msSizeW;
    end else
    if (Y <= H.Hotspot.Area.Top + GripSize) then begin
      Result:= msSizeN;
    end else
    if (X >= H.Hotspot.Area.Right - GripSize) then begin
      Result:= msSizeE;
    end else
    if (Y >= H.Hotspot.Area.Bottom - GripSize) then begin
      Result:= msSizeS;
    end else begin
      //Mouse is directly over hotspot, move, not resize
      Result:= msMove;
    end;
  end;
end;

//Exit the application
procedure TForm1.Exit1Click(Sender: TObject);
begin
  Close;
end;

//Close currently opened image
procedure TForm1.Close1Click(Sender: TObject);
begin
  Self.CloseFile;
end;

//Main parsing procedure - need to migrate to 'CodeToImage' procedure
procedure TForm1.cmdParseClick(Sender: TObject);
var
  X: Integer;
  H: THotspot;
  T: String;
  ID: String;
  procedure Add(const Hotspot: THotspot);
  begin
    SetLength(fHotspots, Length(fHotspots)+1);
    fHotspots[Length(fHotspots)-1]:= Hotspot;
  end;
begin                  
  Status[spModify]:= '';
  cmdParse.Enabled:= False;
  HotspotUnselected;
  HParser.SourceBufferAsStr:= HTML.Text;
  ID:= '';
  SetLength(fHotspots, 0);
  while HParser.ParseNextPiece do begin
    if HParser.PieceType = ptHTMLTag then begin
      T:= LowerCase(HParser.HtmlTag.TagName);
      if T = 'map' then begin
        ID:= HParser.HtmlTag.ValueOfNameCS['id'];
        if ID = '' then begin
          ID:= HParser.HtmlTag.ValueOfNameCI['name'];
        end;
      end else
      if T = 'area' then begin
        H.URL:= HParser.HtmlTag.ValueOfNameCI['href'];
        H.Shape:= HParser.HtmlTag.ValueOfNameCI['shape'];
        T:= HParser.HtmlTag.ValueOfNameCI['coords']+',';
        X:= 0;
        while Length(T) > 0 do begin
          if Pos(',', T) > 1 then begin
            case X of
              0: H.Area.Left:=   StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
              1: H.Area.Top:=    StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
              2: H.Area.Right:=  StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
              3: H.Area.Bottom:= StrToIntDef(Copy(T, 1, Pos(',', T)-1), 0);
              else T:= '';
            end;
            Delete(T, 1, Pos(',', T));
          end else begin
            T:= '';
          end; //if pos...
          Inc(X);
        end; //while length...
        Add(H);
      end; //if t = ...
    end; //if hparser.piecetype...
  end; //while hparser...

  DrawHotspots;

end;

//Converts HTML code to list of hotspots, then draws image
procedure TForm1.CodeToImage;
begin

end;

//Converts list of hotspots (updated by image) to HTML code
procedure TForm1.ImageToCode;
begin

end;

procedure TForm1.Image1Click(Sender: TObject);
begin
  if dlgOpen.Execute then begin
    Self.CloseFile;
    Self.LoadFile(dlgOpen.FileName);
    cmdParseClick(Self);
  end;
end;

function TForm1.GetStatus(Pan: TStatPan): String;
begin
  case Pan of
    spStatus:   Result:= Stat.Panels[0].Text;
    spPosition: Result:= Stat.Panels[1].Text;
    spSize:     Result:= Stat.Panels[2].Text;
    spModify:   Result:= Stat.Panels[3].Text;
    spFilename: Result:= Stat.Panels[4].Text;
  end;
end;

procedure TForm1.SetStatus(Pan: TStatPan; const Value: String);
begin
  case Pan of
    spStatus:   Stat.Panels[0].Text:= Value;
    spPosition: Stat.Panels[1].Text:= Value;
    spSize:     Stat.Panels[2].Text:= Value;
    spModify:   Stat.Panels[3].Text:= Value;
    spFilename: Stat.Panels[4].Text:= Value;
  end;
end;

procedure TForm1.HTMLChange(Sender: TObject);
begin
  cmdParse.Enabled:= True;
  Status[spModify]:= 'Modified';
end;

procedure TForm1.HotspotImage1Click(Sender: TObject);
begin
  if dlgOpenHTML.Execute then begin
    try
      HTML.Lines.LoadFromFile(dlgOpenHTML.FileName);
      cmdParseClick(Self);
    except
      on e: exception do begin
        raise Exception.Create(
          'Invalid HTML or text in file "'+dlgOpenHTML.FileName+'"');
      end;
    end;
  end;
end;

procedure TForm1.HotspotSelected(const Hotspot: THotspot);
begin
  udLeft.Position:=     Hotspot.Area.Left;
  udTop.Position:=      Hotspot.Area.Top;
  udWidth.Position:=    Hotspot.Area.Right - Hotspot.Area.Left;
  udHeight.Position:=   Hotspot.Area.Bottom - Hotspot.Area.Top;
  txtURL.Text:=         Hotspot.URL;
  if not fChanging then
    HotspotEdit(True);
end;

procedure TForm1.HotspotUnselected;
begin
  udLeft.Position:= 0;
  udTop.Position:= 0;
  udWidth.Position:= 0;
  udHeight.Position:= 0;
  txtURL.Clear;
  HotspotEdit(False);
end;

procedure TForm1.HotspotEdit(const DoEdit: Bool);
begin
  txtLeft.Enabled:= DoEdit;
  txtTop.Enabled:= DoEdit;
  txtWidth.Enabled:= DoEdit;
  txtHeight.Enabled:= DoEdit;
  udLeft.Enabled:= DoEdit;
  udTop.Enabled:= DoEdit;
  udWidth.Enabled:= DoEdit;
  udHeight.Enabled:= DoEdit;
  txtURL.Enabled:= DoEdit;
end;

procedure TForm1.ChangeSelHotspot;
var
  H: THotspot;
begin
  //Read values from user entry and set records
  if not fChanging then begin
    if fSelHotspot >= 0 then begin
      H:= fHotspots[fSelHotspot];

      H.Area.Left:= udLeft.Position;
      H.Area.Top:= udTop.Position;
      H.Area.Right:= udLeft.Position + udWidth.Position;
      H.Area.Bottom:= udTop.Position + udHeight.Position;
      H.URL:= txtURL.Text;

      fHotspots[fSelHotspot]:= H;
    end;
    //Update HTML

    //Parse HTML
    DrawHotspots;
  end;
end;

procedure TForm1.txtLeftChange(Sender: TObject);
begin
  ChangeSelHotspot;
end;

procedure TForm1.udLeftClick(Sender: TObject; Button: TUDBtnType);
begin
  ChangeSelHotspot;
end;

end.

And the DFM:

Code:
object Form1: TForm1
  Left = 343
  Top = 250
  Width = 774
  Height = 778
  Caption = 'Image Map Editor'
  Color = 16117483
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object pMain: TPanel
    Left = 0
    Top = 0
    Width = 721
    Height = 701
    Align = alLeft
    Anchors = [akLeft, akTop, akRight, akBottom]
    BevelOuter = bvNone
    ParentBackground = True
    ParentColor = True
    TabOrder = 0
    object Splitter2: TSplitter
      Left = 0
      Top = 193
      Width = 721
      Height = 5
      Cursor = crVSplit
      Align = alTop
      Beveled = True
      Color = clBtnFace
      ParentColor = False
      ResizeStyle = rsUpdate
    end
    object pHTML: TPanel
      Left = 0
      Top = 0
      Width = 721
      Height = 193
      Align = alTop
      BevelOuter = bvNone
      TabOrder = 0
      object HTML: TMemo
        Left = 0
        Top = 0
        Width = 664
        Height = 193
        Align = alLeft
        Anchors = [akLeft, akTop, akRight, akBottom]
        Font.Charset = DEFAULT_CHARSET
        Font.Color = clWindowText
        Font.Height = -13
        Font.Name = 'Consolas'
        Font.Style = []
        ParentFont = False
        ScrollBars = ssBoth
        TabOrder = 0
        WordWrap = False
        OnChange = HTMLChange
      end
    end
    object pImage: TPanel
      Left = 0
      Top = 264
      Width = 721
      Height = 437
      Align = alBottom
      Anchors = [akLeft, akTop, akRight, akBottom]
      BevelOuter = bvNone
      TabOrder = 1
      object Box: TScrollBox
        Left = 0
        Top = 41
        Width = 664
        Height = 396
        HorzScrollBar.Smooth = True
        HorzScrollBar.Tracking = True
        VertScrollBar.Smooth = True
        VertScrollBar.Tracking = True
        Align = alLeft
        Anchors = [akLeft, akTop, akRight, akBottom]
        Color = clWhite
        ParentColor = False
        TabOrder = 0
        object Img: TImage
          Left = 0
          Top = 0
          Width = 200
          Height = 200
          Cursor = crSizeNWSE
          AutoSize = True
          IncrementalDisplay = True
          OnMouseDown = ImgMouseDown
          OnMouseMove = ImgMouseMove
          OnMouseUp = ImgMouseUp
        end
      end
      object Panel1: TPanel
        Left = 0
        Top = 0
        Width = 721
        Height = 41
        Align = alTop
        ParentBackground = False
        TabOrder = 1
        DesignSize = (
          721
          41)
        object Label1: TLabel
          Left = 128
          Top = 4
          Width = 23
          Height = 13
          Caption = 'Left'
          FocusControl = txtLeft
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
          Transparent = True
        end
        object Label2: TLabel
          Left = 208
          Top = 4
          Width = 23
          Height = 13
          Caption = 'Top'
          FocusControl = txtTop
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
          Transparent = True
        end
        object Label3: TLabel
          Left = 296
          Top = 4
          Width = 34
          Height = 13
          Caption = 'Width'
          FocusControl = txtWidth
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
          Transparent = True
        end
        object Label4: TLabel
          Left = 376
          Top = 4
          Width = 38
          Height = 13
          Caption = 'Height'
          FocusControl = txtHeight
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
          Transparent = True
        end
        object Label5: TLabel
          Left = 464
          Top = 4
          Width = 26
          Height = 13
          Caption = 'URL'
          FocusControl = txtURL
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
          Transparent = True
        end
        object cmdParse: TBitBtn
          Left = 8
          Top = 5
          Width = 113
          Height = 32
          Caption = 'Synchronize'
          Enabled = False
          TabOrder = 0
          OnClick = cmdParseClick
        end
        object txtLeft: TEdit
          Left = 128
          Top = 16
          Width = 53
          Height = 21
          Cursor = crHandPoint
          TabOrder = 1
          Text = '0'
          OnChange = txtLeftChange
        end
        object udLeft: TUpDown
          Left = 181
          Top = 16
          Width = 16
          Height = 21
          Cursor = crHandPoint
          Associate = txtLeft
          Min = -9999
          Max = 9999
          TabOrder = 2
          OnClick = udLeftClick
        end
        object txtTop: TEdit
          Left = 208
          Top = 16
          Width = 53
          Height = 21
          Cursor = crHandPoint
          TabOrder = 3
          Text = '0'
          OnChange = txtLeftChange
        end
        object udTop: TUpDown
          Left = 261
          Top = 16
          Width = 16
          Height = 21
          Cursor = crHandPoint
          Associate = txtTop
          Min = -9999
          Max = 9999
          TabOrder = 4
          OnClick = udLeftClick
        end
        object txtWidth: TEdit
          Left = 296
          Top = 16
          Width = 53
          Height = 21
          Cursor = crHandPoint
          TabOrder = 5
          Text = '0'
          OnChange = txtLeftChange
        end
        object udWidth: TUpDown
          Left = 349
          Top = 16
          Width = 16
          Height = 21
          Cursor = crHandPoint
          Associate = txtWidth
          Min = -9999
          Max = 9999
          TabOrder = 6
          OnClick = udLeftClick
        end
        object txtHeight: TEdit
          Left = 376
          Top = 16
          Width = 53
          Height = 21
          Cursor = crHandPoint
          TabOrder = 7
          Text = '0'
          OnChange = txtLeftChange
        end
        object udHeight: TUpDown
          Left = 429
          Top = 16
          Width = 16
          Height = 21
          Cursor = crHandPoint
          Associate = txtHeight
          Min = -9999
          Max = 9999
          TabOrder = 8
          OnClick = udLeftClick
        end
        object txtURL: TEdit
          Left = 464
          Top = 16
          Width = 249
          Height = 21
          Anchors = [akLeft, akTop, akRight]
          TabOrder = 9
          Text = '[URL unfurl="true"]www.somewebsite.com'[/URL]
          OnChange = txtLeftChange
        end
      end
    end
  end
  object Stat: TStatusBar
    Left = 0
    Top = 701
    Width = 758
    Height = 19
    Panels = <
      item
        Text = 'Not Ready'
        Width = 110
      end
      item
        Text = '0 x 0'
        Width = 80
      end
      item
        Text = '0 x 0'
        Width = 80
      end
      item
        Width = 80
      end
      item
        Text = '[No Image Open]'
        Width = 80
      end>
  end
  object HParser: TDIHtmlParser
    FilterHtmlTags.StartTags = fiShow
    Left = 184
    Top = 56
  end
  object dlgOpen: TOpenPictureDialog
    Left = 216
    Top = 88
  end
  object MainMenu1: TMainMenu
    Left = 185
    Top = 89
    object File1: TMenuItem
      Caption = 'File'
      object Open1: TMenuItem
        Caption = 'Open'
        object Image1: TMenuItem
          Caption = 'Image...'
          OnClick = Image1Click
        end
        object HotspotImage1: TMenuItem
          Caption = 'Map...'
          OnClick = HotspotImage1Click
        end
      end
      object Save1: TMenuItem
        Caption = 'Save'
      end
      object SaveAs1: TMenuItem
        Caption = 'Save As...'
      end
      object Close1: TMenuItem
        Caption = 'Close'
        OnClick = Close1Click
      end
      object N1: TMenuItem
        Caption = '-'
      end
      object Exit1: TMenuItem
        Caption = 'Exit'
        OnClick = Exit1Click
      end
    end
    object Edit1: TMenuItem
      Caption = 'Edit'
      object Cut1: TMenuItem
        Caption = 'Cut'
      end
      object Copy1: TMenuItem
        Caption = 'Copy'
      end
      object Paste1: TMenuItem
        Caption = 'Paste'
      end
    end
    object View1: TMenuItem
      Caption = 'View'
    end
  end
  object dlgOpenHTML: TOpenDialog
    Filter = 
      'HTML Image Map Files (*.hmp)|*.hmp|HTML Files (*.htm;*.html)|*.h' +
      'tm;*.html|All Files (*.*)|*.*'
    Left = 248
    Top = 88
  end
end



JD Solutions
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top