Board index » delphi » Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas

Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas

Dear All,

I have a TPaintBox control on a TPanel and use double buffers to animate.

When I try to click-hold-and-pan the image with the following code, I get a
what appears to be a mouse echo.    Meaning that the image draws first in
one pace,  then in another,  then back to the first with an offset,  then
back to the other with an offset,  then to the first with a new offset,
etc...

By not refreshing between draws, I can clearly see two paths of images
following my mouse.  The faster I move the mouse the larger the difference
between the two paths.

Any ideas as to what is wrong?

-Jim

    Note: WP and PenStart are of TwXYpoint type with x,y as doubles.
              PenStart and the boolean Panning are set in MyMouseDown

MyMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
 WP: TwXYpoint;
begin
    if Panning then begin
      { convert mouse click to world point }
      WP := ImageXYToWorldXY(x,y);

      { Translate wvp by the distance mouse has moved from the last mouse
action }
      WorldViewPort.left := WorldViewPort.left + (PanStart.x - wp.x);
      WorldViewPort.top := WorldViewPort.top + (PanStart.y - wp.y);
      WorldViewPort.right := WorldViewPort.right + (PanStart.x - wp.x);
      WorldViewPort.bottom := WorldViewPort.bottom + (PanStart.y - wp.y);

      { use new WVP to build a new BkGroundBmp }
      GrafixEngine.Render (BkGroundBmp.canvas, theta, ImageViewPort,
WorldViewPort, false);

      { clear animation layer }
     AnimaiBmp.canvas.FillRect(rect(0, 0, AnimaiBmp.Width,
AnimaiBmp.Height));

     { draw view background }
     AnimaiBmp.canvas.Draw(0,0,BkGroundBmp);

     BitBlt(PaintBox.Canvas.Handle,0,0,PaintBox.Width, PaintBox.Height,
AnimaiBmp.Canvas.Handle,0,0,SRCCOPY);

     PanStart := wp;
   end;
end;

 

Re:Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas


I'm just curious, but is GrafixEngine something you wrote or is it a 3rd
party component/class?

--
Paul Nicholls (Delphi 5)
"The plastic veneer of civilized man is easily melted in the heat of the
moment" - Paul Nicholls

 Home Page: www.southcom.com.au/~phantom
       < IF YOU WANT TO EARN MONEY WHILE YOU SURF ON THE NET GO HERE: >
       < http://www.alladvantage.com/go.asp?refid=BEM-274 >

Re:Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas


It's something I wrote.

Here is a simple 100 liner, one form, one button, one paint box, app that
shows the problem.

Thanks for the reply.  Hope you spot something I missed.

- Jim Johnson - "People are like flowers, they bloom at different times, and
some of them are plastic."

unit Unit1;

interface

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

type

  TiXYPoint = RECORD
    X, Y:  integer;
  END;
  PiXYPoint = ^TiXYPoint;

  TwXYPoint = RECORD
    X, Y:  DOUBLE;
  END;
  PwXYPoint = ^TwXYPoint;

  TLimit = record
   left: Double;
   top: Double;              {ltrb same as trect}
    right: Double;
    bottom: Double;
  end;

  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift:
TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    procedure LoadPolygon;
    procedure RenderPolygon;

    function WorldPointToImagePoint(const wp: TwXYPoint): TiXYPoint;
    function ImageXYToWorldXY(const x,y: integer): TwXYPoint;
  end;

var
  Form1: TForm1;
  BkGroundBmp: TBitMap;
  VertexList: Tlist;
  WVP: TLimit;
  IVP: TRect;
  BorderWidth: integer;
  PanStart: TwXYPoint;
  Panning: boolean;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  RenderPolygon;
  BitBlt(PaintBox1.canvas.handle,0,0,PaintBox1.Width,PaintBox1.Height,
BkGroundBmp.Canvas.Handle,0,0,SRCCOPY);
end;

function TForm1.WorldPointToImagePoint(const wp: TwXYPoint): TiXYPoint;
begin
  result.X := Round((((WP.X - WVP.Left) / (WVP.Right- WVP.Left)) *
(IVP.right - IVP.left)) + IVP.left);
  result.Y := Round((((WP.Y - WVP.top) / (WVP.Bottom - WVP.top)) *
(IVP.bottom - IVP.top)) + IVP.top);
end;

function TForm1.ImageXYToWorldXY(const x,y: integer): TwXYPoint;
begin
  result.X := (((X - IVP.Left) / (IVP.Right- IVP.Left)) * (WVP.right -
WVP.left)) + WVP.left;
  result.Y := (((Y - IVP.top) /(IVP.Bottom - IVP.top)) * (WVP.bottom -
WVP.top)) + WVP.top;
end;

procedure TForm1.RenderPolygon;
var
 i, j: integer;
  sp, ip: TiXYPoint;
  wp: TwXYPoint;
begin
  BkGroundBmp.canvas.Pen.Color := clBlue;
  i := 0;
  wp.x := PwXYPoint(VertexList[i]).x;
  wp.y := PwXYPoint(VertexList[i]).y;
  sp := WorldPointToImagePoint(wp);
  BkGroundBmp.Canvas.Moveto( sp.x, sp.y);
  for i := 1 to VertexList.count-1  do begin
    wp.x := PwXYPoint(VertexList[i]).x;
    wp.y := PwXYPoint(VertexList[i]).y;
    ip := WorldPointToImagePoint(wp);
    BkGroundBmp.Canvas.lineto( ip.x, ip.y);
  end;
  BkGroundBmp.Canvas.lineto( sp.x, sp.y);
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  BkGroundBmp := TBitMap.Create;
  BkGroundBmp.Width  := PaintBox1.ClientWidth;
  BkGroundBmp.Height := PaintBox1.ClientHeight;
  BkGroundBmp.PixelFormat := pf24bit;
  BkGroundBmp.Canvas.Brush.Style := bsSolid;
  BkGroundBmp.canvas.brush.color := 8454016;    {LiteGreen}
 BkGroundBmp.canvas.FillRect(rect(0, 0, BkGroundBmp.Width,
BkGroundBmp.Height));

  VertexList := Tlist.create;

  WVP.left := 0.0;
  WVP.top := 10.0;
  WVP.right := 10.0;
  WVP.bottom := 0.0;

  BorderWidth := 10;
  IVP.top := BorderWidth;
  IVP.Left := BorderWidth;
  IVP.Bottom := PaintBox1.ClientHeight - BorderWidth;
  IVP.Right := PaintBox1.ClientWidth  - BorderWidth;

  LoadPolygon;
  Panning := false;
end;

procedure AddPoint(const x,y: double);
var
 nuPt: PwXYPoint;
begin
 New(nuPT);
 nuPT^.x := x;
 nuPT^.y := y;
  VertexList.Add(nupt);
end;

procedure TForm1.LoadPolygon;
begin
 Addpoint( 1.34607676470588, 1.688504);
 Addpoint( 1.82577638235294, 1.482051);
 Addpoint( 2.40263035294118, 1.91317344117647);
 Addpoint( 2.19617735294118, 2.66611967647059);
 Addpoint( 1.70433344117647, 2.74505758823529);
 Addpoint( 1.38858179411765, 2.39894520588235);
 Addpoint( 0.574914088235294, 2.16213147058824);
 Addpoint( 1.26713885294118, 1.76136976470588);
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
  PanStart := ImageXYToWorldXY( X, Y);
 Panning := true;
end;

procedure Tform1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
 Panning := false;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
 WP: TwXYpoint;
begin
 if Panning then begin
      {convert mouse click to world point}
      WP := ImageXYToWorldXY(x,y);

      {Translate wvp by the distance mouse has moved from the last}
mouse action
      WVP.left := WVP.left + (PanStart.x - WP.x);
      WVP.top := WVP.top + (PanStart.y - WP.y);
      WVP.right := WVP.right + (PanStart.x - WP.x);
      WVP.bottom := WVP.bottom + (PanStart.y - WP.y);

      {clear            comment this next line out to better see trails}
{     BkGroundBmp.canvas.FillRect(rect(0, 0, BkGroundBmp.Width,
BkGroundBmp.Height));  }

      { use new WVP to build a new image}
      RenderPolygon;

      BitBlt(PaintBox1.canvas.handle,0,0,PaintBox1.Width,PaintBox1.Height,
BkGroundBmp.Canvas.Handle,0,0,SRCCOPY);

      PanStart := WP;
   end;
end;

end.

Quote
Paul Nicholls <phan...@southcom.com.au> wrote in message

news:3a8c9e7c$1_2@dnews...
Quote
> I'm just curious, but is GrafixEngine something you wrote or is it a 3rd
> party component/class?

> --
> Paul Nicholls (Delphi 5)
> "The plastic veneer of civilized man is easily melted in the heat of the
> moment" - Paul Nicholls

>  Home Page: www.southcom.com.au/~phantom
>        < IF YOU WANT TO EARN MONEY WHILE YOU SURF ON THE NET GO HERE: >
>        < http://www.alladvantage.com/go.asp?refid=BEM-274 >

Re:Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas


It's something I wrote.

Here is a simple 100 liner, one form, one button, one paint box, app that
shows the problem.

Thanks for the reply.  Hope you spot something I missed.

- Jim Johnson - "People are like flowers, they bloom at different times, and
some of them are plastic."

unit Unit1;

interface

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

type

  TiXYPoint = RECORD
    X, Y:  integer;
  END;
  PiXYPoint = ^TiXYPoint;

  TwXYPoint = RECORD
    X, Y:  DOUBLE;
  END;
  PwXYPoint = ^TwXYPoint;

  TLimit = record
   left: Double;
   top: Double;              {ltrb same as trect}
    right: Double;
    bottom: Double;
  end;

  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift:
TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    procedure LoadPolygon;
    procedure RenderPolygon;

    function WorldPointToImagePoint(const wp: TwXYPoint): TiXYPoint;
    function ImageXYToWorldXY(const x,y: integer): TwXYPoint;
  end;

var
  Form1: TForm1;
  BkGroundBmp: TBitMap;
  VertexList: Tlist;
  WVP: TLimit;
  IVP: TRect;
  BorderWidth: integer;
  PanStart: TwXYPoint;
  Panning: boolean;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  RenderPolygon;
  BitBlt(PaintBox1.canvas.handle,0,0,PaintBox1.Width,PaintBox1.Height,
BkGroundBmp.Canvas.Handle,0,0,SRCCOPY);
end;

function TForm1.WorldPointToImagePoint(const wp: TwXYPoint): TiXYPoint;
begin
  result.X := Round((((WP.X - WVP.Left) / (WVP.Right- WVP.Left)) *
(IVP.right - IVP.left)) + IVP.left);
  result.Y := Round((((WP.Y - WVP.top) / (WVP.Bottom - WVP.top)) *
(IVP.bottom - IVP.top)) + IVP.top);
end;

function TForm1.ImageXYToWorldXY(const x,y: integer): TwXYPoint;
begin
  result.X := (((X - IVP.Left) / (IVP.Right- IVP.Left)) * (WVP.right -
WVP.left)) + WVP.left;
  result.Y := (((Y - IVP.top) /(IVP.Bottom - IVP.top)) * (WVP.bottom -
WVP.top)) + WVP.top;
end;

procedure TForm1.RenderPolygon;
var
 i, j: integer;
  sp, ip: TiXYPoint;
  wp: TwXYPoint;
begin
  BkGroundBmp.canvas.Pen.Color := clBlue;
  i := 0;
  wp.x := PwXYPoint(VertexList[i]).x;
  wp.y := PwXYPoint(VertexList[i]).y;
  sp := WorldPointToImagePoint(wp);
  BkGroundBmp.Canvas.Moveto( sp.x, sp.y);
  for i := 1 to VertexList.count-1  do begin
    wp.x := PwXYPoint(VertexList[i]).x;
    wp.y := PwXYPoint(VertexList[i]).y;
    ip := WorldPointToImagePoint(wp);
    BkGroundBmp.Canvas.lineto( ip.x, ip.y);
  end;
  BkGroundBmp.Canvas.lineto( sp.x, sp.y);
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  BkGroundBmp := TBitMap.Create;
  BkGroundBmp.Width  := PaintBox1.ClientWidth;
  BkGroundBmp.Height := PaintBox1.ClientHeight;
  BkGroundBmp.PixelFormat := pf24bit;
  BkGroundBmp.Canvas.Brush.Style := bsSolid;
  BkGroundBmp.canvas.brush.color := 8454016;    {LiteGreen}
 BkGroundBmp.canvas.FillRect(rect(0, 0, BkGroundBmp.Width,
BkGroundBmp.Height));

  VertexList := Tlist.create;

  WVP.left := 0.0;
  WVP.top := 10.0;
  WVP.right := 10.0;
  WVP.bottom := 0.0;

  BorderWidth := 10;
  IVP.top := BorderWidth;
  IVP.Left := BorderWidth;
  IVP.Bottom := PaintBox1.ClientHeight - BorderWidth;
  IVP.Right := PaintBox1.ClientWidth  - BorderWidth;

  LoadPolygon;
  Panning := false;
end;

procedure AddPoint(const x,y: double);
var
 nuPt: PwXYPoint;
begin
 New(nuPT);
 nuPT^.x := x;
 nuPT^.y := y;
  VertexList.Add(nupt);
end;

procedure TForm1.LoadPolygon;
begin
 Addpoint( 1.34607676470588, 1.688504);
 Addpoint( 1.82577638235294, 1.482051);
 Addpoint( 2.40263035294118, 1.91317344117647);
 Addpoint( 2.19617735294118, 2.66611967647059);
 Addpoint( 1.70433344117647, 2.74505758823529);
 Addpoint( 1.38858179411765, 2.39894520588235);
 Addpoint( 0.574914088235294, 2.16213147058824);
 Addpoint( 1.26713885294118, 1.76136976470588);
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
  PanStart := ImageXYToWorldXY( X, Y);
 Panning := true;
end;

procedure Tform1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
 Panning := false;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
 WP: TwXYpoint;
begin
 if Panning then begin
      // convert mouse click to world point
      WP := ImageXYToWorldXY(x,y);

      file://Translate wvp by the distance mouse has moved from the last
mouse action
      WVP.left := WVP.left + (PanStart.x - WP.x);
      WVP.top := WVP.top + (PanStart.y - WP.y);
      WVP.right := WVP.right + (PanStart.x - WP.x);
      WVP.bottom := WVP.bottom + (PanStart.y - WP.y);

      // clear animation layer       comment this next line out to see
trails
//     BkGroundBmp.canvas.FillRect(rect(0, 0, BkGroundBmp.Width,
BkGroundBmp.Height));

      // use new WVP to build a new image
      RenderPolygon;

      BitBlt(PaintBox1.canvas.handle,0,0,PaintBox1.Width,PaintBox1.Height,
BkGroundBmp.Canvas.Handle,0,0,SRCCOPY);

      PanStart := WP;
   end;
end;

end.

Quote
Paul Nicholls <phan...@southcom.com.au> wrote in message

news:3a8c9e7c$1_2@dnews...
Quote
> I'm just curious, but is GrafixEngine something you wrote or is it a 3rd
> party component/class?

> --
> Paul Nicholls (Delphi 5)
> "The plastic veneer of civilized man is easily melted in the heat of the
> moment" - Paul Nicholls

>  Home Page: www.southcom.com.au/~phantom
>        < IF YOU WANT TO EARN MONEY WHILE YOU SURF ON THE NET GO HERE: >
>        < http://www.alladvantage.com/go.asp?refid=BEM-274 >

Re:Dancing Mouse A.K.A. Mysterious Mouse Echo on TPaintBox while BitBlting to canvas


Quote
In article <96ia3h$g...@bornews.inprise.com>, Jim Johnson wrote:
> PanStart := WP;

Try to leave out that line in MouseMove, leaving PanStart at the
MouseDown value. That works for me, I even remember, I once knew why...

Renate

Other Threads