Solved

Monitor for a specific window / process

Posted on 2003-11-23
5
439 Views
Last Modified: 2010-04-03
Hello All,

I know how to get all the current windows or processes, but for some reason I'm having trouble with something that should be much simpler than that.

I want to monitor for a specific caption and then execute an action if the caption becomes visible.  For example, my app will run in the background, if it sees a window named 'Outlook' then I want it to execute an action or run a function.  I would also like this to be friedly with system resources, but spontanious.  In other words, I don't want to hang a slow system with a low interval timer, but I want the app to react instantly to the apearence of 'Outlook'

If possible, I would like to get partial captions.  As-In if part of the caption is 'Outlook'.  So even if the actual caption is 'Microsoft Outlook' or 'Microsoft Outlook - Contacts' It will still fire my function.

I hope I am clear.  :)
// Happy Coding
0
Comment
Question by:fibdev
  • 2
  • 2
5 Comments
 
LVL 7

Assisted Solution

by:jconde
jconde earned 25 total points
ID: 9809201
Hi!

In my example, button1 shows the list of the executable files currently running.  Button2 displays all of the running window-captions.  I beleive the code for "Button2" will be the one that helps you out the most.

Basically, modify the code and fit it into a timer and parse each string to find the application you're looking for:


unit Unit1;

interface

uses
  Controls, StdCtrls, Classes, Forms, windows, SysUtils, tlhelp32;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  WindowList: TList;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
var
 I: Integer;
 Snapshot: THandle;
 PE: TProcessEntry32;
begin
 ListBox1.Clear;
 Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 if (Snapshot = DWORD(-1)) then
     Exit;
 PE.dwSize := SizeOf(TProcessEntry32);
 if Process32First(Snapshot, PE) then
 repeat
   I := ListBox1.Items.Add(PE.szExeFile);
 until not Process32Next(Snapshot, PE);
 CloseHandle (Snapshot);
end;

function GetWindow (Handle: HWND; LParam: longint): bool; stdcall;
begin
  Result := true;
  WindowList.Add (Pointer(Handle));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
  Hnd: HWND;
  Buffer: array [0..255] of char;
begin
  ListBox1.Clear;
  try
    WindowList := TList.Create;
    EnumWindows (@GetWindow, 0);
    ListBox1.Items.Clear;
    for i := 0 to WindowList.Count - 1 do begin
      Hnd := HWND (WindowList [i]);
      if IsWindowVisible (Hnd) then begin
        GetWindowText (Hnd, Buffer, SizeOf (Buffer) - 1);
        if Buffer [0] <> #0 then
          ListBox1.Items.Add (StrPas(Buffer));
      end;
    end;
  finally
    WindowList.Free;
  end;
end;

end.
0
 
LVL 5

Expert Comment

by:DeerBear
ID: 9810052
Hi,

You can "easily" do it using hooks <g>.

It's enough to use the GetMessage hook, and monitor the WM_SETFOCUS message.
Once you find the window text and compare it to your text, you can issue the
related action.

HTH,

Andrew

P.S. To use Hooks, have a look at SetWindowsHookEx/UnHookWindowsHookEx.
0
 
LVL 3

Author Comment

by:fibdev
ID: 9810238
jCondi,

Thanks for the code.  I am already alble to do that.  :)

DeerBeer,

Please elaborate  :)
0
 
LVL 5

Accepted Solution

by:
DeerBear earned 25 total points
ID: 9810379
Hi again,

I was simply saying you should use a hook, specifically the WH_GETMESSAGE hook, which will
monitor the incoming messages for a Window. It can be local or system wide.

In the system-wide version, you can monitor all messages from all the windows in the system,
thus you just retrieve the caption for the Window you're interested in and then issue appropriate
action if the message is WM_SETFOCUS or WM_SETFOREGROUND( which is the one that actually
makes the form visible ).

That's all, in theory.

The problem is in practice <g>.

Now I'll show you a very simple way to implement what you need, but please
beware that this code can be DANGEROUS and you can't debug it as you'd do
with any other DLL, k?

I'll simply write it without testing it, thus you'll have to test it on your own.

If someone has the time to, please look at it and correct it if needed.

Code:


library TestLib;

interface

uses Windows, Messages,
       uWindowUtils; // This unit comes from my own codebase and will be posted just after the
                            // library code.

var Caption : String;

function GetMessageHook (code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
var Msg : tagMsg;
     TmpCaption : String;
begin
  if code > 0 then
  begin
     @Msg := Pointer( lparam );
     case Msg.message of
        WM_SETFOREGROUND : begin
                                               TmpCaption := uWindowUtils.GetWindowText( Msg.Handle );
                                               if TmpCaption = Caption then
                                                  DoYourActionHere;
                                            end;
    end;
  end
  else Result := CallNextHook( WH_GETMESSAGE,wparam,lparam );
end;

var TheHook : Integer;

procedure InstallHook( CaptionValue : String );stdcall;
begin
   Caption := CaptionValue;
   theHook := SetWindowsHookEx(WH_GETMESSAGE, @MyHookProc, hInstance, 0);
end;

procedure RemoveHook;stdcall;
begin
   UnhookWindowsHookEx(theHook);
end;

exports
 
    InstallHook index 1,
    RemoveHook index 2;

end.

uWindowUtils module:

unit uWindowUtils;

interface

uses Windows;

function GetWindowText( Handle : THandle ) : String;
function GetWindowClass( Handle : THandle ) : String;

implementation

function GetWindowText( Handle : THandle ) : String;
var WText : PChar;
    TxtBuf : String;
begin
  GetMem( WText,255 );
  Windows.GetWindowText( Handle,WText,255 );
  TxtBuf := WText;
  Result := TxtBuf;
  FreeMem( WText );
end;

function GetWindowClass( Handle : THandle ) : String;
var WText : PChar;
    TxtBuf : String;
begin
  GetMem( WText,255 );
  GetClassName( Handle,WText,255 );
  TxtBuf := WText;
  Result := TxtBuf;
  FreeMem( WText );
end;

end.

To make it work appropriately, you'll need to setup a MemoryMappedFile.

Look to my reply history for an example of how to do it.

HTH,

Andrew
0
 
LVL 3

Author Comment

by:fibdev
ID: 10090568
I didn't really get what I was after... Just cleaning house.  Happy new year.  :)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
loading dll from external path 1 213
Delphi - replicating a form 8 67
Comparing dates in Delphi. Greater than/ Less than 3 119
Delphi selector screen 2 70
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now