I am quite new to Delphi and wanted to practise a little bit.
While trying to implement a basic custom component I couldn't figure out how to "catch" events like "OnMouseWheel" or "OnMouseMove" etc.. (the component just should let the user zoom into an TImage)
At the moment I wrote some public functions like LMouseWheel(...), now the user of the component has to implement the OnMouseWheel-Function, but only has to call the public MouseWheel(...)-Method to get the component working. Is there a way, that the MouseWheel-Method gets called by default?
The code is an abstract of my custom component. What do I have to do, to immediately call the LMouseWheel(...)-Method, when the user scrolls the mouse wheel over my component?
unit TLZoomage;
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
interface
{$IFDEF MSWINDOWS}
uses
Classes, SysUtils, FileUtil, Forms, LCLType, Controls, Graphics,
Dialogs, ExtCtrls, Spin, Types, Math;
type
{ TLZoomage }
TLZoomage = class(TImage)
private
{ Private-Deklarationen }
FStartZoom: integer;
FmaxZoom: integer;
FminZoom: integer;
FcurrentZoom: integer;
FzoomSpeed: integer;
mouseMoveOrigin: TPoint;
procedure setCurrentZoom(AValue: integer);
procedure setMaxZoom(AValue: integer);
procedure setMinZoom(AValue: integer);
procedure setStartZoom(AValue: integer);
protected
{ Protected-Deklarationen }
property currentZoom: integer read FcurrentZoom write setCurrentZoom;
public
{ Public-Deklarationen }
constructor Create(AOwner: TComponent); override;
//###################################################################
//###################################################################
//
// This should get called automatically
//
//###################################################################
//###################################################################
procedure LMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: integer; MousePos: TPoint; var Handled: boolean);
published
property maxZoom: integer read FmaxZoom write setMaxZoom;
property minZoom: integer read FminZoom write setMinZoom;
property startZoom: integer read FStartZoom write setStartZoom;
property zoomSpeed: integer read FzoomSpeed write FzoomSpeed;
end;
{$ENDIF}
procedure Register;
implementation
{$IFnDEF MSWINDOWS}
procedure Register;
begin
end;
{$ELSE}
procedure Register;
begin
RegisterComponents('test', [TLZoomage]);
end;
{ TLZoomage }
//###################################################################
//###################################################################
//
// This should get called automatically
//
//###################################################################
//###################################################################
procedure TLZoomage.LMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: integer; MousePos: TPoint; var Handled: boolean);
var
xZoomPoint: double;
yZoomPoint: double;
begin
if (ssCtrl in Shift) then
begin
xZoomPoint := MousePos.x / self.Width;
yZoomPoint := MousePos.y / self.Height;
// der Benutzer möchte zoomen
currentZoom := currentZoom + Sign(WheelDelta) * scrollSpeed;
self.Left := round(self.Left + MousePos.x - (xZoomPoint * self.Width));
self.Top := round(self.Top + MousePos.y - (yZoomPoint * self.Height));
end;
Handled:=true;
end;
procedure TLZoomage.setCurrentZoom(AValue: integer);
var
ChildScaleFactor: double;
ParentScaleFactor: double;
begin
FcurrentZoom := AValue;
if (FcurrentZoom < minZoom) then
FcurrentZoom := minZoom;
if (FcurrentZoom > maxZoom) then
FcurrentZoom := maxZoom;
if Assigned(self.Picture) then
begin
self.Width := round(self.Picture.Width * FcurrentZoom / 100);
self.Height := round(self.Picture.Height * FcurrentZoom / 100);
if Assigned(self.Parent) then
begin
if (self.Width < self.Parent.Width) and (self.Height < self.Parent.Height) and
(self.Height <> 0) then
begin
ChildScaleFactor := self.Width / self.Height;
ParentScaleFactor := self.Parent.Width / self.Parent.Height;
// Parent ist breiter -> Höhe gibt die größe vor
if (ParentScaleFactor > ChildScaleFactor) then
begin
self.Height := self.Parent.Height;
self.Width := round(ChildScaleFactor * self.Parent.Height);
end
else
// Parent ist höher -> Breite gibt die Größe vor
begin
self.Width := self.Parent.Width;
self.Height := round(self.Parent.Width / ChildScaleFactor);
end;
end;
end;
end;
end;
procedure TLZoomage.setMaxZoom(AValue: integer);
begin
FmaxZoom := AValue;
currentZoom := currentZoom;
end;
procedure TLZoomage.setMinZoom(AValue: integer);
begin
FminZoom := AValue;
currentZoom := currentZoom;
end;
procedure TLZoomage.setStartZoom(AValue: integer);
begin
currentZoom := AValue;
FstartZoom := currentZoom;
end;
procedure TLZoomage.limitImgPos();
begin
if Assigned(self.Parent) then
begin
// limit the Scrolling
if self.Left > 0 then
self.Left := 0;
if self.Left < -(self.Width - self.Parent.Width) then
self.Left := -(self.Width - self.Parent.Width);
if self.Top > 0 then
self.Top := 0;
if self.Top < -(self.Height - self.Parent.Height) then
self.Top := -(self.Height - self.Parent.Height);
end;
end;
constructor TLZoomage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
maxZoom := 200;
minZoom := 10;
startZoom := 100;
FzoomSpeed := 10;
currentZoom := startZoom;
end;
{$ENDIF}
end.
Solution: The simplest solution was, to override the following procedure / functions out of TControl, thanks to "Remy Lebeau":
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;