Canvas/Bitmap scrolling question
I'm trying to make a small game based on the canvas in Delphi. Basically, I'd like to make a fairly large bitmap ( 3000x3000, for example ), then load it into the canvas, and being able to sc开发者_运维技巧roll right/left/up/down just like an ordinary image viewer, however I can't seem to find what I'm looking for. Any ideas?
Load the image to an off-screen TBitmap
object. Then, OnPaint
, or whenever is suitable in your particular application, use BitBlt
or Canvas.Draw
to draw a rectangular subimage of the TBitmap
onto the canvas. The subpart should start at (X, Y)
on the TBitmap
and have a width and height equal to ClientWidth
and ClientHeight
of the form, respectively.
Now, respond to keyboard events. Write a FormKeyDown
event handler, and listen to Key = VK_LEFT
, Key = VK_RIGHT
, Key = VK_UP
, and Key = VK_DOWN
(use a case
statement). When you detect such a key being pressed, increase/decrease X
or Y
, as appropriate, and paint the scene again using this starting point.
You can also respond to the MouseDown
, MouseMove
, and MouseUp
events to scroll using the mouse. Either you can use the middle one only (MouseMove
): You can check if the cursor is near an edge of the form, and if so, scroll in this direction smoothly (using a TTimer
, for instance). Alternatively, you can set a FMouseDown
flag to true
in MouseDown
, and reset it to false
in MouseUp
. Then, in MouseMove
, scroll the bitmap by a delta X-XOld
in the x direction if FMouseDown
is true
, and a delta Y-YOld
in the y direction. (Here, X
and Y
are parameters of the MouseMove
event handler; (X, Y)
is the current position of the cursor.) The MouseMove
procedure should end with
XOld := X;
YOld := Y;
no matter if FMouseDown
is on or off.
I had the same problem. My Bitmap is about 5000x5000 pixel, loaded into an Timage of 500x500 pixels.
I wrote a code to move the bitmap arround in the Timage, and it cant go out of the "borders"
AlteMausPos is declared in Form1 var at the beginning. Kerzenbitmap is your bitmap that contains the 5000x5000 picture. MausPosDifferenz contains the absolut amount of pixels(x,y) you have moved your mouse while mousekey down.
Then it checks if everything is in Range of the bitmap before copying it with CopyRect.
It took some time for my brain to find out that the best way to copy the rect ist to use the absolut changed mouseposition.
procedure Form1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var picLimits: Tpoint;
begin
AlteMausPos.X := X;
AlteMausPos.Y := Y;
end;
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var SourceRect, DestRect: TRect;
begin
var tempBMP:= Tbitmap.Create;
MausPosDifferenz.X := MausPosDifferenz.X+ (AlteMausPos.X- X);
MausPosDifferenz.Y := MausPosDifferenz.Y+ (AlteMausPos.Y- Y);
if MausPosDifferenz.X >= Kerzenbitmap.Width- Image1.Width then MausPosDifferenz.X := Kerzenbitmap.Width-Image1.Width;
if MausPosDifferenz.X < 0 then MausPosDifferenz.X:=0;
if MausPosDifferenz.Y >= Kerzenbitmap.Height-Image1.Height then MausPosDifferenz.Y := Kerzenbitmap.Height-Image1.Height;
if MausPosDifferenz.Y < 0 then MausPosDifferenz.Y:=0;
SourceRect:= Rect( MausPosDifferenz.X, MausPosDifferenz.Y, Image1.Width+ MausPosDifferenz.X, Image1.Height+ MausPosDifferenz.Y);
DestRect:= Rect( 0,0, Image1.Width, Image1.Height);
tempBMP.Assign(Kerzenbitmap);
TempBMP.Canvas.CopyRect(DestRect, Kerzenbitmap.Canvas, SourceRect);
Image1.Picture.Assign(tempBMP);
tempBMP.Free;
end;
精彩评论