Solved

Revealing the current application/object event

Posted on 2004-03-30
21
647 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
  • 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
 

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
Free Trending Threat Insights Every Day

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.

 
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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
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…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

743 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