Solved

Detecting change on another app

Posted on 2000-02-28
12
270 Views
Last Modified: 2010-04-04
Hi,
How can I detect a an edit box change on another app? e.g. If calc was running and somebody put a value in, I would like my app to detect and act on it. Please help
Thanks
0
Comment
Question by:smurff
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
12 Comments
 
LVL 17

Expert Comment

by:inthe
ID: 2565905
i think the only way would be a keyboard hook ..but this would be in effect for all others apps unless you know the handle of the program with the edit and if it running then use loadlibrary etc...
0
 
LVL 7

Accepted Solution

by:
ahalya earned 50 total points
ID: 2567029
Here is a sample code that updates an EditBox & Memo as Keys are pressed in Calc.

You need to create TWO projects; one a DLL for hooking the keyboard & the other the EXE that calls the DLL.

Run the EXE, start Calc and try it :-)

================== Code For DLL ===========
Create a new project.  Delete all units and copy the following code to the DPR & save it as KBHook.dpr
---------------------------------

library KBHook;

uses Windows, Messages;

const
YourFormClass  = 'TKeyHookForm';
YourFormTitle  = 'Calc Key trap';

var
   KeyState : TKeyboardState;
   CharCode : LPARAM;

function KeyHookProc(nCode: integer; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;

begin
Result := CallNextHookEx(0, nCode, wp, lp);
if not (nCode < 0) then
   begin
   if (lp and (1 shl 31)) = 0 then
     begin
     CharCode := 0;              
     GetKeyboardState(KeyState);
     if ToASCII(wp, HiWord(lp), KeyState, @CharCode, 0) = 1 then
        PostMessage( FindWindow(YourFormClass, YourFormTitle),
                     WM_User + 1, 0, CharCode);

     end;
   end;
Result := CallNextHookEx(0, nCode, wp, lp);
end;

exports KeyHookProc;
end.

==================Code for EXE ============
Drop a TEdit and a TMemo in your form.  Define the FormCreate & FormDestroy events:  Put the DLL & EXE in the same directory:

Set your Form's Name to "KeyHookForm" (*IMPORTANT* DLL uses this name to get back to you)
finally:
-Replace your unit's source with the following-
-----------------------------------------------

unit junk1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,  StdCtrls;

type
  TKeyHookForm = class(TForm)
    Edit1: TEdit;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
  { Private declarations }
    LibHandle,
    HHookProc : THandle;
    HookProc  : function(nCode: integer; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;

    function  InstallHook:boolean;

    procedure WMUser_KeyPressedGlobal(var Message : TMessage); message WM_User + 1;
  public
  { Public declarations }
  end;

var
  KeyHookForm: TKeyHookForm;

implementation

{$R *.DFM}

function TKeyHookForm.InstallHook:boolean;

var ok : boolean;

begin;
ok := false;
try
LibHandle := LoadLibrary('KBLib.dll');
if LibHandle <> 0 then
   begin
   @HookProc := GetProcAddress(LibHandle, 'KeyHookProc');
   if @HookProc <> nil then
      begin;
      HHookProc := SetWindowsHookEx(WH_KEYBOARD, HookProc, LibHandle, 0);
      ok := true;
      end
   else Application.MessageBox('Failed to get HookProc address', 'Error', mb_ok);
   end;
except on Exception do end;
InstallHook := ok;
end;


procedure TKeyHookForm.WMUser_KeyPressedGlobal(var Message : TMessage);

var
    ch : char;
    b  : boolean;
    p : array[0..255] of char;

begin
ch := Chr(LoByte(LoWord(Message.lParam)));
FillChar(p[0], 255, 0);
GetWindowText(GetForeGroundWindow,  p, 255);
b := (StrPos(StrLower(p), 'calculator') <> nil);
if b then
   begin;
     if ch > #31 then
        begin;
        Edit1.Text := Edit1.Text + ch;
        Memo1.SetSelTextBuf(pchar(Format('%s', [ch])));
        end
   else
     begin;
     Memo1.SetSelTextBuf(pchar(Format('[Char Code : %d]', [ord(ch)])));
     if ch = #13 then
        begin;
        Memo1.Lines.Add('');
        Edit1.Text := '';
        end;
     end;
   end;
end;


procedure TKeyHookForm.FormCreate(Sender: TObject);

begin
if not InstallHook then Application.Terminate;
end;


procedure TKeyHookForm.FormDestroy(Sender: TObject);

begin
if LibHandle <> 0 then
   begin
   if HHookProc <> 0 then UnhookWindowsHookEx(HHookProc);
   FreeLibrary(LibHandle);
   end;
end;

end.



0
 
LVL 7

Expert Comment

by:ahalya
ID: 2567047
btw, as inthe noted this hook is active for all apps, and fills in your memo if Calculator is the forground window.

There are two ways to overcome this:
(1) Theoretically You can "install" the hook when Calc becomes the forgroundwindow, and then "Uninstall" it, when calc loses focus; but finding the focus change then becomes the issue (& would need another Hook i guess :-) -or a timer -

(2) Better alternative: You can find the ThreadID of the Calculator, and set the Hook with the ThreadID as the third parameter -instead of zero-); I have never done this. It shd work as per MS's docs..

As long as the Code in the DLL isn't very complex, having a system Hook shouldn't be an issue i'd think.



and btw, While we are at it, here is another proc that could be handy:
if you're interested in the contents of the edit box in the "Calc" then this code does it. (Drop in another TEdit. It'll correctly show the content in Calculator's Edit Box)


procedure TKeyHookForm.GetCalcText;

var h, c : HWND;
    p : array[0..100] of char;

begin;
h := FindWindow('SciCalc', 'Calculator');
c := GetDlgItem(h, 414);
SendMessage(c, WM_GetText, 100, longint(@p));
Edit2.Text := string(p);
end;


0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Expert Comment

by:ahalya
ID: 2567048
..and btw, it appears that i have written too much for a 50-point question :-)
0
 
LVL 3

Author Comment

by:smurff
ID: 2568106
ahalya,

Ive been working on this for far too long. Thank you for your reply, I can now get to work on this and sleep at night :)
0
 
LVL 3

Author Comment

by:smurff
ID: 2572910
It didnt run, it just terminated... Ive copied exactly what you out. Where am I going wrong?
0
 
LVL 7

Expert Comment

by:ahalya
ID: 2573023
I have checked this on my computer and it works fine. (compiled in D2).

You have to make sure that you have the "correct" classname & title for your window. Look at the constants declared in the DLL.

DO NOT assign the 'YourFormTitle' to your form in designtime, rather assign it in runtime (in the FormCreate event, Caption := YourFormTitle;)  This is to make sure that the DLL finds the correct HWND.

Give me more details of the problem; put a breakpoint in the event handler for the message to see whether you get there.  [Also you can try "F7" and step through to find where it terminates]

0
 
LVL 7

Expert Comment

by:ahalya
ID: 2573034
oops, there is one mistake in the code i copied for you.  The name of the DLL should be KBLib.dpr (and not KBHook.DPR).
0
 
LVL 3

Author Comment

by:smurff
ID: 2573415
Yes found it, that was it. Thank you once again :)

This app will be the death of me!!
can every resourse on a form be monitored for change, e.g. listbox or colour of the form....?
0
 
LVL 7

Expert Comment

by:ahalya
ID: 2573463
well, the answer is Yes, but obviously it'll get tricky, and you'll need to spend considerable effort to make them work.

if you have a specific problem, then post it.
0
 
LVL 3

Author Comment

by:smurff
ID: 2577401
Ive been playing about with this for quite some time. Theres a network monitoring program on a server and when one of the 6 servers is down then the name turns to red. I was trying to code something that would email me or notify me over udp to tell me. Now because its not my program im having to build something that will monitor the form on the display, hence thats where my question came in.
I cant seem to get the code you helped me with to work in NT, I have looked at PSAPI.DLL but its not as straight forward as the win95 code you gave me. If you can point me in the right direction or give any help that would be great. maybe girls and Delphi dont mix well :)
0
 
LVL 7

Expert Comment

by:ahalya
ID: 2578546
Well, AFAIK, my code should work on NT without any modifications.

PSAPI.DLL is needed ONLY if you want to use the ToolHelp32 functions. (and we didn't use any ToolHelp functions in the above.)

About detecting the info on the other program:
The only way i could think of is to track all the messages, the other program is getting and find out what message does it get when there is an error.  Then you can write a MessageHook (similar to our KeyboradHook), and you program will get the info whenever the error occurs.

It will be more earsier if the text in the other program changes when an error occurs. Then you can monitor the text to decide  whether there is an error.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

726 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