Sign in to follow this  
Followers 0
veles68

In delphi app controlID

20 posts in this topic

Hi all,

I have a problem with a delphi app, in which I run an AutoIt script for automatic testing. The problem is, that each time I add a new field, the controlIDs of some of the edit or dbedit fields are being changed. That way, I always have to go through all the fields in the Auto-It script to reassign the correct controlID.

The "Instance" under "Basic Control Info" from the Window Info tool changes also.

Here is an example how do I enter text in the fields:

ControlSend("WindowTitle", "", "TDBEdit14", "29.06.2013")

where 14 is the instance number.

Any workaround or solution for this?

Kind Regards,

Dimce

Share this post


Link to post
Share on other sites



Would it help if you could get the EditNN within your Delphi program, then you could tell the AutoIt program which edit had which name using a message say.

If it would help I can show some Delphi code which I think would do what you want.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Try >_ControlGetHandleByPos() by LxP.

Also try >_CtrlGetByPos() by SmOke_N.

MHz,

I tried the _ControlHandleByPos, but it doesn't work. I tried with the coordinates for all three options - Screen, Window, Client, but with none of them worked.

Even the test script didn't work for me.

Share this post


Link to post
Share on other sites

Would it help if you could get the EditNN within your Delphi program, then you could tell the AutoIt program which edit had which name using a message say.

If it would help I can show some Delphi code which I think would do what you want.

I suppose you mean the "Name" - property of the TEdit component in Delphi? But, how do I tell the AutoIt this "Name"?

Otherwise, an sample Delphi code is more than welcome.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

You could tell the AUtoit program the name with a message. If you only need to tell the au3 script which edit has which number then it would be quite simple, but you could do it a lot of other ways. You could have a memo and write the results there then the au3 script could read the memo.

Anyway, here is an example of delphi which works out the edit number. They are allocated in reverse order for some reason when I have tested this using D2010.

 
//create a project with a form, add some edits and a memo which is large enough that you can see the results.
//then add this code for the oncreate event
 
procedure TForm2.FormCreate(Sender: TObject);
var
  ii: Integer;
  editcount: Integer;
  cname, cclassname: string;
begin
  editcount := 1;
  memo1.clear;
  for ii := 0 to ComponentCount - 1 do
    if components[ii] is TEdit then
      begin
        cname := components[ii].name;
        cclassname := components[ii].classname;
        with components[ii] as TEdit do
          if parent = Form2 then  //or whatever the parent for the edits you are interested in might be, or just leave this line out
            begin
              memo1.lines.add(cname + ' classnameNN = ' + cclassname );
              inc(editcount);
            end;
      end;

      //the edits are given numbers in reverse order
      for ii := editcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(editcount - ii);


end;
 
 

If you want some help with using messages then I can give that.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Martin.

thank you for the delphi code. I tried it out, but I found a problem with the TDBEdit components, I have in my application. All of the TDBEdit comp. are having the same "ClasnameNN", namely the "TDBEdit".

This is how the output looks like, when I have five TDBEdit fields on a delphi form:

DBEdit1 classnameNN = TDBEdit
DBEdit2 classnameNN = TDBEdit
DBEdit3 classnameNN = TDBEdit
DBEdit4 classnameNN = TDBEdit
DBEdit5 classnameNN = TDBEdit
 

So, I don't think it is a solution for me.

You mentioned also, that there is a possibility "to tell the AUtoit program the name with a message". Frankly speaking I don't understand this solution? Could you please explain it little beat deeper, or with a small example?

Dimce

Share this post


Link to post
Share on other sites

It looks like you haven't modified the code sufficiently to deal with TDBEdit instead of TEdit.

If I try it it seems to work fine.

procedure TForm2.FormCreate(Sender: TObject);
var
  ii: Integer;
  editcount: Integer;
  cname, cclassname: string;
begin
  editcount := 1;
  memo1.clear;
  for ii := 0 to ComponentCount - 1 do
    if components[ii] is TDBEdit then
      begin
        cname := components[ii].name;
        cclassname := components[ii].classname;
        with components[ii] as TDBEdit do
          if parent = Form2 then  //or whatever the parent might be or just leave this line out
            begin
              memo1.lines.add(cname + ' classnameNN = ' + cclassname );
              inc(editcount);
            end;
      end;

      //the edits are given numbers in reverse order
      for ii := editcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(editcount - ii);


end;

 

But if you only call the names DBEdit1 and DBEdit 2 it isn't very helpful. If you use a meaningful name, like DBEdIPAdd or something, then when the AutoIt script reads it it will see that DBEdIPAdd is DBEdit3 and so it can work out which one to read.

I have assumed that if the AutoIt script knows what DBEdit3 is for then it can work. Otherwise I don't understand what you are trying to do. Wouldn't reading the text in the memo do what you want (after you have corrected your code)?

The message suggestion is not really relevant until I understand the problem better.

Suppose you want the AutoIt script to know which DBEdit it should write to as in your example

ControlSend("WindowTitle", "", "TDBEdit14", "29.06.2013")

but you know that DBEdit14 is the name of the edit in your Delphi code, but you don't know the classnameNN once it is running. So in your AutoIt script you can do this

Dim $DB14 ;global


$DB14 = 'not found'

findinstances()

If $DB14 <> 'not found' Then
    ControlSend("WindowTitle", "", $DB14, "29.06.2013")
EndIf





Func findinstances()
    $list = ControlGetText("WindowTitle", "", "[Class:TMemo]")

    $list = StringReplace($list, @LF, '')
    $list = StringSplit($list, @CR)
    For $n = 1 To $list[0] - 1
        If StringInStr($list[$n], 'DBEdit14') Then
            $DB14 = StringStripWS(StringRight($list[$n], StringLen($list[$n]) - StringInStr($list[$n], '=')), 3)
            ConsoleWrite("$DB14 = " & $DB14 & @CR)
        EndIf
      ;add any others you need
    Next

EndFunc   ;==>findinstances

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

 

It looks like you haven't modified the code sufficiently to deal with TDBEdit instead of TEdit.

If I try it it seems to work fine.

procedure TForm2.FormCreate(Sender: TObject);
var
  ii: Integer;
  editcount: Integer;
  cname, cclassname: string;
begin
  editcount := 1;
  memo1.clear;
  for ii := 0 to ComponentCount - 1 do
    if components[ii] is TDBEdit then
      begin
        cname := components[ii].name;
        cclassname := components[ii].classname;
        with components[ii] as TDBEdit do
          if parent = Form2 then  //or whatever the parent might be or just leave this line out
            begin
              memo1.lines.add(cname + ' classnameNN = ' + cclassname );
              inc(editcount);
            end;
      end;

      //the edits are given numbers in reverse order
      for ii := editcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(editcount - ii);


end;

 

Martin,

sorry for the delay, I was very busy since yesterday.

I've changed the names of the TDBEdit, but the same coding is not working for me :(. Here is my version, which is actually the same as yours, only with the extension with th TEdit besides TDBEdit:

procedure TFormMain.FormCreate(Sender: TObject);
var
  ii: Integer;
  editcount
, dbeditcount
  : Integer;
  cname, cclassname: string;
begin
  editcount := 1;
  dbeditcount := 1;
  memo1.clear;
  for ii := 0 to ComponentCount - 1 do
    if components[ii] is TEdit then
    begin
      cname := components[ii].name;
      cclassname := components[ii].classname;
      with components[ii] as TEdit do
        //if parent = FormVertraege then  //or whatever the parent for the edits you are interested in might be, or just leave this line out
        //begin
            memo1.lines.add(cname + ' classnameNN = ' + cclassname );
            inc(editcount);
        //end;
    end
    else if components[ii] is TDBEdit then
    begin
      cname := components[ii].name;
      cclassname := components[ii].classname;
      with components[ii] as TDBEdit do
        //if parent = FormVertraege then  //or whatever the parent for the edits you are interested in might be, or just leave this line out
        //begin
            memo1.lines.add(cname + ' classnameNN = ' + cclassname );
            inc(dbeditcount);
        //end;
    end;
 
      //the edits are given numbers in reverse order
      for ii := editcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(editcount - ii);
 
      for ii := dbeditcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(dbeditcount - ii);
 
end;

 

 

And the output is:

DBEditNAME classnameNN = TDBEdit

DBEditFIRSTNAME classnameNN = TDBEdit
DBEditSTREET classnameNN = TDBEdit
DBEditPOST_CODE classnameNN = TDBEdit
DBEditLAND classnameNN = TDBEdit
 
So, the only problem is getting the ClasnamesNN out of the delphi app. Maybe the problem on my side is the old delphi version - 5.0 ?
 
Cheers,
Dimce
 
You said:
"... I have assumed that if the AutoIt script knows what DBEdit3 is for then it can work. Otherwise I don't understand what you are trying to do. Wouldn't reading the text in the memo do what you want (after you have corrected your code)?..."
Yes, your assumption is correct. Getting the ClassnamesNN out of the Memo box is just what I need, so I can process the entries in my delphi application triggered from the AutoIt script.

Share this post


Link to post
Share on other sites

Veles68

you have an error I think in your logic. The for loops cover the same memo lines probably and you don't know, without doing something to find out, what order the edits and DBEdits are in the list of components so you will have a bit of a mess.

Change your code to this and I think it will work.

procedure TForm2.FormCreate(Sender: TObject);
var
  ii: Integer;
  editcount
, dbeditcount
  : Integer;
  cname, cclassname: string;
  lastmemoline:integer;
begin
  editcount := 1;
  dbeditcount := 1;
  memo1.clear;
  for ii := 0 to ComponentCount - 1 do
    if components[ii] is TEdit then
    begin
      cname := components[ii].name;
      cclassname := components[ii].classname;
      with components[ii] as TEdit do
        //if parent = FormVertraege then  //or whatever the parent for the edits you are interested in might be, or just leave this line out
        //begin
            memo1.lines.add(cname + ' classnameNN = ' + cclassname );
            inc(editcount);
        //end;
    end;
      for ii := editcount - 1 downto 1 do
      memo1.lines[ii-1] := memo1.lines[ii-1] + inttostr(editcount - ii);
//now you have all the edits, so get the DBEdits next and don't mix them up
       lastmemoline :=  editcount - 1;


     for ii := 0 to ComponentCount - 1 do
     if components[ii] is TDBEdit then
    begin
      cname := components[ii].name;
      cclassname := components[ii].classname;
      with components[ii] as TDBEdit do
        //if parent = FormVertraege then  //or whatever the parent for the edits you are interested in might be, or just leave this line out
        //begin
            memo1.lines.add(cname + ' classnameNN = ' + cclassname );
            inc(dbeditcount);
        //end;
    end;

      //the edits are given numbers in reverse order

      for ii := dbeditcount - 1 downto 1 do  //and remember to start from lastmemoline
      memo1.lines[lastmemoline + ii-1] := memo1.lines[lastmemoline + ii-1] + inttostr(dbeditcount - ii);

end;
 

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Martin,

you are right. I had somewhere an error. Using your code it's working, it shows properly the ClasnameNN's.

But, now I see (sorry), that I have to modify my application, and add a memo box to list all the edit- and dbedit - fields. Actually, I would do it rather unwillingly. If yes, then I have to hide it somehow from the end user (either visible=false or putting it on some panel in the background).

Thanks a lot for your support,

Dimce

Share this post


Link to post
Share on other sites

Ok, the memo was just a way to show the results in an easy way and also a way that an AutoIt script could read.

You could make the memo not visible, or you can position it off the form out of sight, it will still work.

If the basic idea of getting the classnameNN works ok and you would like to do it with messages so that there is no memo then I can work out an example.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

I was just testing my app getting the ClasnameNN's out of the memo, but it didn't work. Probably I'm missing something. I'll continue tomorrow.

Share this post


Link to post
Share on other sites

Although it works with the test delphi app, it doesn't work with my real delphi app.

The problem is, that in memo box, the ClasnameNN for a field is being reported as "TDBEdit30", but the AutoIt Window Info tool reports the ClasnameNN as "TDBEdit18". So if I try to automate the entry in that field, it only works with "TDBEdit18", and not with "TDBEdit30".

I have no idea...

Share this post


Link to post
Share on other sites

 

Might this not be as simple as 

$iInstance = 14
ControlSend("WindowTitle", "", "[CLASS:TDBEdit; Instance:" & $iInstance, "29.06.2013")

 

No, I don't know the $Instance. It changes each time I add/remove a/an new/existing field in the delphi app.

Share this post


Link to post
Share on other sites

Although it works with the test delphi app, it doesn't work with my real delphi app.

The problem is, that in memo box, the ClasnameNN for a field is being reported as "TDBEdit30", but the AutoIt Window Info tool reports the ClasnameNN as "TDBEdit18". So if I try to automate the entry in that field, it only works with "TDBEdit18", and not with "TDBEdit30".

I have no idea...

 

It could be that the tests I made worked and so I concluded that the approach was correct, but maybe it isn't.

Do the DBEdits have the same parent?

What is the difference between the test and the real app. as far as the DBEdits are concerned?

Are the DBEdit classNN numbers shown in the memo all TDBEdit30, or if not can you show me what they look like?


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

It could be that the tests I made worked and so I concluded that the approach was correct, but maybe it isn't.

Do the DBEdits have the same parent?

What do you mean exactly if they have the "same parent"? They are all from the class TDBEdit. Or you mean if they are all on the same panel/tab sheet? In that case the answer is - no.

 

What is the difference between the test and the real app. as far as the DBEdits are concerned?

Well, the test app is without any functionality. Just few DBEdits dropped on the form without any coding. The form from the real app is inherited from another one.

 

Are the DBEdit classNN numbers shown in the memo all TDBEdit30, or if not can you show me what they look like?

 

No, they are all different. Here are the clasnameNN numbers from all DBEdit - fields:

DBEditID classnameNN = TDBEdit35
DBEditINSDATUM classnameNN = TDBEdit34
DBEditINSUSER classnameNN = TDBEdit33
DBEditUPDDATUM classnameNN = TDBEdit32
DBEditUPDUSER classnameNN = TDBEdit31
DBEditBEZEICHNUNG classnameNN = TDBEdit30
DBEditFIRMA classnameNN = TDBEdit29
DBEditVONDATUM classnameNN = TDBEdit28
DBEditBISDATUM classnameNN = TDBEdit27
DBEditVERTRAGSART classnameNN = TDBEdit26
DBEditSTATUS classnameNN = TDBEdit25
DBEditLAUFZEIT classnameNN = TDBEdit24
DBEditVERTRAGNUMMER classnameNN = TDBEdit23
DBEditBEITRAG classnameNN = TDBEdit22
DBEditZAHLUNGSART classnameNN = TDBEdit21
DBEditVERTRAGSNEHMER classnameNN = TDBEdit20
DBEditANSPRECHPARTNER classnameNN = TDBEdit19
DBEditZAHLUNGSWEISE classnameNN = TDBEdit18
DBEditKUNDENNUMMER classnameNN = TDBEdit17
DBEditBEITRAG_NETTO classnameNN = TDBEdit16
DBEditMANDANT classnameNN = TDBEdit15
DBEditLAUFZEIT_MON classnameNN = TDBEdit14
DBEditIDCopy classnameNN = TDBEdit13
DBEditKNGFRIST classnameNN = TDBEdit12
DBEditKUENDIGUNGSFRIST classnameNN = TDBEdit11
DBEditLFZ_VERL_JAHR classnameNN = TDBEdit10
DBEditLFZ_VERL_TAG classnameNN = TDBEdit9
DBEditLFZ_VERL_MON classnameNN = TDBEdit8
DBEditTAGE_ERINNERUNG classnameNN = TDBEdit7
DBEditKOSTENSTELLE classnameNN = TDBEdit6
DBEditABTEILUNG classnameNN = TDBEdit5
DBEditFILE_LOC classnameNN = TDBEdit4
DBEditMOBILEPROV classnameNN = TDBEdit3
DBEditMOBILERATE classnameNN = TDBEdit2
DBEditSIM_CARD classnameNN = TDBEdit1
 
Dimce

Share this post


Link to post
Share on other sites

Maybe testing for the parent is wrong, I think perhaps I should have said owner. So could you try replacing parent with owner, and maybe refer to a particular DBEdit if possible

Eg

 with components[ii] as TDBEdit do
          if owner= DBEdit1.owner then//Form2 then //or use the form name if you cannot specify one of the edits.

 

If that doesn't help I'm running out of ideas, but it would help if you could give more information. For example, when you tell me the list of DBEdits in the memo is that all that should be there, too many too few? What is the relationship, if you can see one, between the classNN given in the memo and what the AutoIt info tools tells you?


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Martin,

I tried with "owner", "InheritsFrom", "ClassParent", but without success.

 

If that doesn't help I'm running out of ideas, but it would help if you could give more information. For example, when you tell me the list of DBEdits in the memo is that all that should be there, too many too few? What is the relationship, if you can see one, between the classNN given in the memo and what the AutoIt info tools tells you?

All of the DBEdits are there, in the memo box,

Unfortunately, I can't establish a relationshipt between the clasnameNN from the AutoIt Window tool and those from the delphi coding.

I'll continue researching and if I find something, will update the thread.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0