Autor Beitrag
Timelesk
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 82


Delphi 2006 Prof
BeitragVerfasst: So 07.11.10 18:18 
Hallo,

ich hole mir ein Handle einer Komponente die unter dem Mauszeiger liegt mit folgendem Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  wnd := Form1.Handle;
  pt:= mouse.CursorPos;
  windows.ScreenToClient(wnd, pt);
  Label1.Caption := inttostr(ChildWindowFromPoint(wnd, pt));


Nun möchte ich den Namen der Komponente, dessen Handle gefunden wurde.
Aber wie "wandle" ich das Handle in eine Komponente um?
Ich hab da überhaupt nichts passendes gefunden. Ist es zu offensichtlich?

Vielen Dank.

gruß
Timelesk
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: So 07.11.10 18:32 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function FindControlAtPos: TWinControl;
var
  Pt: TPoint;
begin
  GetCursorPos(Pt);
  Result := FindControl(WindowFromPoint(Pt));
end;
Timelesk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 82


Delphi 2006 Prof
BeitragVerfasst: So 07.11.10 18:40 
Hi,

ich möchte eine Art Hilfe schreiben.
Dazu lasse ich eine Form als Overlay über der Hauptform mit AlphaBlending anzeigen und der Benutzer kann dann zur Anzeige der Hilfe auf die Komponente "klicken"

Edit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  pt: TPoint;
  wnd: HWND;
begin
  wnd := Main.Handle;
  pt:= mouse.CursorPos;
  windows.ScreenToClient(wnd, pt);
  Main.Caption := FindControl(ChildWindowFromPoint(wnd, pt)).Name;


Das funktioniert nun soweit, dass er mir die richtige Komponente gibt, jedoch nicht in der Ebene.
Also wenn ich in einem Panel einen Button habe, gibt er mir den Namen des Panels, aber nicht des Buttons aus.
Weiß jemand, wie ich hier die nächste Ebene "erklimmen" kann?

Besten Dank.

@toms: Vielen Dank noch einmal für das "vor Augen führen" des Codes. Dadurch bin ich auf FindControl gestoßen.


gruß
Timelesk
Timelesk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 82


Delphi 2006 Prof
BeitragVerfasst: So 07.11.10 19:19 
Got it!

Es gibt die Funktion RealWindowFromPoint von Eugen Honeker.
Diese Funktion habe ich um ein Handle erweitert und umbenannt in ComponentFromPoint

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
function ComponentFromPoint(wnd: HWND; 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 := wnd;
  ce.pt.x := pt.x; //sche***-w9x
  ce.pt.y := pt.y; //sche***-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;


und dann einfach diesen Code irgendwo platzieren (FormClick, Timer):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  pt: TPoint;
  wnd: HWND;
begin
  wnd := Self.Handle;
  pt:= mouse.CursorPos;
  Label1.Caption := FindControl(ControlFromPoint(wnd, pt)).Name;