We help IT Professionals succeed at work.

getfocus question

mabell
mabell asked
on
Hello you :) .. I just want to know if its possible to make/have a function similar to getfocus but who return the handle of the control that have focus on another app? I'll appreciate a little exemple of how to do it .. if its possible :)
thx
Comment
Watch Question

Commented:
What's wrong with the GetFocus() API function..?

Commented:
Try using AttachThreadInput() and GetWindowThreadProcessId() to attach our app the the other one...

Author

Commented:
The getfocus api function only return the handle of the control that receive the focus on my app only (I think).. what I need is a function who give me the handle of the control that receive the focus of the active window .. not my app

I'll try what u said as soon as possible
thx :)

Commented:
Epsylon's suggestion is right. Only the mention of "GetForegroundWindow" was missing. Here comes a little function:

function GetFocusSystemWide : dword;
var tid : dword;
begin
  tid := GetWindowThreadProcessID(GetForegroundWindow, nil);
  AttachThreadInput(GetCurrentThreadID, tid, true);
  result := GetFocus;
  AttachThreadInput(GetCurrentThreadID, tid, false);
end;

Regards, Madshi.

Author

Commented:
Thx :) it works fine except that when my app is attached to the active window the active window dont process/receive double click until my app is detached from it. is it normal  and what I need to do (if its possible) to correct this problem?

thx :)

Commented:
You're right, I had exactly the same problem, too. The solution is quite simple: Don't call the "GetFocusSystemWide" function too often.
If that is no real solution for you, you need to go a different way, which is write a system wide message hook (which needs a little dll), which hooks WM_SETFOCUS and WM_ACTIVATE(APP) messages and so always logs the current focused window. I know, it's quite ugly to do such a complicated thing just to ask the focused window...   :-(

Regards, Madshi.
listening...

Author

Commented:
Hehe in fact but .. can we catch the double click and send it back to the app attached ? or check if the application requier double clicks or if the app have double click event.. so we will know when call or not call the GetFocusSystemWide function ?

Author

Commented:
Hehe in fact but .. can we catch the double click and send it back to the app attached ? or check if the application requier double clicks or if the app have double click event.. so we will know when call or not call the GetFocusSystemWide function ?

Commented:
Hmmm... Maybe you could send the double click back, not sure. Have not tried that, yet. However, I don't think you can check whether the application requires double clicks or something like that...

How often and for what purpose do you call the GetFocusSystemWide function? I mean if you don't call it too often, it's not very probable that exactly in that time a double click happens, or am I wrong?

Regards, Madshi.

Author

Commented:
Hehe in fact but .. can we catch the double click and send it back to the app attached ? or check if the application requier double clicks or if the app have double click event.. so we will know when call or not call the GetFocusSystemWide function ?

Author

Commented:
Im doing a little Keylogger and I want to know where the keys are pressed in the active window .. so I call the getfocusSytemWide function each time a key is pressed and with the handle of the focus I Call getClassName .. the logged keys are written in a memo bellow the active app and below the active handle and className.. everythings works fine .. except the double click problem hehe

Commented:
How do you get the keys system wide? Do you use a keyboard hook?

If you only call GetFocusSystemWide, when a key was pressed, then why does this hinder double clicks? I mean do you press a key and do a double click at the same time? I never do!

Author

Commented:
The problem is that every user dont type only one key in the active window .. and I need to call the function to check the change of control or handle to seperate the keys
ex: you have a form with three editboxes .. one for the name .. the other for the lastname and the last with the age .. instead of having all keys togetter Like -User Information Form-
MartyBishop25

I have this
-User Information Form-
<2323 EditBox>
Marty
<2383 EditBox>
Bishop
<2235 EditBox>
25

So I call the GetfocusSystem wide very often .. to determinate the change of control


Commented:
Then you have only 2 choices, I think:

(1) Try to send double clicks back (but I don't know how) or
(2) Write a little message hook like I suggested earlier...

Here comes the sources of my little dll, which I use to ask the current mouse cursor (system wide):

library hook;

uses Windows, Messages;

type THookRec = record
                  hook   : cardinal;
                  cursor : cardinal;
                end;
var  PHookRec : ^THookRec;

function HookProc(code, wParam, lParam: integer) : integer; stdcall;
begin
  if PHookRec <> nil then begin
    if (code >= 0) and (lParam <> 0) and (not IsBadReadPtr(pointer(lParam), 20)) and
       (PCWPRETSTRUCT(lParam)^.message = WM_SETCURSOR) then
      PHookRec^.cursor := GetCursor;
    result := CallNextHookEx(PHookRec^.hook, code, wParam, lParam);
  end else
    result := 0;
end;

function DllEntryPoint(hInstance, reason, reserved: cardinal) : longBool; stdcall;
begin
  result := true;
  if reason = DLL_PROCESS_ATTACH then
    PHookRec := MapViewOfFile(OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 'MtsGetCursorHook'),
                              FILE_MAP_ALL_ACCESS, 0, 0, 0);
end;

exports
  DllEntryPoint index 1,
  HookProc      index 2;

end.

Here is how I use the stuff in the application:

var
  FHookDll   : cardinal;
  FMapHandle : cardinal;
  FPHookRec  : ^THookRec;

procedure InstallHook;
begin
  FMapHandle := CreateFileMapping(maxCard, nil, PAGE_READWRITE, 0, 8, 'MtsGetCursorHook');
  FPHookRec := MapViewOfFile(FMapHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  FHookDll := LoadLibrary(pchar(GetStartPath + 'hook.dll'));
  FPHookRec^.hook := SetWindowsHookEx(WH_CALLWNDPROCRET, GetProcAddress(FHookDll, 'HookProc'), FHookDll, 0);
end;

procedure UninstallHook;
begin
  UnhookWindowsHookEx(FPHookRec^.hook);
  FreeLibrary(FHookDll);
  UnmapViewOfFile(FPHookRec);
  CloseHandle(FMapHandle);
end;

function GetSystemWideCursor : dword;
begin
  result := FPHookRec^.cursor;
end;

There's one thing you should know: Delphi DLLs do several things in their initialization phase, which are not very good for hooking DLLs. So sometimes Delphi compiled hooking DLLs make problems. To solve this problem I've written a little tool, which patches Delphi DLLs in a way, that the standard entry point is NOT called, instead the exported DllEntryPoint function is called. As a negative side effect unit initializations are not called. So you can only do quite limited things with such DLLs. But: Hooking works very reliably. Here you can download the tool:

http://www.madshi.net/hackDll.zip

Please use it as the help example suggests.

Regards, Madshi.

Author

Commented:
Ok thx for the idea :))

Explore More ContentExplore courses, solutions, and other research materials related to this topic.