Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 295
  • Last Modified:

syncing mouse pointer & scrollbar movement

Hello,

I have an image in a scrollbox and I have code in place to move the image if the user "grabs" it.  My porblem is that I want to syncrhonize the mouse pointer and the movement of my image [much like adobe acrobat reader] so that as I move the image the mouse pointer remains in the same position as it started.  I've tried to speed up the image and just about had it but then the image got very jumpy because I was making it move to fast.
0
wilee
Asked:
wilee
  • 4
  • 3
1 Solution
 
sperlingCommented:
Not entirely sure what you're asking, but if I understand your question, this unit does what you wan't.

-------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    FOffsetX,
    FOffsetY  : INTEGER;
    FMoving   : BOOLEAN;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button=mbLeft then begin
    FOffsetX := X;
    FOffsetY := Y;
    FMoving := TRUE;
  end;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  pt : TPoint;
begin
  if FMoving then begin
    pt := Image1.ClientToScreen(Point(x, y));
    pt := ScreenToClient(pt);
    Image1.SetBounds(pt.X - FOffsetX, pt.Y-FOffsetY, Image1.Width, Image1.Height);
  end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FMoving and (Button = mbLeft) then begin
    FMoving := FALSE;
  end;
end;

end.
-------------


Regards,

Erik.
0
 
wileeAuthor Commented:
It works great except the image flickers terribly.  And I've tried to make it smaller and it still flickers.  If there is a way to get rid of the flicker this will work splendidly.  But to have the image flciker is totally unacceptable.  And I'm running a cyrus 686 200 Mhz machine so if this can't redraw it my user machines sure won't.
Just fix the flicker and I'll give you an A Thanks.
wilee
0
 
wileeAuthor Commented:
To whom it may concern,

I have figured the problem out myself.  I simply took the code I have and inside my mouse down event handler I just set the X & Y values for the mouse to my origin point.

Thanks for the help and I'd be glad to give you 50 points cause you were on the right track just e-mail me back and we can discuss it.

wilee
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
sperlingCommented:
A "standard" method to fix flickering is to handle the WM_ERASEBKGND message...

In protected part of an TImage ancestor:
  procedure WMEraseBkgnd(var Message: TWMEraseBkgnd);
    message WM_ERASEBKGND;

Implemented as:

procedure TNoFlickerImage.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  Message.Result := 1;
end;


This'll probably fix the flickering. Or had you already fixed it?


Regards,

Erik.
0
 
wileeAuthor Commented:
Could you explain a little bit behind what each line of code does in the first section.  Actually what the 3 lines of code in the on mouse move event do?  I fixed mine by actually manipulating the scrollbars in a scrollbox to move my image.  I had to do some intricate coding to actually revers the scroll bars.  When you move a scroll bar down the image moves up.  Then I had to reset the X & Y coordinates of the mouse in the onmousemove event handler.  But yours is much more efficient and simple.  But I'd like to understand how it works.  Thanks for your help.
0
 
sperlingCommented:
All visible controls has a ClientToScreen and ScreenToClient method. These converts any TPoint between the coordinate system of the control and the coordinate system of the entire screen.

pt := Image1.ClientToScreen(Point(x, y));

Convert X and Y, which are relative to the upper left corner of Image1, to the coordinate system of the screen.

E.g. if Form1.Left = 100 and Image1.Left = 50:

X = 20 in Image1's coordinate system -> X=100+50+20 = 170 in screens coordinate system.

pt := ScreenToClient(pt);  

This converts the screen x and y back to the form's coordinate system. The result of these two lines is the X and Y coordinate passed to the event, but relative to the forms upper left corner. The X from before would now be 70.

Image1.SetBounds(pt.X - FOffsetX, pt.Y-FOffsetY, Image1.Width, Image1.Height);

The offset values are simply the position of the mouse pointer relative to the images top left corner. The X (which is now relative to the Forms left edge) is reduced by the amount of pixels from the images left edge to the initial position of the mouse on the image, giving the new position for the images left edge, relative to the form's left edge.

Setting Left first, and Top afterwards, requires the Image to redraw twice.

SetBounds sets left, top, width and height all in once. This means that the Image won't have to redraw after each of these values are changed.


Regards,

Erik.
0
 
wileeAuthor Commented:
Thanks for all your help.  I'm using your solution instead of mine just cause like I said it is easier to understand.

Jeff
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now