AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Kompo um bei "disabled" Delphi-Kompos ein Hint's zu zeigen
Thema durchsuchen
Ansicht
Themen-Optionen

Kompo um bei "disabled" Delphi-Kompos ein Hint's zu zeigen

Ein Thema von Alex_ITA01 · begonnen am 10. Jan 2005 · letzter Beitrag vom 5. Okt 2012
Antwort Antwort
Alex_ITA01
Registriert seit: 22. Sep 2003
Hallo erstmal,
hier ist meine fertige Komponente...
Als erstes einmal eine Erklärung, warum sie nur als .dcu vorliegt:
Ich habe mich im Internet über bestimmte Funktionen schlau gemacht und musste ein paar anpassen bzw. ändern. Jetzt muss ich mich erstmal schlau machen, ob der Author des "ehemaligen" Sources damit einverstanden ist (aber ich denke schon, weil es nur eine Erweiterung bzw. Verbesserung seines Sources war).
Also falls ich das okay habe, dann werde ich alles nach OpenSource verschieben...

Jetzt die Erklärung der Komponente:
Ihr braucht sie nur ein einziges Mal pro Anwendung verwenden (es wird sowieso überprüft ob man diese Kompo mehrmals aufs Formular ablegen will...). Die Komponente ist ein Workaround für einige Delphi-Komponenten (Button,Edit,CheckBox,StringGrid,Panel usw.) die standardmäßig KEINEN Hint anzeigen wenn sie "not enabled" sind.
Also ganz einfaches Beispiel:

Mit meiner Kompo:
Neues Formular -> Button drauf -> ShowHint = True -> Hint = Button1 -> Enabled = False
Ergebnis: Hint wird angezeigt

Ohne meine Kompo:
Neues Formular -> Button drauf -> ShowHint = True -> Hint = Button1 -> Enabled = False
Ergebnis: Hint wird NICHT angezeigt

Also wer es gebrauchen kann solls nutzen
Wünsche euch viel Spaß...

MFG Alex

Download: ca. 5k
Angehängte Dateien
Dateityp: zip hintkompo_184.zip (3,2 KB, 21x aufgerufen)
Let's fetz sprach der Frosch und sprang in den Mixer
 
Alex_ITA01

 
Delphi 12 Athens
 
#2
  Alt 20. Dez 2006, 16:00
Hallo erstmal,
nach langer Zeit wurde ich angesprochen, ob ich nicht den Source für diese Kompo auch posten könnte.
Es spricht nichts dagegen. Die Funktion EnumProc ist glaube ich von Eugen gewesen. Ich habe diese im Netz gefunden.
Ich hoffe, falls es nicht Eugen war, dass sich der richtige Author jetzt nicht angegriffen fühlt
Viel Spaß damit.
MFG Alex

PS: Es wird alles über einen Maushook gemacht

Delphi-Quellcode:
unit HintKompo;

interface

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

type
  THintKompo = class(TComponent)
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;
    procedure Loaded; override;
  published
    { Published-Deklarationen }
  end;

  procedure ShowText(Text : String; X, Y : Integer);
  function MouseProc(nCode : Integer; wParam: WPARAM; lParam : LPARAM): LRESULT; stdcall; { MouseHook-Procedure }

var
  HintWnd : THintWindow; { Instanz für das Anzeigen des Hint's }
  MouseHook : HHOOK; { Instanz für den MouseHook }
  InstanceCount : Integer = 0; { erlaubt nur eine Instanz der Komponente pro Anwendung }

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Jung', [THintKompo]);
end;

function RealWindowFromPoint(pt: TPoint): HWND;
type
  PCHILDS_ENUM = ^CHILDS_ENUM;
  CHILDS_ENUM = record
    nDiff : integer;
    hWndFound : HWND;
    pt : TPoint;
  end;

var
  ce: CHILDS_ENUM;

  function EnumProc(hwndChild: HWND; lParam: LPARAM): Boolean; stdcall;
  var
    rc: TRECT;
  begin
    GetWindowRect(hwndChild, rc);

    with PCHILDS_ENUM(lParam)^, rc do
    begin
      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;
    end;
    Result := True;
  end;

begin
  ce.nDiff := MAXLONG;
  ce.hWndFound := WindowFromPoint(pt);
  ce.pt.X := pt.X;
  ce.pt.Y := pt.Y;
  if (ce.hWndFound <> 0) then
  begin
    if (GetWindowLong(ce.hWndFound, GWL_STYLE) and WS_OVERLAPPED 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;
  X, Y : Integer;
  MousePos : PMOUSEHOOKSTRUCT;
begin
  Result := CallNextHookEx(MouseHook,nCode,wParam,lParam);
  case nCode < 0 of
    TRUE: Exit;
    FALSE:
      begin
        if (wParam = WM_MOUSEMOVE) then
        begin
          MousePos := PMOUSEHOOKSTRUCT(lParam);
          X := MousePos^.pt.X;
          Y := MousePos^.pt.Y;

          if not Assigned(HintWnd) then Exit;
          GetCursorPos(MPos);
          tmpHandle := RealWindowFromPoint(MPos);
          if FindControl(tmpHandle) = Nil then Exit;

          if IsPublishedProp(FindControl(tmpHandle), 'Enabled') then
          begin
            if IsPublishedProp(FindControl(tmpHandle), 'ShowHint') then
            begin
              if (FindControl(tmpHandle).Enabled = False) and
                 (FindControl(tmpHandle).ShowHint = True) then
              begin
                if FindControl(tmpHandle).Hint = 'then
                  ShowText('Hint',X,Y)
                else
                  ShowText(FindControl(tmpHandle).Hint,X,Y);
              end
              else
              begin
                if Assigned(HintWnd) then
                  HintWnd.ReleaseHandle;
              end;
            end;
          end;
        end;
      end;
  end;
end;

procedure ShowText(Text: String; X, Y : Integer);
begin
  if Assigned(HintWnd) then
  begin
    HintWnd.Color := clInfoBk;
    HintWnd.ActivateHint(Rect(X + 15, Y, X + 20 + HintWnd.Canvas.TextWidth(Text), Y + 15), Text);
  end;
end;

constructor THintKompo.Create(AOwner: TComponent);
begin
  inherited;
  HintWnd := THintWindow.Create(Self);
  HintWnd.Color := clInfoBk;

  Inc(InstanceCount);
  if InstanceCount > 1 then
    raise Exception.Create('Diese Komponente darf nur einmal pro Anwendung existieren!');
end;

destructor THintKompo.Destroy;
begin
  Dec(InstanceCount);

  if MouseHook <> 0 then
    UnhookWindowsHookEx(MouseHook);
  inherited;
end;

procedure THintKompo.Loaded;
begin
  Inherited Loaded;
  if ComponentState = [csDesigning] then Exit;
  MouseHook := SetWindowsHookEx(WH_MOUSE, @MouseProc, 0, GetCurrentThreadId);
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms

 
Delphi XE Professional
 
#3
  Alt 27. Jan 2008, 17:04
Ich habe noch eine kürzere Möglichkeit gefunden bei experts-exchange.
Vorteil: Es ist keine Komponente. Unit kann eingebundenn werden und Hints werden bei
inaktiven Controls angezeigt.

Delphi-Quellcode:
unit ControlsHook;
////////////////////////////////////////////////////////////////////////////////
//
// Unit : ControlsHook
// Author : rllibby
// Date : 12.20.2005
// Description : Code for runtime hooking of the FindVCLWindow function in the
// controls unit.
//
////////////////////////////////////////////////////////////////////////////////
interface

////////////////////////////////////////////////////////////////////////////////
// Include units
////////////////////////////////////////////////////////////////////////////////
uses
  Windows, Controls, Forms;

////////////////////////////////////////////////////////////////////////////////
// ASM block structure for installing hook
////////////////////////////////////////////////////////////////////////////////
type
  TJmpBlock = packed record
    Code: Byte;
    Offset: Integer;
  end;

////////////////////////////////////////////////////////////////////////////////
// Our replacement for the FindVCLWindow function
////////////////////////////////////////////////////////////////////////////////
function HookFindVCLWindow(const Pos: TPoint): TWinControl;

implementation

function HookFindVCLWindow(const Pos: TPoint): TWinControl;
var Form: TForm;
  Handle: HWND;
begin

  Result := nil;
  Form := Screen.ActiveForm;
  if Assigned(Form) then
  begin
    Handle := ChildWindowFromPoint(Form.Handle, Form.ScreenToClient(Pos));
    while (Handle <> 0) do
    begin
      Result := FindControl(Handle);
      if Assigned(Result) and Result.Visible then
        break
      else
        Result := nil;
      Handle := GetParent(Handle);
    end;
  end;

end;

procedure SetFunctionHook;
var jmpBlock: TJmpBlock;
  dwProtect: LongWord;
  lpFunc: Pointer;
begin

  // Get the address of the FindVCLWindow function
  lpFunc := @FindVCLWindow;

  // Calculate the jump offset
  jmpBlock.Code := $E9;
  jmpBlock.Offset := Integer(@HookFindVCLWindow) - (Integer(lpFunc) + SizeOf(TJmpBlock));

  // Unprotect the memory so we can add the new asm code
  VirtualProtect(lpFunc, SizeOf(TJmpBlock), PAGE_EXECUTE_READWRITE, dwProtect);

  // Update the FindVCLWindow with a jump to our hook
  Move(jmpBlock, lpFunc^, SizeOf(TJmpBlock));

end;

initialization

  // Set the function hook
  SetFunctionHook;

end.
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

 
Delphi 12 Athens
 
#4
  Alt 5. Okt 2012, 17:06
Hmmm, tom's Code hat in unserem XE irgendwie überhaupt nicht funktioniert.
Keine Fehlermeldungen oder so, aber es tauchten auch einfach keine hints auf. (hab aber nicht weitergesucht, nachdem der andere Code soweit eigentlich funktionierte)

Ich hab den Code von Alex_ITA01 aber nochmal überarbeitet und einige Bugs behoben.

Es ist jetzt keine Komponente mehr, da es eh nur einmal im Programm verwendet werden kann, reicht es, wenn man nur die Unit einbindet.
So könnten auch TDE-Besitzer es nutzen und es nängt nicht sinnlos in der IDE rum ... Tipp: Kennt ihr noch die sinnlose TXPManifest-Komponente?

EnumProc hatte z.B. den falschen Rückgabetypen. (Delphi-Boolean = 1 Byte und Windows-BOOL = 4 Byte, bzw. es ist so groß wie ein CPU-Register)

Das böse WITH ist auch raus.

Typkonvertierungen sind auch in Bezug auf andere Zielplattforem (vorallem Win64) überarbeitet.
Pointer <> Integer (nja, hätte man den Integer nicht eingefroren, wäre es fast richtig)

Und das Verhalten wurde etwas mehr an die anderen delphi-Hint angepaßt.
- die korrekte Hint-Klasse wird verwendet
- auch die Farbe wird ordentlich übernommen
- der Hint verfolgt den Zeiger nicht mehr so penetrant
- und was weiß ich was ich sonst noch alles gemacht hab



Hinweis: Es ist alles natürlich nur für die VCL (kein FMX) und ob es unter Win64 läuft, konnte ich nicht testen.
Angehängte Dateien
Dateityp: pas DisabledHintHook.pas (2,9 KB, 22x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:39 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