function RealWindowFromPoint(pt: TPoint
{$IFDEF RWFPCHOICE}; swinvis: boolean = true
{$ENDIF}): HWND;
(*
Functionality:
This will get a windows handle from the position of the mouse, even if it is
for example inside the area occupied by a groupbox.
[GENERIC] It may be used as a substitute to "ChildWindowFromPoint" which
however doesn't work as well as this one ;)
Featured by Eugen, all credits go to him ...
Corrected version (by Eugen) - should work on 9x now ;)
I changed a few things more to have a more consistent behavior
*)
type
PCHILDS_ENUM = ^CHILDS_ENUM;
CHILDS_ENUM =
record
nDiff: integer;
hWndFound: HWND;
pt: TPoint;
{$IFDEF RWFPCHOICE}
showinvis: boolean;
{$ENDIF RWFPCHOICE}
end;
var
ce: CHILDS_ENUM;
function EnumProc(hwndChild: HWND; lParam: LPARAM): Boolean;
stdcall;
(*
Functionality:
This is the core of RealWindowFromPoint. It enumerates child windows of the
window given by handle.
[SPECIFIC] only useful in the context of this function.
*)
var
rc: TRECT;
begin
GetWindowRect(hwndChild, rc);
with PCHILDS_ENUM(lParam)^, rc
do
{$IFDEF RWFPCHOICE}
case showinvis
of
true:
if (pt.x >= Left)
and (pt.x < Right)
and (pt.y >= Top)
and (pt.y < Bottom)
and
(nDiff > (Right - Left) + (Bottom - Top))
then
begin
hWndFound := hwndChild;
nDiff := (Right - Left) + (Bottom - Top);
end;
else
if (pt.x >= Left)
and (pt.x < Right)
and (pt.y >= Top)
and (pt.y < Bottom)
and
(nDiff > (Right - Left) + (Bottom - Top))
and IsWindowVisible(hwndChild)
then
begin
hWndFound := hwndChild;
nDiff := (Right - Left) + (Bottom - Top);
end;
end;
{$ELSE RWFPCHOICE}
if (pt.x >= Left)
and (pt.x < Right)
and (pt.y >= Top)
and (pt.y < Bottom)
and
(nDiff > (Right - Left) + (Bottom - Top))
then
begin
hWndFound := hwndChild;
nDiff := (Right - Left) + (Bottom - Top);
end;
{$ENDIF RWFPCHOICE}
Result := True;
end;
begin
ce.nDiff := MAXLONG;
ce.hWndFound := WindowFromPoint(pt);
ce.pt.x := pt.x;
//scheiss-w9x
ce.pt.y := pt.y;
//scheiss-w9x
{$IFDEF RWFPCHOICE}
ce.showinvis := swinvis;
{$ENDIF RWFPCHOICE}
if (ce.hWndFound <> 0)
then
begin
// Windows 9x does not like NULL for a handle handed over to EnumChildWindows()
// The NT platform treats this just like EnumWindows()
if (GetWindowLong(ce.hWndFound, GWL_STYLE)
and WS_CHILD <> 0)
then
ce.hwndFound := GetParent(ce.hwndFound);
EnumChildWindows(ce.hWndFound, @EnumProc, Integer(@ce));
end;
Result := ce.hwndFound;
end;