What TStatusPanel clicked in TStatusBar

When a user double clicks on a Tstatusbar is there an easy way of knowing what TStatusPanel they clicked on? That way one could essentially assign OnDoubleClick events, etc, to each TStatusBar by checking what TSatusPanel they clicked first. This would seem to be the downside of TStatusBar, a reason to stick using groups of panels. Thanks, Tom.
boardtcAsked:
Who is Participating?
 
rickpetCommented:
Tom...

There is an easy way to always distinguish one component from another...Inprise (Borland) gave you  a nice property called Tag.
Set each TStatusBar to a unique value.  Then you can write one event handler and

Case (Sender as TStatusBar).Tag of
  0:...
  1:...
  2:...


Rick
0
 
Edo082297Commented:
Hi Tom,
  Here is a way to know what panel the user clicked on. What we do is to check the X coordinate OnMouseDown and then we add up the width of each panel until we know what panel the X coordinate falls into. This is not great code, however. You really should derive a new component for what you want to do.
   I leave it up to you to implement the same thing for the double click event and the like. If you have any questions, I will be glad to help you further.

HTH

Edo

procedure TForm1.StatusBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  i, j, WidthIndex : integer;
begin

  for i := 0 to (StatusBar1.Panels.Count - 1) do
  begin
    WidthIndex := 0;

    for j := 0 to i do
      WidthIndex := (WidthIndex + StatusBar1.Panels.Items[j].Width);

    if X <= WidthIndex then
    begin
      showmessage ('You clicked panel ' + IntToStr(i));
      Break;
    end;
  end;
end;
0
 
Edo082297Commented:
You had better cut and paste the above code, this font does not differentiate between i and j very much!
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
boardtcAuthor Commented:
This system frustrates me, I'd like to be able to award points and leave it open...

Sorry, I should have said that I had considered a solution like this and was wondering if there was a sweeter way.

Thanks, Tom.
0
 
boardtcAuthor Commented:
I just finished using tags in creating TMenuItems at run-time for the pages of a TPageControl. Why didn't I think of that. Thanks a lot, Tom.
0
 
boardtcAuthor Commented:
I just finished using tags in creating TMenuItems at run-time for the pages of a TPageControl. Why didn't I think of that? Thanks a lot, Tom.
0
 
boardtcAuthor Commented:
RickPet. That doesn't work - the TStatusPanel doesn't have a tag property (I assume that was what you meant). How do I reopen the question? Tom.
0
 
rickpetCommented:
Try this one...Sorry about that...was a sleep on the last one...

Rick

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, TypInfo;

type
  TForm1 = class(TForm)
    StatusBar1: TStatusBar;
    procedure StatusBar1DblClick(Sender: TObject);
    procedure StatusBar1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation
type
{$M+}
   spPanel = (spOne, spTwo, spThree);
{$M-}
var
  Panel: spPanel;
{$R *.DFM}

procedure TForm1.StatusBar1DblClick(Sender: TObject);
begin
  Case Panel of
    spOne: ShowMessage(GetEnumName(TypeInfo(spPanel), ord(spOne)));
    spTwo: ShowMessage(GetEnumName(TypeInfo(spPanel), ord(spTwo)));
    spThree: ShowMessage(GetEnumName(TypeInfo(spPanel), ord(spThree)));
  end;
end;

procedure TForm1.StatusBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  i, inStart: integer;
begin
  inStart := 0;
  Panel := spOne;
  for i := 0 to ord(high(spPanel))-1 do
    begin
      if (X >= instart) and (X <= instart + StatusBar1.Panels.items[i].Width) then
        exit
      else
      begin
        inc(Panel);
        instart := instart + StatusBar1.Panels.items[i].Width;
      end;
    end;
end;

end.
0
 
Edo082297Commented:
I am disappointed.  
  RickPet's answer is a complex and worse version of exactly what I already posted. I don't think there is any advantage to the code either, other than confounding the sorry programmer who has to modify that code. Additionally, what if there are more than 3 panels? You had better write a case statement with at least 10 panels. (Oh no! The requirements changed). My solution works with ANY number of panels, and additionally doesn't require bizarre declarations.
  Sorry to be a party pooper.

Edo
0
 
boardtcAuthor Commented:
Yes, it seems like there is no elegant solution. Unfortunaelty through the limits of this system this question is now closed. Tom.
0
 
rickpetCommented:
actually I find it easier to code than
having to modify...an array of panels or some other solution...it works very similar to the tag value.  Basically on the mouse down you are assigning a value like the tag value.

I use something similar when working with TPageControls.  Because now I know what the link is between my Panels.  I'll I have to do is keep the enumerated types in the correct order(A very simple and intuitive process).  At anytime that I change the panels.  I'll I have to modify is  the enumerated types, and any new panels that I may want to add code for...Actually if you want to be serious your solution would be more of a headache to upkeep.  Evertime I want to add a panel I would have to check out where it is in the list and add the code...If I had to reorder the panels I would have to reorder all my code...With my solution I'll you have to do is reorder the enumerated types if the panel order changes or add any adition code for the panel for any new enumerations.

Also your's doesn't work with double click...mine does...and yours can't be expanded without a major hack...mine will easily port over to a click or any other mouse event...

Note...you don't need the {$M+} or getEnumName...that was just added to show that you can easily get the enumerated string names if you want them...

Rick
0
 
boardtcAuthor Commented:
Rick, Thanks for taking the time. At the moment there is no real reason for me to change my multi TPanel implementatio I think. Tom.
0
 
Edo082297Commented:
>"...Evertime I want to add a panel I would have to check out >where it is in the list and add the code..." :

Instead of the line that reads:
showmessage ('You clicked panel ' + IntToStr(i));

Put:
  DispatchAMethod(i : integer);
 
  Dispatch whatever you want for the first, second, or nth panel.

or:
  case i of
    1 : Panel1Method;
    2 : Panel2Method;
  end;

This is the same difference.


"Also your's doesn't work with double click...mine does...":

Yours doesn't work with single click. (...Sorry about that...was a sleep on the last one... ). For EITHER case, any two year old can select the same event handler (click) for the OnDoubleClick event.

"...and yours can't be expanded without a major hack...":

Are you joking? Your way is tied to a particular number of panels. Mine isn't. You have to declare a new enumerated type. (An enumerated type? To find out what panel was clicked?) Your method involves 26 lines of head scratching code versus 17 obvious lines. It does the job: what TStatusPanel was clicked on? After that it is up to the user to do what he will.

Think about it: if you were going to write a component, wouldn't you expose a PanelNumber property, and in a descended OnClick provide the user with the PanelNumber as part of the procedure's signature, to do what they will?

And you wanted to use the (absent) tag property? The tag property is akin to goto statement. There is nothing that tag can accomplish better than solid code.

End of discussion.

My email address is egarson@hotmail.com if you would like to discuss this any further (I am always interested in discussing style). I will not be returning to this thread.

Edo
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.