Link to home
Start Free TrialLog in
Avatar of the_modder
the_modderFlag for United States of America

asked on

Delete part of image

I have two images sitting on top of one of another (bottom has all the items highlighted, the top layer doesn't). I also have an empty image box that is empty on top of the two. What I'm trying to do is temporarily make the part under the empty image box empty on mouse over, so it should display the highlighted part on the bottom layer, but all the other items should not be affected.

Thanks in advance,
David Burban
Avatar of sftweng
sftweng

Why not use a separate pair of TImages for each item, one highlighted and the other not highlighted, and just change the "Visible" attribute to false in the OnMouseOver event for the item itself and back to true in the background (surrounding) component (perhaps a TPanel)?
Of course I meant "OnMouseMove", like this:

unit uLayeredImages;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, jpeg, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    Image1: TImage;
    Image2: TImage;
    procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure GroupBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Image2.Visible := False;
end;

procedure TForm1.GroupBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Image2.Visible := True;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Image2.Visible := True;
end;

end.
Avatar of the_modder

ASKER

I already came up with that code. Sorry. I said delete PART of the image, and by delete I mean temporarily hide, not hide the whole image. Imagine writing that code for ALL lettors on a keybaord, now you know why I need to hide part of an image (when mouse is over part of image2 disapears, and when mouse leaves it appears).

Thanks.
Given a separate TImage pair for each key on the keyboard, you could use a single OnMouseOver event that determines which TImage to make visible or invisible by using the X,Y coordinates to determine which one should be affected.

I think this would be easier than, say, trying to set transparency for just a portion of a TImage, or doing a BitBlt of the underlying image.
Another advantage of doing it this way is that you could have key-specific event handlers - e.g., to toggle capslock.
Nope. I'm not interested in writing code for so many keys, plus having to map everything out in a file.

Here's why I like my idea: I just have two images, and something that is transperent and accepts mouse clicks/overs/whatever. When a mouse comes over I just call up a function that reads the dimentions of the box and clears a part of the 2nd image. When the mouse leaves the part come back.
OK, I'll leave it to others to come up with a solution you'd prefer. It's the middle of the night for me and I'm heading back to bed. Good luck. Enjoy!

Alan
Thanks. The problem with your code would have been that I would have had to split up the images into a LOT of smaller ones, and for a skinably app it should be as easy as possible when making the skins.

Thanks for your help,
David Burban
Just a parting thought - keep two invisible TImages available, use the OnMouseMove X,Y coordinates to define the TRect you want to change then use the bitmap's scanlines or pixels to overwrite the 3rd visible image.
Bump =)
You can do it this way.
Place bottom image.
Place Panel on top of it.
Place top image on Panel.
When You want to show some part of top image

var
  hr: HRGN;
begin
  hr := CreateRectRgn(10,10,30,30);
  SetWindowRgn(Panel1.Handle,hr,True);
Doesn't work. Sorry.

I've tested it. It works OK. You must misunderstand me somewhere.
In my example highlighted image should be on top of course.
I've got an idea. We could maybe paint part of the top picture with clFuchsia and set that to be the transparent color. But before that we put the other part to memory, and after the mouse leaves we can copy the thing from memory back. Now I'd just need the code for that :)
That's essentially what I suggested at 01:08 AM PDT. Keep 2 read-only TImages and update a region of the single visible TImage from them.
I can't find panel. When I look in help I can only find statusbar :|
Panel is on Standard Page of components palette.
TPanel
Doesn't work. I place the Tpanel on top of my first image and then added a random pic on top of the Tpanel. When I Panel1MouseMove, it (tpalne) disapears and makes a small square.
bump :)
> When I Panel1MouseMove, it (tpalne) disapears and makes a small square
This mean that it works. It was just my previous example

var
  Form1: TForm1;
  hr: HRGN;

procedure TForm1.FormCreate(Sender: TObject);
begin
  hr := 0;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  SIZE = 20;
begin
  if (X < SIZE) or (Y <SIZE) or (X >= Panel1.Width -SIZE) or
                    (Y >= Panel1.Height -SIZE) then
// create safe margines for hiding panel
    Panel1.Visible := False
  else
    begin
// You may add here checking for previous X, Y and
// do nothing when it creates same region
    Panel1.Visible := False;
    if hr <> 0 then
      begin
      SetWindowRgn(Panel1.Handle,0,True);
      DeleteObject(hr);
      end;
    hr := CreateRectRgn(SIZE*(X div SIZE),SIZE*(Y div SIZE),
             SIZE*(X div SIZE)+SIZE,SIZE*(Y div SIZE)+SIZE);
    SetWindowRgn(Panel1.Handle,hr,True);
    Panel1.Visible := True;
    end;
end;
Now I don't get any movement at all... lol

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, jpeg;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Panel1: TPanel;
    Image2: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
    hr: HRGN;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   hr := 0;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  SIZE = 20;
begin
  if (X < SIZE) or (Y <SIZE) or (X >= Panel1.Width -SIZE) or
                    (Y >= Panel1.Height -SIZE) then
// create safe margines for hiding panel
    Panel1.Visible := False
  else
    begin
// You may add here checking for previous X, Y and
// do nothing when it creates same region
    Panel1.Visible := False;
    if hr <> 0 then
      begin
      SetWindowRgn(Panel1.Handle,0,True);
      DeleteObject(hr);
      end;
    hr := CreateRectRgn(SIZE*(X div SIZE),SIZE*(Y div SIZE),
             SIZE*(X div SIZE)+SIZE,SIZE*(Y div SIZE)+SIZE);
    SetWindowRgn(Panel1.Handle,hr,True);
    Panel1.Visible := True;
    end;
end;


end.
If you can't make this do what you want to do, then I'm giving up on this conversation. The concept is simple and doesn't need any tricks of MSWindows peculiarities:

unit uPartImage;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure CopyRegion(target : TImage; Source : TImage;
                         top, left, height, width : Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  oldTop, oldLeft, oldHeight, oldWidth : Integer;

implementation

{$R *.dfm}

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  newTop, newLeft, newHeight, newWidth : Integer;
begin
  newHeight := 50;
  newWidth := 50;
  newTop := Y-25;
  newLeft := X-25;
  CopyRegion(Image1,Image2,oldTop,oldLeft,oldHeight,oldWidth);
  CopyRegion(Image1,Image3,newTop,newLeft,newHeight,newWidth);
  oldTop := newTop;
  oldLeft := newLeft;
  oldHeight := newHeight;
  oldWidth := newWidth;
end {Image1MouseMove};

procedure TForm1.FormCreate(Sender: TObject);
begin
  oldHeight := 50;
  oldWidth := 50;
  oldTop := 0;
  oldLeft := 0;
end {FormCreate};

procedure TForm1.CopyRegion(target : TImage; Source : TImage;
                         top, left, height, width : Integer);
var
  row, col : Integer;
begin
  { There are faster ways of doing this but it's up to you to optimize}
  { if you want to do so. }
  for row := top to top+height do
    for col := left to left+width do
    begin
      target.Canvas.Pixels[col,row] := source.Canvas.Pixels[col,row];
    end;
end {CopyRegion};

end.
A final comment: Make image2 and image3 not visible, image1 visible and always on top. (Right click on it and set it's properties before compiling).
What i'm getting is an eraser effect. The image starts out with all the highlights, and then when I move my mouse over it it turns to non-highlight, but it is amazingly slow even on my 2.5ghz machine.
Choose which picture starts in each TImage carefully. Image1 should be the unhighlighted image. Yes, copying pixels is about a thousand times slower than using Scanline. You'll find a Scanline example via Help.
The thing is that I needed the picture to turn back to unhighlighted state when the mouse left. And the block should be transparent, and it should activate when I enter the boundaries of image3.
Everything is in my example
I don't see it going back to the original image when my mouse leaves, instead it earases the original image.
Image1 and Image2 need to be set to the unhighlighted BMP and Image3 to the highlighted.
Better. Its still too slow, it takes about a minute to load! Also I need to have a "hot button" so when my mouse enters that area the whole area clears, not just the square under my mouse.

Thanks!
hello Modder, you say transparent, but the screen does not really have a transparent, for a transparent "effect" to just copy (draw , paint) whatever is "percieved" as behind something, onto that something, so it looks like you see what's behind it, but you are really seeing what is drawn on the screen.

Here is some code that uses a TPaintBox, and two separate TBitmaps to do this "Highlight" type of graphics operation. I do NOT use a TImage for several reasons, the main one is that A TImage will overDraw it's primary TBitmap whenever you draw on it's Canvas, so you can not "restore" the image from it's bitmap.
I have 2 TBitmaps, FrontBmp and BackBmp, and a TPaintBox, PaintBox3, , and also an Array of TRect, which will keep All of the "Areas" (rectangles) that will be highlighted.
You will need you get the  OnMouseMove  event and the  OnPaint  event, for the PaintBox3, and the  OnMouseMove  for the "Parent" of the PaintBox3.

  private
    { Private declarations }
    FrontBmp, BackBmp: TBitmap;
    aryRect: Array[0..5] of TRect;
    LastPaint: Integer;


procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
LastPaint := -1; // LastPaint is  -1 if no highlight

FrontBmp := Tbitmap.Create;
BackBmp := TBitmap.Create;
FrontBmp.LoadFromFile('E:\Blend11.bmp');
{you can load these 2 bitmaps from resource, I used
 LoadFromFile just for this example}
BackBmp.LoadFromFile('E:\Blend12.bmp');


{YOU MUST define all of your highlight areas with this
 Array of TRect, I just divide the PaintBox3 into 6 equal
 rectangles, but you will have to give all of your rectangles
 the dimentions you need, you can have as many TRects as you need}
for i := 0 to 2 do
  aryRect[i] := Rect(88 * i,0, 88*(i+1), 128);
for i := 3 to High(aryRect) do
  aryRect[i] := Rect(88 * (i-3),129, 88*(i-2), 257);

end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
// be sure to free all bitmaps
FreeAndNil(FrontBmp);
FreeAndNil(BackBmp);
end;



// paintbox procedures

procedure TForm1.PaintBox3Paint(Sender: TObject);
begin
PaintBox3.Canvas.Draw(0,0, FrontBmp);
end;


procedure TForm1.PaintBox3MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
i: Integer;
begin
{loop through the TRect Array and see if you in a Rect}
for i := 0 to High(aryRect) do
  if PtInRect(aryRect[i], Point(X, Y)) then
    begin
    if LastPaint = i then Exit;
  {if you already paint it then exit}
    PaintBox3.Canvas.CopyRect(aryRect[i], BackBmp.Canvas, aryRect[i]);
  {use copyrect  to just draw a portion of the bitmap}
    if (LastPaint > -1) then
      PaintBox3.Canvas.CopyRect(aryRect[LastPaint], FrontBmp.Canvas, aryRect[LastPaint]);
        {Redraw the "Old" highlight to restore}
    LastPaint := i; // set new lastPaint
    Break
    end;
end;

// paintbox parent

procedure TForm1.TabSheet1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
// you must get the parent Mousemove to resore after leaves the paintbox
if (LastPaint > -1) then
  begin
  PaintBox3.Canvas.CopyRect(aryRect[LastPaint], FrontBmp.Canvas, aryRect[LastPaint]);
  LastPaint := -1;
  End;
end;


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ask questions if you need more
I can't find TBitmap on the toolbar... lol
TBitmap isn't a visual component, just a class. Look for it in "Help".
I don't know were to put this:
procedure TForm1.TabSheet1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
// you must get the parent Mousemove to resore after leaves the paintbox
if (LastPaint > -1) then
  begin
  PaintBox3.Canvas.CopyRect(aryRect[LastPaint], FrontBmp.Canvas, aryRect[LastPaint]);
  LastPaint := -1;
  End;
end;

Also, i need to make the thing clickable, and so it goes back to unhighlighted when the mouse leaves. Otherwise GREAT JOB!
???
OK
??
I really do not know how to respond to your  TBitmap question, if you do not know a  TBitmap then I can not help you, you need to know more, at least what a TBitmap is ? ?

and you say
"the empty image box empty on mouse over"
and I thought I did a "on mouse over", but what do I know?

I tried to say as plainly as I know how
// you must get the parent Mousemove to resore after leaves the paintbox

do you know what a Parent is?
if your PaintBox in on a Panel, then the "Parent" is a TPanel
if the PaintBox is on a Form, then the parent is a TForm
if the paintbox is on a whatever, then the Parent is a whatever

and I am not sure about your asking  "goes back to unhighlighted when the mouse leaves", I thought I said that the  LastPaint as  -1 is used as the NO-HIGHLIGHT  setting. . . .



procedure TForm1.PaintBox3MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
i: Integer;
InRect: Boolean;
begin
{loop through the TRect Array and see if you in a Rect}
inRect := False;
for i := 0 to High(aryRect) do
  if PtInRect(aryRect[i], Point(X, Y)) then
    begin
    if LastPaint = i then Exit;
  {if you already paint it then exit}
    PaintBox3.Canvas.CopyRect(aryRect[i], BackBmp.Canvas, aryRect[i]);
  {use copyrect  to just draw a portion of the bitmap}
    if (LastPaint > -1) then
      PaintBox3.Canvas.CopyRect(aryRect[LastPaint], FrontBmp.Canvas, aryRect[LastPaint]);
        {Redraw the "Old" highlight to restore}
    LastPaint := i; // set new lastPaint
    inRect := True;
    Break
    end;

if not InRect and (LastPaint > -1) then
  begin
  PaintBox3.Canvas.CopyRect(aryRect[LastPaint], FrontBmp.Canvas, aryRect[LastPaint]);
  LastPaint := -1;
  end;
end;

 - - - - - - - - - - - - - -  --
I guess you don't get what I'm trying to show you?
I looked and looked but I did not see anything about "need to make the thing clickable" before I posted, plwease excuse me. I'm kind of dumb, but what is a "Thing" is that like a hing with a T for type?
The Thing is the rectangle that we created. Its not a delphi command or anything :)
It works. Now I just need to make the Rect have an even when it is clicked. Also I need to make as many Rects at runtime as I need.

Points increased to 300.
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Slick812! Great! Just what I needed!
Damn it.. one last thing. How can I make 1 thing stay selected even when my mouse leaves? Like I click on one of the rectangeles and it changes to yet another image (like the mute button icon... it can have deselected, highlighted, and clicked).

Thanks again!
???, here at EE you are not suppose to keep on and on asking new questions, , that were not part of the original question, you might look at the membership guidlines.

And about your "Questions", if you want the experts here to spend more that 5 minutes to help you, ,  then you might spend more than 5 minutes building and rebuilding your questions, so it gives enough information to let us know how to help you, And we do not need to ask "What is a Thing?"

I did not understand much of your last question, especialy the
"and it changes to yet another image (like the mute button icon"   part

You did not give any info about "When" to set the "Permanent Show" to true. . The following code will use a Record called TRectShow, to keep a boolean value "Show", which will be true if the BackBmp Rect will be shown all the time. I have add a "Click" for the Right mouse button, the usual "Left" click will set the "Show" to true, and the Rect will NOT revert back to the FrontBmp. A :Right" click will set the "Show" to False and the Rect will redraw the FrontBmp Rect on Mouse Out.
Since you seem like you need help, here is some code that may help you -



type
  TRectShow = record // record type to keep Show and Rect info
    Show: Boolean;
    ImgRect: TRect;
    end;


  TForm1 = class(TForm)


  private
    { Private declarations }
    FrontBmp, BackBmp: TBitmap;
    LastPaint: Integer;
    aryRectShow: Array[0..5] of TRectShow; // changed to array of record


procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
// Bitmaps Unchanged here

for i := 0 to 2 do
  begin
  aryRectShow[i].ImgRect := Rect(88 * i,0, (88*i)+70, 100);
  aryRectShow[i].Show := False; // set Show to false
// if Show is True, then the Rect will NOT go back to FrontBmp
  end;
for i := 3 to High(aryRectShow) do
  begin
  aryRectShow[i].ImgRect := Rect(88 * (i-3),128, (88*(i-3))+70 , 228);
  aryRectShow[i].Show := False;
  end;
end;


procedure TForm1.Form1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
// PaintBox Parent OnMouseMove
if (LastPaint > -1) then
  begin
  if not aryRectShow[LastPaint].Show then
    PaintBox3.Canvas.CopyRect(aryRectShow[LastPaint].ImgRect, FrontBmp.Canvas, aryRectShow[LastPaint].ImgRect);
  LastPaint := -1;
  End;
end;


procedure TForm1.PaintBox3Paint(Sender: TObject);
var
i: Integer;
begin
PaintBox3.Canvas.Draw(0,0, FrontBmp);
// ADD a test for Show to paint the Rects
for i := 0 to High(aryRectShow) do
  if aryRectShow[i].Show then
    PaintBox3.Canvas.CopyRect(aryRectShow[i].ImgRect, BackBmp.Canvas,
                              aryRectShow[i].ImgRect);

end;



procedure TForm1.PaintBox3MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
i: Integer;
InRect: Boolean;
begin
InRect := False;
for i := 0 to High(aryRectShow) do
  if PtInRect(aryRectShow[i].ImgRect, Point(X, Y)) then
    begin
    InRect := True;
    if LastPaint = i then Exit;
    if not aryRectShow[LastPaint].Show then // test for Show
      PaintBox3.Canvas.CopyRect(aryRectShow[i].ImgRect, BackBmp.Canvas, aryRectShow[i].ImgRect);
    if (LastPaint > -1) and (not aryRectShow[LastPaint].Show) then
      PaintBox3.Canvas.CopyRect(aryRectShow[LastPaint].ImgRect, FrontBmp.Canvas, aryRectShow[LastPaint].ImgRect);
    LastPaint := i;
    Break
    end;

if (not InRect) and  (LastPaint > -1) then
  begin
  if not aryRectShow[LastPaint].Show then // test for Show
  PaintBox3.Canvas.CopyRect(aryRectShow[LastPaint].ImgRect, FrontBmp.Canvas, aryRectShow[LastPaint].ImgRect);
  LastPaint := -1;
  end;
end;



procedure TForm1.PaintBox3MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
i: Integer;
Pt1: TPoint;
begin
{I have added a Right AND Left Click event
The left click will make the Rect permament, by setting Show to True.
The Right click will make the Rectangle Hide, by setting Show to False}

if Button = mbMiddle then Exit;
for i := 0 to High(aryRectShow) do
  if PtInRect(aryRectShow[i].ImgRect, Point(X, Y)) then
    begin
    Label1.Caption := 'Click on rect '+IntToStr(i);
    if Button = mbLeft then  // added Left Button test
      begin
      aryRectShow[i].Show := True; // will Permanetly show rect i
      case i of
        0: Label2.Caption := 'Ha Ha Ha, the Zero was clicked';
        1: ShowMessage('The Rectangle Clicked was  ONE !');
        2: Label2.Caption := 'What Happend? Got Clicked';
        3: ShowMessage('Number 3 was clicked');
        4: Label2.Caption := 'This was a Four Click';
        5: ShowMessage('5 clicked');
        end;
      // code below is nessary for a "Pop Up" like a message box, because
      // it will be Modal and the rect will not redraw
      Pt1 := PaintBox3.ScreenToClient(Mouse.CursorPos);
      if not PtInRect(aryRectShow[i].ImgRect, Pt1) then
        begin
        if not aryRectShow[i].Show then // test for Show
        PaintBox3.Canvas.CopyRect(aryRectShow[i].ImgRect, FrontBmp.Canvas, aryRectShow[i].ImgRect);
        LastPaint := -1;
        end;
      end;

    if Button = mbRight then // added Right Button test
      aryRectShow[i].Show := False; // will hide rect i on mouse out

    Break;
    end;
end;

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
you have all of the methods needed I think, you might try and useing them and getting to know what they do (in order to find ways to paint what you want when you want it), If you want a "MouseDown" Third Image, then have a Third Bitmap and draw that Rect of the Third Bitmap in the "OnMouseDown"  event of the of the Paintbox.

I may not add anymore to this question. . .

Good Luck
Slick812,
If I give you an extra 90 points, could you modify the code to have only some of the rectangles clickable, and have a different picture when I click on the image?

Thanks again,
David Burban
Maybe I should explain the question better: I want to have a image (1), and when my mouse goes over it it should turn selected (2). But when I click on it and hold, it should turn dark (3). Also I need to have only one or two rectangles that remember if you clicked on them; the others should just be mouse over and dark when clicked on. But the ones that I clicked on and remember, they should display another image.

For example: you have a mute button. The button is deselected when a mouse is not over it. The button is highlighted when the mouse is over it. The button should turn dark when I click and hold my mouse over it. And when I let go of the mouse it should turn to another image (in this example a speaker icon with a red X over it). And when I click again it should return to normal (I guess since I clicked on it, and the mouse is still over it, it should be to the highlited state).

Thanks again,
David Burban
???

you can use Boolean values in your Record to keep information on what you need that particular Rectangle to do, I have already shown you about One Boolean value called "Show", you can add as many Boolean values as you need to this record

TRectShow = record // record type to keep Show and Rect info
    Show: Boolean;
    StayDark: Boolean;
    RememberClickOn: Boolean;
    UseOtherImageForMouseMove: Boolean;
    UseImage3ForMouseDown: Boolean;
    UseImage7ForMouseUp: Boolean;
    AsManyBooleanValuseAsYouNeed: Boolean;
    ImgRect: TRect;
    end;

you will need to set and test for these Boolean values as you need in your requirements of the image rectangle,

you can also place Other Information variables in your Record, to give you the data you need for a draw operation, you can place a second TRect, for an alternate Location on some other bitmap, you can have Integer variable and keep the number of an Image, or any numerical information that might help you, ,or a TPoint variable
I believe I posted a workable solution on 07/18, one that has been ignored. I'm baffled as to why this thread is still going on, aftr points were awarded. It's probably time for a new question.
Slick812,
Could I get some code like the one you made on 7/18 for this? So basically I need 3 states of images: nonhighlighted, highlited, and down. And then when I click on only 1 of the 14 rectangles, that one should turn to another picture.

You'll get 100pnts for a working example :)

sftweng: the code you made on 7/18 takes 30 seconds to load. That is unacceptable.

Thank you,
David Burban
I agree with sftweng about the never ending thread here, this is NOT what the EE guidelines allow. . . so I will follow the guidelines and not post here any more, , , ,

the_modder
you can ask another question about this and give this EE question web address as a reference for the code you need to change. OR better, show some of your code, that you have tried and ask for fixes
You question said nothing about performance requirements, though I did comment that optimization was a  possibility - you seem to have ignored that.
Slick812,
I hate creating two threads on exactly the same topic. This allows for clutter on EE.

sftweng,
Ok. I have two peices of code. One that is slow (yours) and one that is fast and does almost all that I need (Slick182's). Guess who will get awarded the points? I should not have to rewrite the worse code (yours) and then give you points for it.
I don't care about the points. I care about your laziness.
LOL @ sftweng.... my lazy? LOL. Its you who was lazy and didn't bother making the code work properly and quickly.
the_modder, if you will look at the following (much faster) procedure modified from my original posting, you'll see how simple it would have been for YOU to make the necessary performance improvement. Don't expect everything to be handed to you on a silver platter; you're eventually going to have to learn how to do research of your own.

procedure TForm1.CopyRegion(Target : TImage; Source : TImage;
                         top, left, height, width : Integer);
var
  row, col : Integer;
begin
  { There are faster ways of doing this but it's up to you to optimize}
  { if you want to do so. }
//  for row := top to top+height do
//    for col := left to left+width do
//    begin
//      target.Canvas.Pixels[col,row] := source.Canvas.Pixels[col,row];
//    end;
  BitBlt(Target.Canvas.Handle,left,top,width,height,
         Source.Canvas.Handle,left,top,SRCCOPY);
  Target.Repaint;
end {CopyRegion};
Of course, even better, to minimize flicker and only repaint the changed area:

procedure TForm1.CopyRegion(Target : TImage; Source : TImage;
                         top, left, height, width : Integer);
var
  row, col : Integer;
  rect : PRect;
begin
  { There are faster ways of doing this but it's up to you to optimize}
  { if you want to do so. }
//  for row := top to top+height do
//    for col := left to left+width do
//    begin
//      target.Canvas.Pixels[col,row] := source.Canvas.Pixels[col,row];
//    end;
  BitBlt(Target.Canvas.Handle,left,top,width,height,
         Source.Canvas.Handle,left,top,SRCCOPY);
//  Target.Repaint;
  New(rect);
  TRY
    rect.Left := left;
    rect.Top := top;
    rect.Right := left+width;
    rect.Bottom := Top+height;
    InvalidateRect(self.Handle,rect,true);
  FINALLY
    Dispose(rect);
  END {TRY - FINALLY};

end {CopyRegion};
Now, if it turns out that you like this code and use it, the gentlemanly thing to do would be to make a "Points for sftweng" question awarding extra points for extra effort. :-)
Sorry sftweng, the code works like an eraser. First when I mouseover the images it removes the selected image I put on top, but it does not return when the mouse leaves. Also your code lacks boxes for multiple places to click.
I was not attempting to solve your entire problem; there was too much requirement drift for that. I thought you'd like to see a way to speed up the graphics, however. As to the "eraser" effect, I have an application running with this code that has a daytime image of North America preloaded into Image1 and Image2 and a nightime image in Image3. When the mouse moves, a small square shows the "underlying" nightime image and reverts correctly to the daytime image when it leaves. As to boxes, all that is required is a little modulo arithmetic on the X,Y coordinates.
Also your code takes 30 seconds to initialize. Slick182's code is instantaneous.
That's because Delphi is slow loading up the resource file (preloaded images). A LoadFromFile would change that. Using Slick182's code as the base, just switch from CopyRect to BitBlt and you'll probably find a performance improvement.