Avatar of ConceptSysInc
ConceptSysInc

asked on 

Revealing the current application/object event

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
Delphi

Avatar of undefined
Last Comment
modulo
Avatar of shaneholmes
shaneholmes

"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
Avatar of kretzschmar
kretzschmar
Flag of Germany image

?? 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 ;-)
Avatar of shaneholmes
shaneholmes



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

Shane

Avatar of ConceptSysInc
ConceptSysInc

ASKER

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)
Avatar of kretzschmar
kretzschmar
Flag of Germany image

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 ;-)
Avatar of kretzschmar
kretzschmar
Flag of Germany image

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 ;-)
Avatar of ConceptSysInc
ConceptSysInc

ASKER

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?
Avatar of kretzschmar
kretzschmar
Flag of Germany image

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 ;-)
Avatar of ConceptSysInc
ConceptSysInc

ASKER

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).
Avatar of kretzschmar
kretzschmar
Flag of Germany image

courious,
just asking myself why you have porblems,
there should be no one

can you show, how you do fill your tree?

meikl ;-)
Avatar of kretzschmar
kretzschmar
Flag of Germany image

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 ;-)
Avatar of ConceptSysInc
ConceptSysInc

ASKER

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
Avatar of ConceptSysInc
ConceptSysInc

ASKER

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.
Avatar of kretzschmar
kretzschmar
Flag of Germany image

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 ;-)
Avatar of ConceptSysInc
ConceptSysInc

ASKER

this question can be closed since I was NOT able to find a more suitable solution than the one I  am already using
Avatar of kretzschmar
kretzschmar
Flag of Germany image

i'm unsure to agree with this
Avatar of ConceptSysInc
ConceptSysInc

ASKER

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
Avatar of shaneholmes
shaneholmes

Lets see the solution posted here....

listening...

Shane
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Delphi
Delphi

Delphi is the most powerful Object Pascal IDE and component library for cross-platform Native App Development with flexible Cloud services and broad IoT connectivity. It provides powerful VCL controls for Windows 10 and enables FMX development for Windows, Mac and Mobile. Delphi is your choice for ultrafast Enterprise Strong Development™. Look for increased memory for large projects, extended multi-monitor support, improved Object Inspector and much more. Delphi is 5x faster for development and deployment across multiple desktop, mobile, cloud and database platforms including 32-bit and 64-bit Windows 10.

60K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo