Author |
Topic |
|
cernisr
United Kingdom
2 Posts |
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 |
|
xequte
38715 Posts |
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
|
|
|
cernisr
United Kingdom
2 Posts |
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 |
|
|
|
Topic |
|
|
|