Solved

What TStatusPanel clicked in TStatusBar

Posted on 1998-05-29
13
406 Views
Last Modified: 2010-04-06
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.
0
Comment
Question by:tomcorcoran
  • 6
  • 4
  • 3
13 Comments
 
LVL 1

Expert Comment

by:Edo082297
ID: 1349215
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
 
LVL 1

Expert Comment

by:Edo082297
ID: 1349216
You had better cut and paste the above code, this font does not differentiate between i and j very much!
0
 

Author Comment

by:tomcorcoran
ID: 1349217
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
 
LVL 3

Accepted Solution

by:
rickpet earned 50 total points
ID: 1349218
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
 

Author Comment

by:tomcorcoran
ID: 1349219
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
 

Author Comment

by:tomcorcoran
ID: 1349220
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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:tomcorcoran
ID: 1349221
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
 
LVL 3

Expert Comment

by:rickpet
ID: 1349222
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
 
LVL 1

Expert Comment

by:Edo082297
ID: 1349223
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
 

Author Comment

by:tomcorcoran
ID: 1349224
Yes, it seems like there is no elegant solution. Unfortunaelty through the limits of this system this question is now closed. Tom.
0
 
LVL 3

Expert Comment

by:rickpet
ID: 1349225
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
 

Author Comment

by:tomcorcoran
ID: 1349226
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
 
LVL 1

Expert Comment

by:Edo082297
ID: 1349227
>"...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

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now