ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 SetViewXY negated if set in OnClick handler
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

cernisr

United Kingdom
2 Posts

Posted - Feb 21 2023 :  10:03:51  Show Profile  Reply
ImageEn 11.4.0; Delphi 11.2 with patch 1; Windows 11 22H2

I have a TIMageEnView where MouseInteractGeneral is set to [miScroll], and I use the OnClick handler to change the image being displayed. As it's a new image, I want to undo any panning the user may have done with the previous image, and reset the view position to 0,0.

In my OnClick handler, I load the new image and SetViewXY(0, 0). However, if the user has panned the image, the new image appears at the old pan position.

in imageenview.pas, TImageEnView.MouseUp undoes my SetViewXY with:

if (Button = mbLeft) and (miScroll in fMsInteractGeneral) and RequiresScrollBars() then
begin
// set "view", free by MouseCapture
SetViewXY(fHSVX1 - trunc((x - fMouseDownX) * fMouseScrollRate), fHSVY1 - trunc((y - fMouseDownY) * fMouseScrollRate));
RestoreCursor();
end

Test program (new Delphi VCL project, with a TImageEnView - you'll have to supply your own images)


unit PBTMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, hyiedefs, hyieutils, iexBitmaps,
iesettings, iexLayers, iexRulers, iexToolbars, iexUserInteractions, imageenio,
imageenproc, iexProcEffects, ieview, imageenview;

type
TForm1 = class(TForm)
ImageEnView1: TImageEnView;
procedure FormCreate(Sender: TObject);
procedure ImageEnView1Click(Sender: TObject);
procedure ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
MinMouseX: integer;
MinMouseY: integer;
MouseDownX: integer;
MouseDownY: integer;
CurMouseX: integer;
CurMouseY: integer;
CurrentImage: integer;
DblCLickLimitX: integer;
DblCLickLimitY: integer;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

const
IMAGE_1 = 'c:\temp\image1.jpg';
IMAGE_2 = 'c:\temp\image2.jpg';

procedure TForm1.FormCreate(Sender: TObject);
begin
ImageEnView1.MouseInteractGeneral := [miScroll];
ImageEnView1.Align := alClient;
ImageEnView1.OnClick := ImageEnView1Click;
ImageEnView1.OnMouseDown := ImageEnView1MouseDown;
ImageEnView1.OnMouseMove := ImageEnView1MouseMove;
ImageEnView1.IO.LoadFromFile(IMAGE_1);
CurrentImage := 1;

DblCLickLimitX :=
GetSystemMetricsforDPI(SM_CXDOUBLECLK, Screen.PixelsPerInch);
DblCLickLimitY :=
GetSystemMetricsforDPI(SM_CYDOUBLECLK, Screen.PixelsPerInch);
end;

procedure TForm1.ImageEnView1Click(Sender: TObject);
begin
// If the user scrolls the image, we get a Click event when they release the
// mouse button at the end of the scroll, so we want to suppress that. I assume
// that any mouse movement beyond the size of the double-click rectangle
// was a pan
if (Abs(CurMouseX - MouseDownX) > DblCLickLimitX)
or (Abs(CurMouseY - MouseDownY) > DblClickLimitY)
then exit;

if CurrentImage = 1 then begin
ImageEnView1.IO.LoadFromFile(IMAGE_2);
CurrentImage := 2;
end
else begin
ImageEnView1.IO.LoadFromFile(IMAGE_1);
CurrentImage := 1;
end;

ImageEnView1.SetViewXY(0, 0);
end;

procedure TForm1.ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbRight then begin
// Use the right mouse button to fip-flop between OnCLick and OnDblCLick
if Assigned(ImageEnView1.OnClick) then begin
ImageEnView1.OnDblClick := ImageEnView1.OnClick;
ImageEnView1.OnClick := nil;
end
else begin
ImageEnView1.OnClick := ImageEnView1.OnDblClick;
ImageEnView1.OnDblClick := nil;
end;
exit;
end;

MouseDownX := X;
MouseDownY := Y;
end;

procedure TForm1.ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
CurMouseX := X;
CurMouseY := Y;
end;

end.


The problem does not arise if I use an OnDblClick handler to change the image, but the loading of the new image needs to happen in an OnClick, not an OnDblClick.

I've been able to achieve the effect I want, albeit with some unnecessary view display that I need to work on, by creating a descendant of TIEUserInteraction, adding it to ImageEnView1.UserInteractions and using MouseUp in that to do another SetViewXY.

My questions are:

(1) Am I missing something, i.e. is there a better way of resetting a scrolled view in an OnClick Handler?
(2) If not, is it safe to derive descendants of TIEUserInteraction and add them to the UserInteractions property?

Thanks,
Ray

xequte

38715 Posts

Posted - Feb 21 2023 :  22:53:57  Show Profile  Reply
Hi Ray

Yes, unfortunately you are doing something that we did not anticipate. Resetting the position during the MouseDown/MouseUp window will clash with the miScroll interaction. If I was in your situation, I think I would just write my own panning code rather than fighting against the miScroll interaction.

That said, adding your own user interaction will allow you to move outside the MouseDown/MouseUp window, and I cannot see any issues in doing that.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

cernisr

United Kingdom
2 Posts

Posted - Feb 22 2023 :  03:02:17  Show Profile  Reply
Thanks Nigel. I think you're right, the better solution is to just handle the panning myself, but it's useful to know about UserInteractions for the future.

Ray
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: