Image 如何在Delphi中从合成图像创建pan

Image 如何在Delphi中从合成图像创建pan,image,delphi,delphi-2010,pan,Image,Delphi,Delphi 2010,Pan,我是一个新的德尔福图形方法,我在创造一个呆板的。。。视口,这就是我在为一个项目做时如何称呼它的。很抱歉,我不能为它提供任何代码,但我停留在逻辑部分,搜索谷歌指向我一些OnPaint,Draw方法。但这些并不是我想要实现的,因为我有,例如: 锚定到客户端顶部/底部/右侧和左侧的1600x1000背景图像 多个TImage元素放置在集合x/y坐标处 一个类似于HTML中地图元素的“热点”,我可以在其中设置可点击区域(对于我在步骤2中放置的图像) 不需要缩放 最重要的是,当背景被拖动时,那些放在背景上

我是一个新的德尔福图形方法,我在创造一个呆板的。。。视口,这就是我在为一个项目做时如何称呼它的。很抱歉,我不能为它提供任何代码,但我停留在逻辑部分,搜索谷歌指向我一些OnPaint,Draw方法。但这些并不是我想要实现的,因为我有,例如:

  • 锚定到客户端顶部/底部/右侧和左侧的1600x1000背景图像
  • 多个TImage元素放置在集合x/y坐标处
  • 一个类似于HTML中地图元素的“热点”,我可以在其中设置可点击区域(对于我在步骤2中放置的图像)
  • 不需要缩放
  • 最重要的是,当背景被拖动时,那些放在背景上的图片也需要被拖动
  • 我的逻辑(在HTML/jQuery中)是创建一个#viewportBinder(这是我正在拖动的div,透明的bg),然后在其中创建另一个名为#viewtown(1600x1000,背景)的div,其中包含放置在CSS中设置坐标处的div(那些时间)

    因此,当我拖动viewportBinder时,jQuery会在#视口上设置新的x/y。隐含地说,#视口中的div(TImages)正在移动,因为父对象是相对定位的

    有人有过这种项目的经验吗?有代码片段吗

    更具体地说,我将向您提供我的html示例,说明我完成了什么,以及我想将什么移植到Delphi代码中:


    抱歉,如果我不够清楚,我没有起点,因为我在delphi中根本没有这方面的经验。(使用RAD Studio 2010)

    这是一个非常简短的示例,说明如何以简单的方式实现它

    您可以使用一个画框进行绘制,一个背景图像,一个包含信息和透明图像的记录数组

    画布可以在偏移/缩放/旋转中操作。 移动和命中检测将在mousedown和mousemove中发生

    它并不完整,但可能会给你一个如何完成的想法

    [delphi]
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls,PNGImage, StdCtrls;
    
    type
      TBuilding=Record   // record for building informations
        Pos:TPoint;
        PNGImage:TPngImage;
        // what ever needed
      End;
    
      TBuildingArray=Array of TBuilding; // array of buildings
    
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
        procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
          Y: Integer);
        procedure Button1Click(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private-Deklarationen }
        FXoffs,FYOffs,FZoom:Double; // offset and zoom for painting
        FMouseDownPoint:TPoint;
        FBackGroundPNG:TPNGImage;
        FBuildingArray:TBuildingArray;
        procedure Check4Hit(X, Y: Integer);
      public
        { Public-Deklarationen }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    uses Math;
    {$R *.dfm}
    
    
    Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);
    var
        form : tagXFORM;
        Winkel:Double;
    begin
          Winkel := DegToRad(Angle);
          SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
          SetMapMode(ACanvas.Handle,MM_ANISOTROPIC);
          form.eM11 := Zoom * cos( Winkel);
          form.eM12 := Zoom *Sin( Winkel)  ;
          form.eM21 := Zoom * (-sin( Winkel));
          form.eM22 := Zoom * cos( Winkel) ;
          form.eDx := CenterpointX;
          form.eDy := CenterpointY;
          SetWorldTransform(ACanvas.Handle,form);
    end;
    
    Procedure ResetCanvas(ACanvas:TCanvas);
    begin
       SetCanvasZoomAndRotation(ACanvas , 1, 0, 0,0);
    end;
    
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
     Path:String;
     i:Integer;
    begin
       FZoom := 1;
       DoubleBuffered := true;
       Path := ExtractFilePath(Paramstr(0));
       FBackGroundPNG:=TPNGImage.Create;
       FBackGroundPNG.LoadFromFile(Path + 'infect.png');
       SetLength(FBuildingArray,3);
       for I := 0 to High(FBuildingArray)  do
          begin
             FBuildingArray[i].PNGImage := TPngImage.Create;
             FBuildingArray[i].PNGImage.LoadFromFile(Path + Format('B%d.png',[i]));
             FBuildingArray[i].Pos.X := I * 300;
             FBuildingArray[i].Pos.Y := Random(1000);
          end;
    
    end;
    procedure TForm1.FormDestroy(Sender: TObject);
    var
     i:Integer;
    begin
       for I := 0 to High(FBuildingArray)  do
          begin
             FBuildingArray[i].PNGImage.Free;
          end;
       FBackGroundPNG.Free;
    end;
    
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if FZoom=0.5 then FZoom := 1 else FZoom := 0.5;
      PaintBox1.Invalidate;
    end;
    
    procedure TForm1.Check4Hit(X,Y:Integer);
    var
     i,Index:Integer;
     R:TRect;
     P:TPoint;
    begin
       index := -1;
       for I := 0 to High(FBuildingArray)  do
          begin
             R := Rect(FBuildingArray[i].Pos.X,FBuildingArray[i].Pos.Y
                        ,FBuildingArray[i].Pos.X + FBuildingArray[i].PNGImage.Width
                        ,FBuildingArray[i].Pos.Y + FBuildingArray[i].PNGImage.Height);
             P := Point(Round((x - FXOffs)/FZoom) ,Round((y - FYOffs)/FZoom));
             if PtInRect(R,P) then Index := i;
          end;
       if index > -1 then
          begin
            Caption := Format('Last hit %d',[index]);
          end
       else Caption := 'No Hit';
    end;
    
    procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
       Check4Hit(X,Y);
       FMouseDownPoint.X := X;
       FMouseDownPoint.Y := Y;
    end;
    
    procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
       if ssLeft in Shift then
          begin
             FXoffs := -( FMouseDownPoint.X - X) ;
             FYoffs := -( FMouseDownPoint.Y - Y) ;
             if FXoffs>0 then FXoffs := 0;
             if FYoffs>0 then FYoffs := 0;
             PaintBox1.Invalidate;
          end;
    end;
    
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    var
     i:Integer;
    begin
       SetCanvasZoomAndRotation(PaintBox1.Canvas,FZoom,0,FXoffs,FYOffs);
       PaintBox1.Canvas.Draw(0,0,FBackGroundPNG);
       for I := 0 to High(FBuildingArray)  do
          begin
             PaintBox1.Canvas.Draw(FBuildingArray[i].Pos.X,FBuildingArray[i].Pos.Y,FBuildingArray[i].PNGImage);
          end;
    end;
    
    end.
    
    [/delphi]
    

    对不起,但在过去的几年里,我和拉扎勒斯而不是德尔福一起工作。但这篇文章将提供信息: 关于相对坐标,没什么好说的——很简单。 关于拖动:很久以前,在一个遥远的星系里。。这有点像:

    // To start dragging
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    // To stop dragging
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
    // To perform dragging
    procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
    

    你的问题是根据地形拖动建筑物吗?地形是不可调整大小的,它只有1600x1000,所以我需要在客户端(可能小于1600x1000)隐式地使其可拖动,客户端的最大约束是1600x1000,我需要terain(后台)在客户端窗体周围可拖动。不,没什么需要的。我会试试看我能做些什么。请继续回答问题。现在非常感谢,我会接受答案,只要我看到这个想法变得有价值(可能在一个小时左右),如果有人在拖动时背景(偏移量)重置为0,0有问题,请遵循以下步骤:declar a tPoint:tPoint;在{public}节下,然后在MouseDown事件集tPoint.x:=Trunc(FXoffs);和tPoint.y:=Trunc(fyoff);因为我们需要从一个doulbe中得到int。然后在MouseMove事件中,为各自的公式添加tempx和tempy。例如:FXoffs:=-(FMouseDownPoint.X-X)+tempx;和fyoff:=-(FMouseDownPoint.Y-Y)+tempy;这样程序就知道他上次在哪里停止了这个拖拽。问候。是的,TrpToBox已经把这些事件称为OnMouSurt/OnMouSeMeFor,但我将考虑Bunmie的答案,因为它不是那种低级编程。我的意思是,当Embarcadero已经在标准库中实现了“最佳”方法来完成类似的任务时,为什么还要做所有的艰苦工作呢。谢谢你抽出时间。