Wasteful FindWindow
Wasteful FindWindow
(OP)
From within my applications I need to check if another application is loaded.
I tried the enum EnumWindows() API and the FindWindow API.
I set up a chronometer within the code and the results I got are that FindWindow takes 64ms to complete and EnumWindows() takes 0 ms to complete. How can this be. Is FindWindow so bad?
Is EnumWindows run in a seperate thread or something?
In that case, how do I stop my application to wait for that thread to finish. I need to wait for it since my code depends on the results of this thread.
BTW, my PC is an AMD 2100XP, if performance is an issue.
Thanks.
I tried the enum EnumWindows() API and the FindWindow API.
I set up a chronometer within the code and the results I got are that FindWindow takes 64ms to complete and EnumWindows() takes 0 ms to complete. How can this be. Is FindWindow so bad?
Is EnumWindows run in a seperate thread or something?
In that case, how do I stop my application to wait for that thread to finish. I need to wait for it since my code depends on the results of this thread.
BTW, my PC is an AMD 2100XP, if performance is an issue.
Thanks.
RE: Wasteful FindWindow
- FindWindow is not so bad in comparison to EnumWindows
- EnumWindows does not run on a separate thread
- It is most likely that you are returning false on your EnumWindows callback prematurely
More explanation
EnumWindows will call its callback each time it finds a window. The first window is found very very quickly (in my PC finding the window took a fraction of millisecond). Now if you return false on your EnumWindows callback then no more windows will be enumerated. End result EnumWindows will finish very quickly.
In comparison FindWindow is looking for a window of a certain type, and this window may not be the first to be found therefore it may take a little more time that the above scenario of enumerating only the first window.
The following code may clarify what i mean a little more
You will need to create a form with two buttons and one TMemo controls and apply the sample code to it.
I hope it will help
CODE
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TmyForm = class(TForm)
EnumTimes: TMemo;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
fEnumCalled:TDateTime;
fFindCalled:TDateTime;
fFindTime:Integer;
public
end;
var
myForm: TmyForm;
implementation
{$R *.dfm}
uses
DateUtils;
//Careful with definition of this routine (dont forget stdcall)
//otherwise your parameters wont be passed in good order
function OnWindowFound(wnd:HWND; myParam:Integer):Boolean; stdcall;
var
sender:TMyForm;
sWindowName:string;
nEnumTime:integer;
processID:DWORD;
begin
//in this example myParam will contain reference to a TMyForms object
sender:=TMyForm(myParam);
//Get the title of this window
SetLength(sWindowName,255);
GetWindowText(wnd,Pchar(sWindowName),255);
//Because in your case most windows are in a different process it is
//slightly more efficient if you use SendMessage to get the window name
//SendMessage(wnd,WM_GETTEXT,255,pChar(sWindowName));
//Calculate the time taken up to here
nEnumTime:=MillisecondsBetween(Now,myform.fEnumCalled);
//Add the window and time taken to find it in EnumTimes Memo lines
sender.EnumTimes.Lines.Add(Format('EnumWindow took %d milliseconds to find '+sWindowName,[nEnumTime]));
//Continue looking for more windows
result:=true; //return false if you found what you wanted
end;
procedure TmyForm.Button1Click(Sender: TObject);
var
nEnumTime:integer;
lp:Integer;
begin
//Time of EnumWindows call
fEnumCalled:=Now();
EnumWindows(@OnWindowFound,integer(self));
nEnumTime:=MilliSecondsBetween(Now,self.fEnumCalled);
//Add the time that enum took to complete in EnumTimes list
self.EnumTimes.Lines.Add(Format('EnumWindow returned after %d milliseconds',[nEnumTime]));
end;
procedure TmyForm.Button2Click(Sender: TObject);
var
nFindTime:integer;
p:PChar;
sWindowName:string;
wnd:HWND;
begin
//Time of FindWindow call
fFindCalled:=Now();
wnd:=FindWindow('TMyForm',nil);
if wnd<>0 then
begin
//How long did it take ?
nFindTime:=MilliSecondsBetween(Now,fFindCalled);
//Show how long did FindWindow take
ShowMessage(Format('Find window took %d milliseconds',[nFindTime]));
//Retreive the window caption. (this time using SendMessage (just another way))
SetLength(sWindowName,255);
SendMessage(wnd,WM_GETTEXT,255,integer(p));
end
else
ShowMessage('Could not find any window of class TMyForm');
end;
"It is in our collective behaviour that we are most mysterious" Lewis Thomas