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

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 SetViewXY negated if set in OnClick handler

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
cernisr Posted - Feb 21 2023 : 10:03:51
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
2   L A T E S T    R E P L I E S    (Newest First)
cernisr Posted - Feb 22 2023 : 03:02:17
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
xequte Posted - Feb 21 2023 : 22:53:57
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