sjesper Posted August 6, 2012 Share Posted August 6, 2012 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). Quote Link to comment Share on other sites More sharing options...
Janilabo Posted August 6, 2012 Share Posted August 6, 2012 (edited) 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 August 6, 2012 by Janilabo Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 7, 2012 Share Posted August 7, 2012 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. Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted August 7, 2012 Share Posted August 7, 2012 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? Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 7, 2012 Share Posted August 7, 2012 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... Quote Link to comment Share on other sites More sharing options...
Bixby Sayz Posted August 7, 2012 Share Posted August 7, 2012 This still gives me the willies every time I see it. It just seems unnatural somehow. [sCAR]SetClient(Client).Free;[/sCAR] Quote Link to comment Share on other sites More sharing options...
Janilabo Posted August 7, 2012 Share Posted August 7, 2012 (edited) 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.. 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 August 7, 2012 by Janilabo Small fix, cheers Freddy Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 7, 2012 Share Posted August 7, 2012 This still gives me the willies every time I see it. It just seems unnatural somehow. [sCAR]SetClient(Client).Free;[/sCAR] Well, you'll only need to do that if you no longer need the old client you're replacing of course... Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted August 7, 2012 Share Posted August 7, 2012 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 ? Quote Link to comment Share on other sites More sharing options...
Bixby Sayz Posted August 7, 2012 Share Posted August 7, 2012 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. Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 8, 2012 Share Posted August 8, 2012 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. Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 8, 2012 Share Posted August 8, 2012 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] Quote Link to comment Share on other sites More sharing options...
Bixby Sayz Posted August 8, 2012 Share Posted August 8, 2012 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.Gotcha. Haven't spent a lot of time playing with it, so didn't completely get it. Now it makes sense. Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted August 8, 2012 Share Posted August 8, 2012 (edited) 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 August 8, 2012 by shadowrecon Quote Link to comment Share on other sites More sharing options...
FHannes Posted August 8, 2012 Share Posted August 8, 2012 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. Quote Link to comment Share on other sites More sharing options...