Jump to content
sjesper

How to activate a windows found by FindWindowsEx

Recommended Posts

Hello. As the title says i'm trying to activate a window that i found by using FIndWindowsEx. Here is what i got to:

[sCAR]

program New;

var

HWDC: THwndArray;

Client: TSCARWindowClient;

begin

HWDC := FindWindowsEx(GetDesktopWindow, 'Note', '', False, False, True);

ActivateWindow(HWDC[0]);

writeln(HWDC[0]);

Client.Handle := HWDC[0]

Client.Activate;

end.[/sCAR]

 

But i get this error: Could not call proc (Unknown error).

Link to comment
Share on other sites

I recommend watching these professional preview videos by Freddy:

He explains a lot of this new Window API stuff in those videos, he also explains them very well - it's all really easy to understand & follow.

 

This works:

 

[scar]var

HWDC: THwndArray;

Client: TSCARWindowClient;

h: Integer;

 

begin

HWDC := FindWindowsEx(GetDesktopWindow, 'Note', '', False, False, True);

if (High(HWDC) > -1) then

begin

Client := TSCARWindowClient.Create(HWDC[0]);

Client.Activate;

end else

WriteLn('FAIL...');

end.[/scar]

 

Also this way works, if you just want to activate a window, and not set it as client:

 

[scar]var

HWDC: THwndArray;

 

begin

HWDC := FindWindowsEx(GetDesktopWindow, 'Note', '', False, False, True);

if (High(HWDC) > -1) then

ActivateWindow(HWDC[0]);

end.[/scar]

 

..but I think you had problems with Client.

So the problem was, that you didn't create the client with TSCARWindowClient.Create(), which is required I think.

 

Small example to show how damn useful this new window API really is:

 

[scar]const

WindowTitle = 'Note'; // NOTE: Open AT LEAST 2 window's which ALL contain this title (or part of the title..)!

 

var

HWDC: THwndArray;

cl: array of TSCARWindowClient;

h, i: Integer;

 

begin

HWDC := FindWindowsEx(GetDesktopWindow, WindowTitle, '', False, False, True);

h := High(HWDC);

if (h < 1) then

begin

WriteLn('Failed to find 2(+) window''s with "' + WindowTitle + '".');

SetLength(HWDC, 0);

TerminateScript;

end;

SetLength(cl, (h + 1));

for i := 0 to h do

cl := TSCARWindowClient.Create(HWDC);

WriteLn(IntToStr(h + 1) + ' clients created - going through em 1-by-1 now!');

for i := 0 to h do

begin

cl.Activate;

cl.Free;

Wait(500);

end;

SetLength(cl, 0);

SetLength(HWDC, 0);

end.[/scar]

 

With it you could easily setup SCAR to macro using multiple clients ("playing" with multiple "players" at the same time). ;)

 

Hope this helps,

-Jani

Edited by Janilabo
Link to comment
Share on other sites

If you don't need to use a window as client, you shouldn't use the client API. As Janilabo pointed out, you need to create a TSCARWindowClient object first before you can assign properties to it. Unlike a record, it requires to be created and destroyed because it is a class.

 

Consider this construct:

[scar]Client := TSCARWindowClient.Create(Handle);

Client.Activate;

SetClient(Client).Free;[/scar]

It will create a client for the window specified by Handle, activate it, set is as active client with [wiki=SetClient]SetClient[/wiki] and free the previously active client. This of course assuming you don't want to keep the old client for later usage.

Link to comment
Share on other sites

If you don't need to use a window as client, you shouldn't use the client API. As Janilabo pointed out, you need to create a TSCARWindowClient object first before you can assign properties to it. Unlike a record, it requires to be created and destroyed because it is a class.

 

Consider this construct:

[scar]Client := TSCARWindowClient.Create(Handle);

Client.Activate;

SetClient(Client).Free;[/scar]

It will create a client for the window specified by Handle, activate it, set is as active client with [wiki=SetClient]SetClient[/wiki] and free the previously active client. This of course assuming you don't want to keep the old client for later usage.

 

 

Can i ask why do you have to call SetClient(Client).Free ? Why cant you call Client.Free?

Link to comment
Share on other sites

Can i ask why do you have to call SetClient(Client).Free ? Why cant you call Client.Free?

 

Go ahead and try it...

[scar]begin

Client := TSCARWindowClient.Create(Handle);

Client.Activate;

SetClient(Client);

Client.Free;

end.[/scar]

 

I'm not sure what I can add to my description to explain this any more detailed...

Link to comment
Share on other sites

Can i ask why do you have to call SetClient(Client).Free ? Why cant you call Client.Free?
I think this way us (scripters) have more power to control the targetted client.

With this new technique, there is actually pretty damn sweet support for multiple clients (this is something I am going to be playing around soon, with my scripts).

 

Well, Client.Free could always do this action below (I think this is what you are after with your question):

 

[scar]var

clnt: TSCARWindowClient;

 

begin

clnt := TSCARWindowClient(GetClient);

// clnt.Free; Could be:

SetClient(TSCARWindowClient.Create(GetDesktopWindow)); // This...

clnt.Free; // ..and this combined TOGETHER could be clnt.Free;

end.[/scar]

 

BUT the problem with that is, it really would be very limited.

Simply because, it would remove the purpose of this whole new Window/Client API pretty much.

As I said, now we as scripters have to power to control SCAR's selected client.

Hopefully things stay this way (and of course, there will be much more to come in future, as in DTM/OCR APIs).

 

Of course Shadow, you could always do something like this:

[scar]var

client: TSCARWindowClient;

 

procedure FreeClient(var clnt: TSCARWindowClient);

begin

SetClient(TSCARWindowClient.Create(GetDesktopWindow));

clnt.Free;

end;

 

begin

client := TSCARWindowClient(GetClient);

FreeClient(client);

end.[/scar]

 

IF you want to keep things simple. I guess.. :P

 

But yeah, I really love the possibilities this new API has added in SCAR.

Don't worry guys, it just takes a little time to get used to it.. Once you do, you never want to go back how things were in the past! ;) I promise.

 

-Jani

Edited by Janilabo
Small fix, cheers Freddy
Link to comment
Share on other sites

So what does SetClient() do? is what im asking. I understand scar has to have a client in order for it to operate but i think it should just default to the desktop if there isnt a client.

 

I do like the new client api, as i have been able to find buttons on windows and etc. by using there class name etc. I just wanted to know WHY we must call setClient(...).. instead of just Client.free. Shouldn't the name be like freeclient like janilabo said. Again my question is why must it be called in this fashion? Why isnt this just included in the class as part of the Client.Free ?

Link to comment
Share on other sites

That is the behavior we are used to seeing: Create a bitmap, use it, free it. Create a dtm, use it, free it.

 

And then there is... Create a client, use it, (but you cannot free it), create a second client and then (and only then) free 1st client by calling 2nd client's free method. Ugh! Makes me queasy. Just takes some getting used to.

Link to comment
Share on other sites

So what does SetClient() do? is what im asking. I understand scar has to have a client in order for it to operate but i think it should just default to the desktop if there isnt a client.

 

I do like the new client api, as i have been able to find buttons on windows and etc. by using there class name etc. I just wanted to know WHY we must call setClient(...).. instead of just Client.free. Shouldn't the name be like freeclient like janilabo said. Again my question is why must it be called in this fashion? Why isnt this just included in the class as part of the Client.Free ?

 

You're missing about every point of object oriented programming... =/

 

SCAR defaults to the desktop client when first started as it always has. If you create a TSCARClient or a derivative of said class, you don't set a new client... The resulting object represents a client which SCAR can target. Once you call SetClient, the object becomes active. SetClient returns the previously targeted client object, which you can dispose of with .Free or store in a variable to restore with SetClient later on.

 

I really don't understand the problem you're having with this, it's just a simple OOP implementation... Also, it HAS to be .Free, as .Free is the entry method to free an object, derived from the TObject base class. This method will in turn call the class destructor, which frees all of the resources for the object.

 

That is the behavior we are used to seeing: Create a bitmap, use it, free it. Create a dtm, use it, free it.

 

And then there is... Create a client, use it, (but you cannot free it), create a second client and then (and only then) free 1st client by calling 2nd client's free method. Ugh! Makes me queasy. Just takes some getting used to.

 

Also missing the point... You don't call Free on the second client, you call it on the original. SetClient set's your new client as the active one in the script engine, it returns the old client object.

Link to comment
Share on other sites

I hope this clears things up:

[scar]var

Client, NewClient, StoredClient: TSCARClient;

begin

ClearDebug;

 

Client := GetClient;

NewClient := TSCARWindowClient.Create(GetDesktopWindow);

 

StoredClient := SetClient(NewClient);

WriteLn(StoredClient = Client);

WriteLn(StoredClient = NewClient);

 

StoredClient := SetClient(Client);

WriteLn(StoredClient = Client);

WriteLn(StoredClient = NewClient);

end.[/scar]

Link to comment
Share on other sites

Thanks your example clears everything up. I just didnt really understand how to use the function. I have watched a few of the client videos but i prefer to read as the information can be read quicker and is easier to go back to.

 

 

Just to make sure i understand it. (using your example variables the way you have them setup) If i were to call "SetClient(Client).free;" that would free the "NewClient" Client and set the client at "Client" and it would return nothing for the "StoredClient"?

Edited by shadowrecon
Link to comment
Share on other sites

Just to make sure i understand it. (using your example variables the way you have them setup) If i were to call "SetClient(Client).free;" that would free the "NewClient" Client and set the client at "Client" and it would return nothing for the "StoredClient"?

 

No, if you call "SetClient(Client).Free;", it won't return anything. SetClient() returns a client TSCARClient.Free does not. Also, it won't free NewClient, it will free whatever client you set previously. If you did SetClient(Client); before that, it will be trying to free Client, which won't work, as you can't free the active client.

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...