Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Auf Eigenschaften von Kompos zugreifen mittels Kompo-Handle (https://www.delphipraxis.net/35529-auf-eigenschaften-von-kompos-zugreifen-mittels-kompo-handle.html)

Alex_ITA01 8. Dez 2004 15:00


Auf Eigenschaften von Kompos zugreifen mittels Kompo-Handle
 
Mir ist kein anderer Titel eingefallen,
also danke Ultimator habe ich jetzt das Handle der Komponente, die sich unter meiner Maus befindet.
Gibt es eine Möglichkeit, auf bestimmte Eigenschaften dieser Kompo jetzt zuzugreifen? Also wie gesagt, ich habe nur das Handle der Kompo aber ich kann in meiner Funktion nicht CheckBox1.XXX aufrufen weil die Funktion nur unterhalb des "implementation" Teils steht...
Hoffe ihr könnt mir helfen

MFG Alex

Ultimator 8. Dez 2004 15:13

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Welche Eigenschaften möchstest du denn im speziellen ändern/auslesen/etc.?
Wenn man weiß, was genau du brauchst, kann man dir besser helfen ;-)

Alex_ITA01 8. Dez 2004 15:18

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
also das Problem ist folgendes:
ich sende an meine Kompo wenn ich mich mit der Maus darüber befinde, eine Nachricht und diese verarbeitet dann ein paar Funktionen und zeigt ein Hint an.
Wenn ich jetzt aber mit der Maus mich von der Komponente wegbewege (also ich bin überhaupt nicht mehr auf der Kompo), dann will ich, dass der Hint versteckt wird.
Das Problem ist, dass ich solbald ich die Kompo verlasse, keine Nachrichten mehr an sie schicken kann.
Drum herum steckt noch ein Hook aber der ist glaube ich in diesen Fall "nebensächlich"

MFG Alex

Alex_ITA01 8. Dez 2004 15:27

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Hier mal die Komplette Kompo:

Delphi-Quellcode:
unit HintCBx;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Messages, Windows, Graphics;

const
  WM_HINT = WM_USER + 1;

type
  THintCBx = class(TCheckBox)
  private
    { Private-Deklarationen }
    HintWnd : THintWindow;
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    procedure WMHint(var Message: TMessage); message WM_HINT;

    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;
    procedure Loaded; override;
  published
    { Published-Deklarationen }
  end;

  function MouseProc(nCode : Integer; wParam: WPARAM; lParam : LPARAM): LRESULT; stdcall;

var
  MouseHook : HHOOK;
{ ---------------------------------------------------------------------------- }
procedure Register;
{ ---------------------------------------------------------------------------- }
implementation
{ ---------------------------------------------------------------------------- }
procedure Register;
begin
  RegisterComponents('Beispiele', [THintCBx]);
end;
{ ---------------------------------------------------------------------------- }
{ THintCBx }
{ ---------------------------------------------------------------------------- }
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;
{ ---------------------------------------------------------------------------- }
function MouseProc(nCode : Integer; wParam: WPARAM; lParam : LPARAM): LRESULT; stdcall;
var
  MPos     : TPoint;
  tmpHandle : HWND;
begin
  Result := CallNextHookEx(MouseHook,nCode,wParam,lParam);
  case nCode < 0 of
    TRUE : Exit; //wenn code kleiner 0 wird nix gemacht
    FALSE:
      begin
        if (wParam = WM_MOUSEMOVE) then
        begin
          GetCursorPos(MPos);
          SendMessage(WindowFromPoint(MPos), WM_USER, wParam, lParam);
          tmpHandle := RealWindowFromPoint(MPos);
          if tmpHandle > 0 then
          begin
            SendMessage(tmpHandle, WM_HINT, wParam, lParam);
          end;
        end;
      end;
  end;
end;
{ ---------------------------------------------------------------------------- }
constructor THintCBx.Create(AOwner: TComponent);
begin
  inherited;
  HintWnd := THintWindow.Create(Self);
  HintWnd.Color := clInfoBk;
  ShowHint := True;

  MouseHook := SetWindowsHookEx(WH_MOUSE, @MouseProc, 0, GetCurrentThreadId());
end;
{ ---------------------------------------------------------------------------- }
destructor THintCBx.Destroy;
begin
  HintWnd.Free;
  if MouseHook <> 0 then
    UnhookWindowsHookEx(MouseHook);
  inherited;
end;
{ ---------------------------------------------------------------------------- }
procedure THintCBx.Loaded;
begin
  Inherited Loaded;
  if ComponentState = [csDesigning] then Exit;
end;
{ ---------------------------------------------------------------------------- }
procedure THintCBx.WMHint(var Message: TMessage);
var
  rec : TRect;
  MPos: TPoint;
  tmpHint : String;
begin
  if Assigned(HintWnd) then
  begin
    tmpHint := Hint;
    GetCursorPos(MPos);
    MPos := ScreenToClient(MPos);

    rec := Rect(Self.Left, Self.Top, Self.Left + Self.Width, Self.Top + Self.Height);
    if (PtInRect(rec, point(MPos.X + Self.Left, MPos.Y + Self.Top))) and (not Self.Enabled) and (Self.ShowHint) then
    begin
      GetCursorPos(MPos);
      HintWnd.Color := clInfoBk;
      HintWnd.ActivateHint(Rect(MPos.X + 15, MPos.Y, MPos.X + 20 + HintWnd.Canvas.TextWidth(tmpHint), MPos.Y + 15), tmpHint);
    end
    else
      HintWnd.ReleaseHandle;
  end;
  Message.Result := 1;
end;
{ ---------------------------------------------------------------------------- }
end.
Sobald ich mich auf die Kompo bewege wird der Hint angezeigt aber wenn ich weggehe möchte ich Ihn wieder verstecken.Das Problem ist, dass eine Disabled CheckBox nicht auf WM_MOUSELEAVE reagiert...

Ich hoffe ihr könnt mir helfen

MFG

Alex_ITA01 8. Dez 2004 15:30

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Delphi-Quellcode:
SendMessage(WindowFromPoint(MPos), WM_USER, wParam, lParam);
Diese Zeile fliegt raus aus der MouseProc.
Die war vorhin nur für Testzwecke...

Ultimator 8. Dez 2004 15:53

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Hilft dir das eventuell weiter?
Du kannst soweit ich gelesen habe, die letzten paar Mauskoordinaten auslesen.
Wenn du das in deiner Kompo benutzt, kannst du vielleicht anhand dieser Koordinaten erkennen, ob die Maus schon die Combobox verlassen hat, oder sich noch darauf befindet.

Hoffe geholfen zu haben, MfG, Ultimator

OLLI_T 8. Dez 2004 16:14

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Hallo Alex!

Was ist ein Komponentenhandle? Welchem Zweck soll Deine Komponente dienen?

Gruss

Der OLLI

Alex_ITA01 9. Dez 2004 07:23

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
moin moin,
danke ultimator, werde es demnächst mal testen.

@OLLI_T: Mit KomponentenHandle meine ich das Handle meiner THintCBx abgeleitet von TCheckBox.
Normale TCheckBox(en) reagieren auf keine MouseEvents, wenn sie disabled sind, daher habe ich mir ein Hook geschrieben und sende eine EIGENE (WM_HINT) Nachricht an die Kompo damit diese die Mauskoordinaten verarbeiten kann und dann entweder ein Hint anzeigt oder nicht.
Der Hintergrund ist einfach, das disabledte CheckBoxen keinen HINT anzeigen...

MFG Alex

Alex_ITA01 9. Dez 2004 08:00

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
Also ich habe das von Ultimator mal eingebaut.
Auf WM_MOUSELEAVE reagiert meine Kompo nur ein einziges mal und zwar wenn ich das Programm starte, auf der sich meine Kompo befindet. Auf WM_MOUSEHOVER reagiert sie gar nicht.

Delphi-Quellcode:
unit HintCBx;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Messages, Windows, Graphics;

const
  WM_HINT = WM_USER + 1;

type
  THintCBx = class(TCheckBox)
  private
    { Private-Deklarationen }
    HintWnd : THintWindow;
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    procedure WMHint(var Message: TMessage); message WM_HINT;
    procedure WMMouseHover(var Message: TMessage); message WM_MOUSELEAVE;

    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;
    procedure Loaded; override;
  published
    { Published-Deklarationen }
  end;

  function MouseProc(nCode : Integer; wParam: WPARAM; lParam : LPARAM): LRESULT; stdcall;

var
  MouseHook : HHOOK;
{ ---------------------------------------------------------------------------- }
procedure Register;
{ ---------------------------------------------------------------------------- }
implementation
{ ---------------------------------------------------------------------------- }
procedure Register;
begin
  RegisterComponents('Beispiele', [THintCBx]);
end;
{ ---------------------------------------------------------------------------- }
{ THintCBx }
{ ---------------------------------------------------------------------------- }
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;
{ ---------------------------------------------------------------------------- }
function MouseProc(nCode : Integer; wParam: WPARAM; lParam : LPARAM): LRESULT; stdcall;
var
  MPos     : TPoint;
  tmpHandle : HWND;
begin
  Result := CallNextHookEx(MouseHook,nCode,wParam,lParam);
  case nCode < 0 of
    TRUE : Exit; //wenn code kleiner 0 wird nix gemacht
    FALSE:
      begin
        if (wParam = WM_MOUSEMOVE) then
        begin
          GetCursorPos(MPos);
          tmpHandle := RealWindowFromPoint(MPos);
          if tmpHandle > 0 then
          begin
            SendMessage(tmpHandle, WM_HINT, wParam, lParam);
          end;
        end;
      end;
  end;
end;
{ ---------------------------------------------------------------------------- }
constructor THintCBx.Create(AOwner: TComponent);
begin
  inherited;
  HintWnd := THintWindow.Create(Self);
  HintWnd.Color := clInfoBk;
  ShowHint := True;
  MouseHook := SetWindowsHookEx(WH_MOUSE, @MouseProc, 0, GetCurrentThreadId());
end;
{ ---------------------------------------------------------------------------- }
destructor THintCBx.Destroy;
begin
  HintWnd.Free;
  if MouseHook <> 0 then
    UnhookWindowsHookEx(MouseHook);
  inherited;
end;
{ ---------------------------------------------------------------------------- }
procedure THintCBx.Loaded;
var
  tme: TTRACKMOUSEEVENT;
  TrackMouseEvent_: function(var EventTrack: TTrackMouseEvent): BOOL; stdcall;
begin
  Inherited Loaded;
  if ComponentState = [csDesigning] then Exit;

  tme.cbSize := sizeof(TTRACKMOUSEEVENT);
  tme.dwFlags := TME_HOVER or TME_LEAVE;
  tme.dwHoverTime := 10;
  tme.hwndTrack := Self.Handle;
  @TrackMouseEvent_:= @TrackMouseEvent; // nur eine Pointerzuweisung!!!
  if TrackMouseEvent_(tme) then
  begin

  end;
end;
{ ---------------------------------------------------------------------------- }
procedure THintCBx.WMHint(var Message: TMessage);
var
  rec : TRect;
  MPos: TPoint;
  tmpHint : String;
begin
  if Assigned(HintWnd) then
  begin
    tmpHint := Hint;
    GetCursorPos(MPos);
    MPos := ScreenToClient(MPos);

    rec := Rect(Self.Left, Self.Top, Self.Left + Self.Width, Self.Top + Self.Height);
    if (PtInRect(rec, point(MPos.X + Self.Left, MPos.Y + Self.Top))) and (not Self.Enabled) and (Self.ShowHint) then
    begin
      GetCursorPos(MPos);
      HintWnd.Color := clInfoBk;
      HintWnd.ActivateHint(Rect(MPos.X + 15, MPos.Y, MPos.X + 20 + HintWnd.Canvas.TextWidth(tmpHint), MPos.Y + 15), tmpHint);
    end
    else
      HintWnd.ReleaseHandle;
  end;
  Message.Result := 1;
end;
{ ---------------------------------------------------------------------------- }
procedure THintCBx.WMMouseHover(var Message: TMessage);
begin
  //DIES IST NUR ZU TESTZWECKEN DAMIT ICH SEHE OB ER IN DIE NACHRICHT "KOMMT"
  HintWnd.ReleaseHandle;
end;
{ ---------------------------------------------------------------------------- }
end.
Ich hoffe, jemand hat eine Idee woran das liegen könnte.

MFG Alex

Alex_ITA01 9. Dez 2004 11:21

Re: Auf Eigenschaften von Kompos zugreifen mittels Kompo-Han
 
PUSH!!!

Hat keiner eine Idee, wie ich auf die MouseHover und MouseLeave-Nachrichten reagieren kann?
Ich weiß echt nicht, warum die MouseHover-Nachricht nicht ankommt....
MFG Alex

PS:
Delphi-Quellcode:
procedure WMMouseHover(var Message: TMessage); message WM_MOUSEHOVER;
procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE;
Ich habe beides schon probiert und bei MouseHover kommt er einfach nicht "rein"


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz