Jump to content
DuByD

Swapping between multiple clients

Recommended Posts

I have written a script that works with one client window and I was trying to branch it out to handle more than one. Here is a sample of what I am doing... Simplified... I get runtime errors when calling a procedure with a different client (ColorSomething in this example). Hope this makes sense....

 

program new;

 var  
   Wnds: THwndArray;
   Client1,Client2 : TSCARWindowClient;  // 2 clients
   Client1Width, Client1Height : Integer;
   Client2Width, Client2Height : Integer;
   RatioX1,RatioX2,RatioY1,RatioY2 : Single;  

const
 ColorTol : 2;
 Color    : 123456;

// used to create a tbox that focuses on a certain area of a windows and adjusts for size.
function CreateTBox(X,Y : Integer; RX1,RY1,RX2,RY2 : Single) : TBox;
var tb : TBox;
   X1,X2,Y1,Y2 : Integer;
begin
   X1 := Floor(X * RX1);
   X2 := Floor(X * RX2);
   Y1 := Floor(Y * RY1);
   Y2 := Floor(Y * RY2);
   tb := Box(X1,Y1,X2,Y2);
   Result := tb;
end;

// sample procedure to look for a color and do something
procedure ColorSomething(Client : TSCARWindowClient; tb : TBox) : Boolean;
var X,Y : Integer;
begin
   Client.Activate;
   Client.ClientArea := True;
   FindColorTol(X,Y,Color,tb.X1,tb.Y1,tb.X2,tb.Y2,ColorTol);
   MoveMouse(X,Y);
   // Do Some Stuff
end;

procedure SetupClient1;
begin
 Wnds := FindWindowsPreg(GetDesktopWindow,Client1Title,'', False);
 Client1 := TSCARWindowClient.Create(Wnds[0]);
 SetClient(Client1).Free(); 
 Client1.Activate;    
 Client1.ClientArea := True;
 Client1Width := Client1.ImageArea.X2 + 1;
 Client1Height := Client1.ImageArea.Y2 + 1;    
end;

procedure SetupClient2;
begin
 Wnds := FindWindowsPreg(GetDesktopWindow,Client2Title,'', False);
 Client2 := TSCARWindowClient.Create(Wnds[0]);
 SetClient(Client2).Free(); 
 Client2.Activate;    
 Client2.ClientArea := True;
 Client2Width := Client2.ImageArea.X2 + 1;
 Client2Height := Client2.ImageArea.Y2 + 1;    
end;

procedure SetupBoxes;
begin
 Client1TB := CreateTBox(Client1Width,Client1Height,RatioX1,RatioY1,RatioX2,RatioY2);
 Client2TB := CreateTBox(Client2Width,Client2Height,RatioX1,RatioY1,RatioX2,RatioY2);
end;

begin
 RatioX1 := 0.2;
 RatioY1 := 0.2;
 RatioX2 := 0.8;
 RatioY2 := 0.8;
 SetupClient1;
 SetupClient2;
 SetupRatios;
 SetupBoxes;
 ColorSomething(Client1,Client1TB);
 ColorSomething(Client2,Client2TB);
 ColorSomething(Client1,Client1TB);
end.

Link to comment
Share on other sites

Constants are set with = not :

 

const
 ColorTol = 2;
 Color    = 123456;

 

I tried to compile that code, and a bunch of different things were wrong. Are you porting this over from Delphi/Free Pascal?

 

What you want to achieve isn't too hard. You need an array of some sort to keep all the clients (windows) in. Then say, you want to run Example() on every client, then you just look through the array and do Client[index].Example();. This is just a concept, an example if you will.

 

In Your Case: Use SetClient function, to change which Window is the Targeted Client. THEN use GetClient.Activate; to bring the window into view, so your functions can work on it.

 

e.g.

// Updated by LordJashin
procedure ColorSomething(Client : TSCARWindowClient; tb : TBox) : Boolean;
var X,Y : Integer;
begin
   SetClient(Client);
   Client.Activate; // or you can use GetClient.Activate;
   Client.ClientArea := True; // Sure if you need this
   if FindColorTol(X,Y,Color,tb.X1,tb.Y1,tb.X2,tb.Y2,ColorTol) then // you need if..then otherwise Mouse(X, Y) always executes
   MoveMouse(X,Y);
   // Do Some Stuff
end;

Edited by LordJashin
Link to comment
Share on other sites

Thanks... I just typed that up real quick for an example... sry about the errors... I added "SetClient(Client);" in front of the "Client.Activate;" throughout the script and I am still getting a runtime error placing the error right at "Client.Activate". Any other ideas?

Link to comment
Share on other sites

You didn't find ANY windows, then your trying to Wnds[0] to it. What if it didn't find any? Then Length(Wnds) = 0; Meaning you can't do Wnds[0].

 

Also, you never set the ClientTitles as far as I can tell. Which is what your searching for in FindWindowPreg.

 

This is how it should be done:

 

var
Client2_IsNull: Boolean;
procedure SetupClient2;
begin
 Wnds := FindWindowsPreg(GetDesktopWindow,Client2Title,'', False);
 if Length(Wnds) < 1 then
begin
   Client2_IsNull := True; // Meaning Client2 := TSCARWindowClient.Create WAS NOT CALLED. So it isn't created
   WriteLn('No windows were found for client 2  Exiting the Setup procedure for CLient2');
   Exit;
end;
 Client2 := TSCARWindowClient.Create(Wnds[0]);
 SetClient(Client2).Free(); 
 Client2.Activate;    
 Client2.ClientArea := True;
 Client2Width := Client2.ImageArea.X2 + 1;
 Client2Height := Client2.ImageArea.Y2 + 1;    
end;

 

Use something like that to Check the array, and then act from there.

 

Length(s): LongInt; : This returns the length of strings. OR the length of Arrays (Including THwndArray)

Refer to the tutorials section to learn more: http://forums.scar-divi.com/tutorials-faq/

Edited by LordJashin
Link to comment
Share on other sites

OK... totally baffled now.. :) I rewrote the sample i gave to a compilable version that uses two notepad windows... I do know that the windows are being found and that isn't the reason for the errors as I see them get activated one by one and pop up over the editor. I did add the SetClient(Client); to the procedures and was still having the issue... This time I noticed that the var for Client1 was showing a blank after the .free and activate for client two. Interestingly enough, this did not happen in my test script and there is no logical difference which is why I am baffled. I do need to go back and do some error handling with some try statements and checking of the variables as in your example. I did however get it to work... In the setup procedure, i changed the SetClient(Client1).Free(); to SetClient(Client1); without the .Free(). Not sure why it works in the example in this post and doesn't in my main script but it seems as though it isn't needed. It looks like Client1 is losing its settings when the 2nd, 3rd, etc. clients are being set and thus the procedure is trying to operate on "nothing". Below is the sample that i made using two notepad documents. One titled test1 and the other test2. My comments mark the points and changes in relation to my full script.

 

program new;

 var  
   Wnds: THwndArray;
   Client1,Client2 : TSCARWindowClient;  

const
 Client1Title = '/test1.*/i';
 Client2Title = '/test2.*/i';

procedure TypeSomething(Client : TSCARWindowClient; s : String);
begin
   SetClient(Client);
   Client.Activate;
   Client.ClientArea := True;    // needed for my purposes not this example
   TypeText(s);
end;

procedure SetupClient1;
begin
 Wnds := FindWindowsPreg(GetDesktopWindow,Client1Title,'', False);
 Client1 := TSCARWindowClient.Create(Wnds[0]);
 SetClient(Client1).Free();     // in main script changed to SetClient(Client1);
 Client1.Activate;    
 Client1.ClientArea := True;
end;

procedure SetupClient2;
begin
 Wnds := FindWindowsPreg(GetDesktopWindow,Client2Title,'', False);
 Client2 := TSCARWindowClient.Create(Wnds[0]);
 SetClient(Client2).Free();    // in main script changed to SetClient(Client1);
 Client2.Activate;    
 Client2.ClientArea := True;   // this is where i lose client 1 in my real script
end;                            // cursor sitting before this line

begin
 SetupClient1;
 SetupClient2;
 TypeSomething(Client1,'This Is Test1');
 TypeSomething(Client1,'This Is Test1 Again');
 TypeSomething(Client2,'This Is Test2');
 TypeSomething(Client1,'This Is Test1 Again');
end.

Link to comment
Share on other sites

I've seen SetClient(Client).Free(); a lot. I never preferred doing this. I could be wrong, but I think that is "chaining" in action. Instead of doing this:

 

SetClient(Client);
Client.Free();

 

You can do this:

 

SetClient(Client).Free();

 

Thus this is the error as you have indicated. My bad for not picking up on it. Change SetClient(Client).Free(); to just SetClient(Client);

 

Since this is a variable you created yourself (e.g. Client1), you also need to Free it, when your done with it. E.g. like if you create a GUI application, once some1 closes it, everything has to be freed from the memory.

 

So after you do the last TypeSomething, do Client1.Free;, Client2.Free;. Try restarting SCAR. And should be good.

 

So the reason this code:

 

Client1.Activate;    
Client1.ClientArea := True;

Doesn't run, is because Client1 was freed early.

 

EDIT: Weird.

 

Well, I think wrapping the FindWindow, and Client stuff in some functions would make this a lot cleaner.

Edited by LordJashin
Link to comment
Share on other sites

@LordJashin: SetClient returns the active client, not the client you set, so SetClient(Client);Client.Free; does not equal SetClient(Client).Free;

 

So

 

SetClient(Client).Free;

 

=

 

PrevActiveClient := SetClient(Client);
PrevActiveClient.Free;

 

Does that do anything to the client system? Or does it just "refresh" it?

Link to comment
Share on other sites

So

 

SetClient(Client).Free;

 

=

 

PrevActiveClient := SetClient(Client);
PrevActiveClient.Free;

 

Does that do anything to the client system? Or does it just "refresh" it?

 

It just changes what client object is active and free the previous one.

 

Think:

 

OldClient := GetClient;
SetClient(NewClient);
OldClient.Free;

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
  • Create New...