Thread: Accessing Array

    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    21
    Rep Power
    0

    Accessing Array


    Hello all, I have a problem, I want to count how many Array I've made by using a Timer (I must use Timer) and show them using an EditText..

    Note : If I use 7 Array of Shape, then when the Shape2.Left is the same as the first Array of Shape's Left, EditText become 1,, then when the Shape2.Left is the same as the second Array of Shape's Left, EditText become 2,, and so on for the third, fourth, fifth, etc..

    What must I add at the Timer?

    Here is my Listing Program :

    var
    Form1: TForm1;
    Shape : array[1..12] of TShape;
    g : integer;;

    implementation
    {$R *.DFM}

    procedure TForm1.Timer2Timer(Sender: TObject);
    begin
    Shape2.Visible := True;
    Shape2.Left := Min(Shape2.Left+1, Image3.Left+22);
    // ??? //
    end;

    procedure TForm1.BitBtn1Click(Sender: TObject);
    var
    d, kiri : integer;
    begin
    if (Image1.Hint = 'Connector') AND (Image2.Hint = 'Connector') then
    begin
    g:= ((Image3.Left+22)-104) DIV 60;
    kiri := 104;
    for d := 1 to g do
    begin
    Shape[d] := TShape.Create(Self);
    with Shape[d] do
    begin
    kiri := kiri + 60;
    parent := Panel1;
    width := 1;
    height := 8;
    left := kiri;
    top := 139;
    show;
    end;
    end;
    end
    else if (Image1.Hint = 'Connector A') AND (Image2.Hint = 'Connector') then
    begin
    a:= ((Image1.Left+22)-104) DIV 60;
    b:= ((Image3.Left+22)-(Image1.Left+22)) DIV 60;
    g:= a+b;
    kiri := 104;
    for d := 1 to g do
    begin
    Shape[d] := TShape.Create(Self);
    if (((Image1.Left+22)-kiri) < 60) AND (((Image1.Left+22)-kiri) > 0) then
    kiri := (Image1.Left+22);
    with Shape[d] do
    begin
    kiri := kiri + 60;
    parent := Panel1;
    width := 1;
    height := 8;
    left := kiri;
    top := 139;
    show;
    end;
    end;
    end
    else if (Image1.Hint = 'Connector') AND (Image2.Hint = 'Connector A') then
    begin
    a:= ((Image2.Left+22)-104) DIV 60;
    b:= ((Image3.Left+22)-(Image2.Left+22)) DIV 60;
    g:= a+b;
    kiri := 104;
    for d := 1 to g do
    begin
    Shape[d] := TShape.Create(Self);
    if (((Image2.Left+22)-kiri) < 60) AND (((Image2.Left+22)-kiri) > 0) then
    kiri := (Image2.Left+22);
    with Shape[d] do
    begin
    kiri := kiri + 60;
    parent := Panel1;
    width := 1;
    height := 8;
    left := kiri;
    top := 139;
    show;
    end;
    end;
    end
    else if (Image1.Hint = 'Connector A') AND (Image2.Hint = 'Connector B') then
    begin
    a:= ((Image1.Left+22)-104) DIV 60;
    b:= ((Image2.Left+22)-(Image1.Left+22)) DIV 60;
    f:= ((Image3.Left+22)-(Image2.Left+22)) DIV 60;
    g:= a+b+f;
    kiri := 104;
    for d := 1 to g do
    begin
    Shape[d] := TShape.Create(Self);
    if (((Image1.Left+22)-kiri) < 60) AND (((Image1.Left+22)-kiri) > 0) then
    kiri := (Image1.Left+22);
    if (((Image2.Left+22)-kiri) < 60) AND (((Image2.Left+22)-kiri) > 0) then
    kiri := (Image2.Left+22);
    with Shape[d] do
    begin
    kiri := kiri + 60;
    parent := Panel1;
    width := 1;
    height := 8;
    left := kiri;
    top := 139;
    show;
    end;
    end;
    end
    else if (Image1.Hint = 'Connector B') AND (Image2.Hint = 'Connector A') then
    begin
    a:= ((Image2.Left+22)-104) DIV 60;
    b:= ((Image1.Left+22)-(Image2.Left+22)) DIV 60;
    f:= ((Image3.Left+22)-(Image1.Left+22)) DIV 60;
    g:= a+b+f;
    kiri := 104;
    for d := 1 to g do
    begin
    Shape[d] := TShape.Create(Self);
    if (((Image1.Left+22)-kiri) < 60) AND (((Image1.Left+22)-kiri) > 0) then
    kiri := (Image1.Left+22);
    if (((Image2.Left+22)-kiri) < 60) AND (((Image2.Left+22)-kiri) > 0) then
    kiri := (Image2.Left+22);
    with Shape[d] do
    begin
    kiri := kiri + 60;
    parent := Panel1;
    width := 1;
    height := 8;
    left := kiri;
    top := 139;
    show;
    end;
    end;
    end;
    end;
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    350
    Rep Power
    7
    Originally Posted by ClaVahnz
    I want to count how many Array I've made by using a Timer (I must use Timer) and show them using an EditText..
    I'm not sure I understand what you are asking for. You say you want to count how many arrays you've made, but that doesn't make sense. You have only one (1) array, consisting of 12 elements of type TShape, count as often as you wish but there is still nothing more than 1 array.

    Are you asking to count how many TShape objects you've created and to display that number in a TEdit Control? And if so, then accomplishing that within a Timer event is less than optimal, and may lead to erroneous results (at least until the timer fires to update the count).
    Last edited by majlumbo; May 3rd, 2013 at 10:24 AM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    21
    Rep Power
    0
    Originally Posted by majlumbo
    I'm not sure I understand what you are asking for. You say you want to count how many arrays you've made, but that doesn't make sense. You have only one (1) array, consisting of 12 elements of type TShape, count as often as you wish but there is still nothing more than 1 array.

    Are you asking to count how many TShape objects you've created and to display that number in a TEdit Control? And if so, then accomplishing that within a Timer event is less than optimal, and may lead to erroneous results (at least until the timer fires to update the count).
    Sorry my mistake.. Yes you are right,, I want to count how many objects I've been made..

    I must do the count in timer because I need to send my calculation to a chart..
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    350
    Rep Power
    7
    Originally Posted by ClaVahnz
    Sorry my mistake.. Yes you are right,, I want to count how many objects I've been made..
    So this is doable

    Originally Posted by ClaVahnz
    I must do the count in timer because I need to send my calculation to a chart..
    I still would not do this via a timer. Timer will continue to fire even if you don't create a shape.

    I'd say you should actually alter the TShape Object to include the ability to track when it is created and when it is destroyed, and update your count on those events.

    There are a few problems with that approach, but they can be overcome.

    1) Instead of creating a TShape, you would define your own shape (Say TMyShape) so everywhere you have
    Code:
    Shape[d] := TShape.Create(Self);
    you'd replace it with
    Code:
    Shape[d] := TMyShape.Create(Self);
    Also
    Code:
    Shape : array[1..12] of TShape;
    becomes
    Code:
    Shape : array[1..12] of TMyShape;
    2) You'd need to send a message to your TMyShape, but a TShape doesn't have a Handle so we would need to give it one.

    So here's the solution:

    before your form's Type section, add a new Message Constant that will signify your message, which will be an AFTERCREATE.

    Code:
    const
       WM_MYSHAPE_AFTERCREATE = WM_USER + 1;
    now within the Type section you can add your own shape based on TShape, and give this new version the new events of AfterCreate and OnDestroy and the ability to get a Handle
    Code:
    TMyShape = Class(TShape)
    private
      fOnAfterCreateEvent: TNotifyEvent;
      fOnDestroyEvent: TNotifyEvent;
    public
      fHandle: HWND;
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
      procedure ReadMessage(var Msg: TMessage);
    published
      property OnAfterCreate: TNotifyEvent read fOnAfterCreateEvent write fOnAfterCreateEvent;
      property OnDestroy: TNotifyEvent read fOnDestroyEvent write fOnDestroyEvent;
    end;
    
    TForm1 = Class(TForm) <<--do not add this it is already there
    Now you have to define your new TMyShape after the implementation section
    Code:
    implementation
    
    constructor TMyShape.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      fHandle := AllocateHWnd(ReadMessage);
      //create windows handle to allow receiving message
      PostMessage(fHandle, WM_MYSHAPE_AFTERCREATE, 0, 0);
      //post a message to your shape using fHandle after it is created
    end;
    
    destructor TMyShape.Destroy;
    begin
      DeallocateHWnd(fHandle);
      if Assigned(fOnDestroyEvent) then
        fOnDestroyEvent(Self);
      inherited;
    end;
    
    procedure TMyShape.ReadMessage(var Msg: TMessage);
    begin
      if Msg.Msg = WM_MYSHAPE_AFTERCREATE then
        if Assigned(fOnAfterCreateEvent) then
          fOnAfterCreateEvent(Self);
    end;
    Now your TMyShape knows when it is created and when it is destroyed

    So now your form can use these events, so alter your form's declaration to include an event handler for the OnAfterCreate and the OnDestroy event like.

    Code:
    TForm1 = class(TForm)
      ...
    private
      procedure MyShapeAfterCreate(Sender: TObject); <--Add this
      procedure MyShapeDestroy(Sender: TObject);<--Add this
      ..
    end;
    Now add those methods to your form.
    Code:
    procedure TForm1.MyShapeAfterCreate(Sender: TObject);
    begin
       Edit1.Text := IntToStr(StrToIntDef(Edit1.Text, 0) + 1);
       //use the event to track the increment in count.
       //you also mentioned sending results to a chart,
       //do so here rather than a timer
    end;
    
    procedure TForm1.MyShapeDestroy(Sender: TObject);
    begin
       Edit1.Text := IntToStr(StrToInt(Edit1.Text) - 1);
      //use the event to track the decrement in count
       //you also mentioned sending results to a chart,
       //do so here rather than a timer
    end;
    so now you have to change your array to TMyShape rather than TShape and after your create one, set the onaftercreate and the ondestroy handlers
    Code:
    var
       Shape : array[1..12] of TMyShape;
    
    ....
      Shape[d] := TMyShape.Create(Self);
      with Shape[d] do
      begin
        OnAfterCreate := MyShapeAfterCreate;
        OnDestroy := MyShapeDestroy;
        kiri := kiri + 60;
        parent := Panel1;
        ...
      end;
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    21
    Rep Power
    0
    Hmm,, I'm confused here...

    But, thanks for the answer, I'll try...
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    350
    Rep Power
    7
    Just take it one step at a time.

    The point is that you are altering the TShape to know when it is created and destroyed, and to attach a method to those events. In those events, you can inc/dec your count.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    21
    Rep Power
    0
    Originally Posted by majlumbo
    Just take it one step at a time.

    The point is that you are altering the TShape to know when it is created and destroyed, and to attach a method to those events. In those events, you can inc/dec your count.
    Ok then majlumbo, thanks for the explanation..

    But could you please help me with my problem at the TChart Thread..
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2012
    Posts
    151
    Rep Power
    3
    You could have initialize your array's members to nil. And in the timer all you need to count is its non-nil members, and voila! You get how many TShape you have created so far. Of course you need to also nil the array member when associated TShape was destroyed.

    Easy.

IMN logo majestic logo threadwatch logo seochat tools logo