I'm not a Delphi guy, so forgive the stupid question. I notice when
running a Delphi application that the window handles for controls
(edit fields, buttons, etc.) are not static. In other words, an edit
field on an application might have an ID of 0x000502cd the first time
I run it, and the same edit field could have an ID of 0x00001133 the
next time I run the program.
I'm interested in determining which field in an executable has focus
at any given point in time, and obviously the non-static nature of the
controls presents a problem. Is there any way to either force the
control IDs to be static, or to otherwise identify a particular
control between instantiations of an application?
Additional (possibly significant information): I'm only interested in
Delphi on Windows operating systems. I have a good background in VC++.
I determine the currently running program and the ID of the control in
this fashion:
HWND hwnd = GetForegroundWindow();
LONG_PTR lpID;
DWORD dwProcID;
TCHAR lpszFilename[MAX_PATH];
// Do some testing of hwnd (make sure it's not this process, etc.)
// Get the process name (very abbreviated)
GetWindowThreadProcessId(hwnd,&dwProcID);
HANDLE hProc = OpenProcess(...,dwProcID);
HMODULE hMod;
EnumProcessModules(hProc,&hModule,....)
GetModuleBase(hProc,hModule,lpszFilename,MAX_PATH);
// Get the window with focus
GUITHREADINFO tInfo;
tInfo.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(NULL,&tInfo);
if (tInfo.hwndFocus)
{
lpID = GetWindowLongPtr(tInfo.hwndFocus,GWLP_ID);
// do stuff depending on process name and lpID
}
Thanks for any information.
In any form -
Self.ActiveControl
- this returns a TWinControl, If the fields you are interested in are
descendants of TWinControl, and the properties or methods are
introduced by the descendant control type, then you would need to test
& typecast the returned TWinControl.
ie
var
ActCtrl : TWinControl;
ActCtrl := Self.ActiveControl;
if (ActCtrl is TEdit) then
SelectedText := TEdit(ActCtrl).SelText;
Application.Active is set if the application has the focus somewhere.
Alan Lloyd
Thanks, Alan.
I guess I should also have said that I need to be able to do this from
an external application -- one that is "just running" and looking at
whatever the currently active window is. In other words, I'm not
interested in writing a Delphi application that tests itself to see
what field has input focus, I want to be able to get this information
in a VC++ program running as a service, and the window that has the
focus happens to be a Delphi program. The service, in fact, already
exists and does exactly the right thing for C and VC programs --
programs that have static control IDs (the control ID is the same
every time the program is run). But because Delphi apparently assigns
control IDs at runtime (rather than at design time), my service is
failing miserably to correctly identify the Delphi program's focus
field.
So the revised version of the question is, is there a way to
interrogate a running Delphi program from another program and
determine which field has focus?
Thanks.
> But because Delphi apparently assigns
> control IDs at runtime (rather than at design time), my service is
> failing miserably to correctly identify the Delphi program's focus
> field.
Delphi controls call CreateWindowEx with a HMENU=0 and when a handle is returned
they set the same value to be the window identifier.
> So the revised version of the question is, is there a way to
> interrogate a running Delphi program from another program and
> determine which field has focus?
You've got the handle to the window, no?
Regards.
I do have a handle to the window. My problem is that the window handle
changes every time the program runs, and I'm using the numeric value
of the window handle to determine context. For example, explorer.exe's
"Address" field has an ID of 0x0000a205; its folder tree view pane has
an ID of 0x00000064; its filename pane has an ID of 0x00000001. The
service uses these values to recognize what the user is doing at any
given time. For example, when the service notices that the "address"
field of explorer has focus, it can provide a clue to the user in the
form of a pop-up message: "Type a file pathname." (Ignore for a minute
that a service can't do this directly and that explorer is the program
I'm using as an example.) What we're trying to provide is something
like tooltips for programs to which we don't have the source code.
This works great for C and VC programs, but I can't determine
"context" of a control in a Delphi program.
So is there a way to either 1) run a Delphi program with a "/
makewindowidsconstant" switch :) or 2) determine what a particular
control in a Delphi program is "for". Yeah, I didn't think so.
> So is there a way to either 1) run a Delphi program with a "/
> makewindowidsconstant" switch :) or 2) determine what a particular
> control in a Delphi program is "for". Yeah, I didn't think so.
No, I don't think so either.
Your approach is not a very good one. It may have served you well up to
this point how ever, it's only due to the fact as to how the app's you
have targeted initiate themselves.
Delphi in many cases does not actually create a window handle until its
time to display that window for the first time. Many things in the
program can be happening to make the order in which they are created
seem random.
Your best bet would be to Enumerate the Child windows, there by,
gathering all the Class and Window Text information which returns the
handles. Class and Window Text should be constant in most cases.