Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Detecting change on another app

Posted on 2000-02-28
12
Medium Priority
?
282 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 200 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

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

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…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

636 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