Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Maus-transparente Komponente (https://www.delphipraxis.net/106042-maus-transparente-komponente.html)

stahli 4. Jan 2008 09:52


Maus-transparente Komponente
 
Hallo Alle,

ich habe eine Komponente von TPaintBox abgeleitet, die einige Linien zeichnet.

Delphi-Quellcode:
  TLineMode = (lmNone, lmLTRTRB, lmLBRBRT, lmRTLTLB, lmRBLBLT);

  TLine = class(TPaintBox)
  private
    FLineMode: TLineMode;
    procedure SetLineMode(const Value: TLineMode);
  protected
    procedure Paint; override;
//    procedure Click; override;
//    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetPosition(X1, Y1, X2, Y2: Integer); virtual;
    procedure SetPositionTo(X, Y: Integer); virtual;
  published
    property LineMode: TLineMode read FLineMode write SetLineMode;
  end;

constructor TLine.Create(AOwner: TComponent);
begin
  inherited;
//  ControlStyle := [csNoStdEvents];
end;

Kann ich erreichen, dass diese für die Maus "durchlässig" ist?
Mit ControlStyle := [csNoStdEvents] erreiche ich, dass keine Mausereignisse behandelt werden. Die Komponente verdeckt aber immer noch den Parent.

Ich möchte gern, dass MouseOver von meiner Kompo gar nicht oder nur auf den nicht transparenten Bereichen "abgefangen" wird.
Mindestens wo meine Kompo unsichtbar ist, soll MouseOver der "sichbaren Komponente dahinter" behandelt werden.


(Alternativ habe ich schon versucht, direkt auf den Canvas zu zeichnen. Das ist etwas ungünstig, da schlecht auf Veränderungen reagiert werden kann.)


stahli

xaromz 4. Jan 2008 10:05

Re: Maus-transparente Komponente
 
Hallo,

um Deine Komponente für die Maus transparent zu setzen, musst Du die Message CM_HITTEST behandeln.

Gruß
xaromz

stahli 4. Jan 2008 10:49

Re: Maus-transparente Komponente
 
Super Klasse!
Danke!

Delphi-Quellcode:
  procedure CMHitTest(var Msg: TWMMouse); message CM_HITTEST;

  procedure TLine.CMHitTest(var Msg: TWMMouse);
  begin
    inherited;
  {
    if Assigned(PicUp) and Assigned(PicUp.Bitmap) and Transparent and
      (Msg.XPos < PicUp.Bitmap.Width) and (Msg.YPos < PicUp.Bitmap.Height) and
      (PicUp.Bitmap.Canvas.Pixels[Msg.XPos, Msg.YPos] = (Picture.Bitmap.TransparentColor and $FFFFFF)) then
      Msg.Result := 0;
  }
    Msg.Result := 0;
  end;
Da ich keine Transparent-Farbe habe setze ich Result einfach immer auf 0. Perfekt! :-)

stahli

stahli 27. Mär 2008 08:52

Re: Maus-transparente Komponente
 
Mit der TPaintBox ging das wunderbar...

Wie kann ich das auch für ein TPanel machen?
CMHitTest wird bei meiner abgeleitetetn Komponente nicht aufgerufen.
Ein Klick soll sich direkt auf dessen Parent beziehen.

Danke
Stahli

SirThornberry 27. Mär 2008 09:38

Re: Maus-transparente Komponente
 
auch beim panel sollte es funktionieren. Mich wundert eigentlich das bei deiner Paintbox der gepostete Code funktioniert. Du solltest am besten von deiner Komponenten ableiten und darin das Messagehandling direkt implementieren. Andernfalls musst du eben die gesamte WindowProc umbiegen

stahli 27. Mär 2008 09:48

Re: Maus-transparente Komponente
 
Ich weiß noch nicht recht, was Du genau meinst.
Die TLine funktioniert so:

Delphi-Quellcode:
  TLine = class(TPaintBox)
  private
    FLineMode: TLineMode;
    FFromX: Integer;
    FFromY: Integer;
    FToX: Integer;
    FToY: Integer;
  protected
    procedure SetLineMode(const Value: TLineMode);
    procedure SetFromX(const Value: Integer);
    procedure SetToX(const Value: Integer);
    procedure SetFromY(const Value: Integer);
    procedure SetToY(const Value: Integer);
    procedure Paint; override;
    procedure CMHitTest(var Msg: TWMMouse); message CM_HITTEST;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetPosition(X1, Y1, X2, Y2: Integer); virtual;
    procedure SetPositionTo(X, Y: Integer); virtual;
    procedure DefineStyle; virtual;
  published
    property LineMode: TLineMode read FLineMode write SetLineMode;
    property FromX: Integer read FFromX write SetFromX;
    property FromY: Integer read FFromY write SetFromY;
    property ToX: Integer read FToX write SetToX;
    property ToY: Integer read FToY write SetToY;
  end;

...

{ TLine }

procedure TLine.CMHitTest(var Msg: TWMMouse);
begin
  inherited;
{
  if Assigned(PicUp) and Assigned(PicUp.Bitmap) and Transparent and
    (Msg.XPos < PicUp.Bitmap.Width) and (Msg.YPos < PicUp.Bitmap.Height) and
    (PicUp.Bitmap.Canvas.Pixels[Msg.XPos, Msg.YPos] = (Picture.Bitmap.TransparentColor and $FFFFFF)) then
    Msg.Result := 0;
}
  Msg.Result := 0;
end;

Für meine Panelableitung habe ich das genau so geregelt:
Delphi-Quellcode:
  TPanelHead = class(TPanel)
  private
  protected
    procedure CMHitTest(var Msg: TWMMouse); message CM_HITTEST;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

...

{ TPanelHead }

procedure TPanelHead.CMHitTest(var Msg: TWMMouse);
begin
  beep;           // HIER GEHT NIX
  inherited;
{
  if Assigned(PicUp) and Assigned(PicUp.Bitmap) and Transparent and
    (Msg.XPos < PicUp.Bitmap.Width) and (Msg.YPos < PicUp.Bitmap.Height) and
    (PicUp.Bitmap.Canvas.Pixels[Msg.XPos, Msg.YPos] = (Picture.Bitmap.TransparentColor and $FFFFFF)) then
    Msg.Result := 0;
}
  Msg.Result := 0;
end;
Hier wird CMHitTest aber nicht erreicht...

Medium 27. Mär 2008 10:01

Re: Maus-transparente Komponente
 
Ich würde TLine nebenbei von TGraphicControl oder TWinControl ableiten (je nach dem, ob du dafür ein Handle brauchst, bzw. die Komponente andere WinControls verdecken können soll).

Bei dem Panel bin ich auch etwas ratlos. Bevor ich auf CM_HITTEST gestoßen bin, habe ich allerdings mit MSDN-Library durchsuchenRegions und TWinControl Nachfahren gearbeitet. Diese funktionieren alledings dann auch nur mit TWinControl-Nachfahren (was ein TPanel ja auch ist).

Muetze1 27. Mär 2008 11:45

Re: Maus-transparente Komponente
 
CM_HITTEST ist die VCL Interne Botschaft welche von dem Parent ausgelöst wird (auf Erhalt der WM_NCHITTEST Botschaft) und entsprechend er Botschaft diese beantwortet. TPaintBox implementiert kein Fenster und erhält somit diese Windows Botschaft nicht sondern wird von dem Parent mit der CM_HITTEST gefragt. Bei einem Panel ist das anders, dieses hat ein Fensterhandle und bekommst somit direkt die WM_NCHITTEST Botschaft und behandelt diese selber. Somit dort nicht CM_HITTEST behandeln sondern WM_NCHITTEST.

stahli 27. Mär 2008 12:40

Re: Maus-transparente Komponente
 
Hallo Muetze1,

danke dafür.

Die Methode wird ausgeführt:
Delphi-Quellcode:
procedure TPanelHead.WMNCHitTest(var Message: TWMNCHitTest);
begin
  inherited;
  Beep;
  Message.Result := 0;
end;
Der Mausklick erreicht aber nicht das Parent meines TPanelHead.
Kannst Du das nochmal anschauen? Ich komme da nicht voran.

Muetze1 27. Mär 2008 13:02

Re: Maus-transparente Komponente
 
Klemm doch einfach mal die alte Behandlungsroutine ab, also inherited auskommentieren.

Zum anderen verstehe ich immer nicht, wie Leute damit arbeiten können direkt irgendwelche Zahlen anzugeben ohne zu Wissen um was es sich handelt bzw anders: zu wissen was man macht.

Schonmal die Dokumentation zu der Botschaft angeschaut? Was ist denn nun 0? Ich würde HTTRANSPARENT zurück geben, wenn nicht 0 zufälligerweise schon dieser Wert sein sollte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 Uhr.
Seite 1 von 2  1 2      

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