Solved

Revealing the current application/object event

Posted on 2004-03-30
21
676 Views
Last Modified: 2010-04-05
I'm creating an application that generates a "treeView" index based on field values in an ADO table. When form is created, certain user-based object events are fired, such as the treeView's "onChange".

How can I test if the current event is fired because of user-action, or if it's fired by the form being created? I looked up "tBasicAction" in the Help, but it didn't clear up the matter, and I can't find how to reveal a current event or the event-source. (The event-model is not that defined).

Thank you, in advance
0
Comment
Question by:ConceptSysInc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
  • 3
  • +1
21 Comments
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10720868
"How can I test if the current event is fired because of user-action, or if it's fired by the form being created?"

UMMMMM, there would be no No user action until after form is created....

Shane
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10720902
?? usual i have a global var

var treefilling : boolean;

then i have a loadtree-proc

procedure TFormX.LoadTree;
begin
  TreeFilling := True;
  //fillingAction
  TreeFilling := False;
end;

and in any event, which may triggered by filling the tree i have

procedure TFormX.TreeviewXChange(sender : TObject; Node : TTreeNode);
begin
  if not TreeFilling then
  begin
     //useraction
  end;
end;

meikl ;-)
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10720920


 Ahhhhhh, not on form creation, he wanted it on Tree creation.... <Smile>

Shane

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ConceptSysInc
ID: 10721299
Let me clarify: for example, there is code in the "onChange" that issues a SQL query for records that fall under the selected treeNode (based associated treeNode data). However, when the form is created, the "onChange" event fires, and surely references to specific objects are null-and-void.

What's needed is a CASE or IF statement that tests the event - ie, if the formis being created, then <do this>; if the user selects a treeNode, then <do that>. The problem for me is capturing and interpreting the event and/or message generated in any event.

Kretz, you method will work but it doesn't reveal anything about the Delphi's event-model (but if there is no true answer, then I'll slide the points to you)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721376
well,

do you have predefined nodes?
if so, the first change-event comes,
if the tree gets the focus, because its the activecontrol

is it such construction you could solve it this way

interface

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

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
  private
    isNotFirst : Boolean; //defaults to False
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}



procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
  if isNotFirst then
    showmessage('Change fired for Node '+Node.Text)
  else
    isNotFirst := True;
end;

end.

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721438
btw. at which time you have a properly filled data-entry
(just asking because this event is just fired after the form is created, not during creating of the form)

meikl ;-)
0
 

Author Comment

by:ConceptSysInc
ID: 10721471
Meikl,

the tree is NOT pre-defined; it is populated from a queried SQLserver-based dataset. Referencing changes in the nodes is no problem for me to code - it's knowing what events and messages are being generated that's the problem. (PARADOX was great for situations like this because you always knew what was going on behind the application).

If this is too "internal", then do you know of any DELPHI sites (or even books) that go into the ying-and-yang of database processing and development with Delphi?
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721498
well, next question,

do u use the standard-treeview or any other third-party tree?
(i know, that the virtualStringTree fires this onChange-event also by adding Nodes, whereas the standard-treeview does not do this)

meikl ;-)
0
 

Author Comment

by:ConceptSysInc
ID: 10721535
sorry, no third-party components...

Call me crazy but I figured anything with tObject inheritance should have methods that reveal the object's events. (I was reading about the tBasicAction class but there isn't aren't any good examples or explanations on it's use).
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721611
courious,
just asking myself why you have porblems,
there should be no one

can you show, how you do fill your tree?

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721621
an older sample,
(Node-amount and Tree-Depth and ID/ParentID order doesn't matter)


unit loadtree_u;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, Mask, DBCtrls, ADODB, ComCtrls;

type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    TreeView1: TTreeView;
    ADOTable1: TADOTable;  //Here are done the Changes
    ADOTable1Id: TAutoIncField;
    ADOTable1Id_Parent: TIntegerField;
    ADOTable1Description: TWideStringField;
    ADOTable1Value: TIntegerField;
    Label1: TLabel;
    DBEdit1: TDBEdit;
    DataSource1: TDataSource;
    Label2: TLabel;
    DBEdit2: TDBEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure TreeView1Deletion(Sender: TObject; Node: TTreeNode);
  private
    Procedure Load_Tree;  //Load the Tree, also use for Refresh_Tree
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Type
  PDataCacheRecord = ^TDataCacheRecord;
  TDataCacheRecord = Record
                       ID  : Integer;
                       PID : Integer;
                       Text: String[50];
                     end;

function FindParent(ATreeView : TTreeView; ID : Integer) : TTreeNode;
var i : integer;
begin
  result := nil;
  i := 0;
  while (i < ATreeView.Items.Count) and
        (assigned(ATreeView.Items[i].Data)) and
        (PDataCacheRecord(ATreeView.Items[i].Data)^.ID <> ID) do
    inc(i);
  if i < ATreeView.Items.Count then
    result := ATreeView.Items[i];
end;


Procedure TForm1.Load_Tree;
var
  ANode : TTreeNode;
  RecordCache : PDataCacheRecord;
  RecordCacheList : TList;
  I, PreviousCount : Integer;
begin
  TreeView1.Items.Clear;
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'Select ID, ID_Parent, Description from Tree_Table Order by Id_Parent';
  RecordCacheList := TList.Create;
  try
    ADOQuery1.Open;
    //Cache Data
    while not ADOQuery1.Eof do
    begin
      RecordCache := New(PDataCacheRecord);
      RecordCache^.ID := ADOQuery1.FieldByName('ID').AsInteger;
      RecordCache^.PID := ADOQuery1.FieldByName('ID_Parent').AsInteger;
      RecordCache^.Text := ADOQuery1.FieldByName('Description').AsString;
      RecordCacheList.Add(RecordCache);
      ADOQuery1.Next;
    end;
    ADOQuery1.Close;
    //Adding Roots
    PreviousCount := RecordCacheList.Count;
    i := 0;
    While i < RecordCacheList.Count do
    begin
      If PDataCacheRecord(RecordCacheList.Items[i])^.PID = 0 then //RootEntry
      begin
        ANode := TreeView1.Items.AddChild(NIL,PDataCacheRecord(RecordCacheList.Items[i])^.Text);
        ANode.Data := RecordCacheList.Items[i];
        RecordCacheList.Delete(i);
      end
      else inc(i);
    end;
    //Adding Childs
    //Loop until there is nothing or it is never reduced -> inkonsistence
    While (RecordCacheList.Count > 0) and (PreviousCount <> RecordCacheList.Count) do
    begin
      i := 0;
      PreviousCount := RecordCacheList.Count;
      while i < RecordCacheList.Count do
      begin
        ANode := FindParent(TreeView1,PDataCacheRecord(RecordCacheList.Items[i])^.PID);
        if Anode <> NIL then
        begin
          ANode := TreeView1.Items.AddChild(ANode,PDataCacheRecord(RecordCacheList.Items[i])^.Text);
          ANode.Data := RecordCacheList.Items[i];
          RecordCacheList.Delete(i);
        end
        else inc(i);
      end;
    end;
    if RecordCacheList.Count > 0 then
      raise exception.Create('Data-Inkonsistence Detected!');
  finally
    RecordCacheList.Free;
  end;
end;

//Load
procedure TForm1.Button1Click(Sender: TObject);
begin
  ADOTable1.Close;
  Load_Tree;
  ADOTable1.Open;
  TreeView1.Selected := TreeView1.TopItem;
end;

//Navigate
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
  if ADOTable1.Active then
    ADOTable1.Locate('ID',PDataCacheRecord(Node.Data)^.ID,[]);
end;

//avoid memoryLeak
procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
  If assigned(Node.Data) then
    Dispose(PDataCacheRecord(Node.Data));
end;

end.

meikl ;-)
0
 

Author Comment

by:ConceptSysInc
ID: 10721656
I fill it the same as you did, pretty much: query the database; while-not-EOF through the recordSet, doing an "... items.add" to the tree.

the problem is that the "onChange" event keeps firing, invoking the code, prior to the tree being populated and the form displayed
0
 

Author Comment

by:ConceptSysInc
ID: 10721705
For now, I have a quick-fix -

the best I can come up with is using the treeView's "selText" property: the SelText property is only valid when the combo box has focus; when the combo box does not have focus, reading SelText always yields an empty string and setting it inserts the text at the cursor rather than replacing the selected text. So if I use an "IF"-statement at a critical point in the "onChange" procedure, I can know if the node was [actually] selected, or if the event was called by something... non-user related.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10721838
well, thats a workaround :-)
(you see in my sample above,
that i determine this on the adotable.active-property)

just to say,
that the treeview doesn't care about properly filled data,
-> means you have to care about this

meikl ;-)
0
 

Author Comment

by:ConceptSysInc
ID: 10866732
this question can be closed since I was NOT able to find a more suitable solution than the one I  am already using
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10866797
i'm unsure to agree with this
0
 

Author Comment

by:ConceptSysInc
ID: 10871435
the thrust of the question was how to "branch" the processing during the initial creation of the form - while your suggested solution and source code show how to populate the tree: that's a "no-brainer", and I already have that coded!

after more trial-and-error, I found the solution to the question/issue is to test whether the tree contains any objects or "nodes"; ie, this is done by an IF-statement that asks whether "... the treeview.componentCount equals zero" - if it's zero, then break; otherwise, you've started the form-creation process, and the inherited objects exists

I just figured that since I came up with this solution on my own, there was no need to keep this question OPEN
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10871499
Lets see the solution posted here....

listening...

Shane
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 13276093
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses
Course of the Month9 days, 7 hours left to enroll

623 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