Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Wasteful FindWindow 1

Status
Not open for further replies.

ors

Programmer
Sep 10, 2005
18
MT
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 wrote a small program to consider your questions and my investigation provide the following answers:

- 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
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top