Is it possible to Alpha Blend a VCL control on a TForm?

前端 未结 3 1506
北海茫月
北海茫月 2020-12-14 03:51

Is it possible to Alpha Blend or implement a similar effect for a VCL control on a TForm?

For example, consider the following screenshot where two TPanels are place

相关标签:
3条回答
  • 2020-12-14 04:30

    To implement a drag operation displaying the image of the control, you must create a TDragControlObject descendent and implement the GetDragImages method, from here you must ensure to add the csDisplayDragImage value to the ControlStyle property of the controls to drag.

    You can find a very good article about this topic here Implementing Professional Drag & Drop In VCL/CLX Applications

    0 讨论(0)
  • 2020-12-14 04:44

    You can do this in Delphi, too. The basic idea is to place the control into an autosized, borderles form with alpha blending enabled.

    According to the article you linked to, in the MouseDown event add the following lines:

      P := TWinControl(Sender).ClientToScreen(Point(0,0));
      frm := TForm.Create(nil);
      TWinControl(Sender).Parent := frm;
      frm.BorderStyle := bsNone;
      frm.AlphaBlend := true;
      frm.AlphaBlendValue := 128;
      frm.AutoSize := true;
      frm.Left := P.X;
      frm.Top := P.Y;
      frm.Position := poDesigned;
      frm.Show;
    

    In the MouseMove event set the Left and Top properties of the controls parent:

      GetCursorPos(newPos);
    
      Screen.Cursor := crSize;
      Parent.Left := Parent.Left - oldPos.X + newPos.X;
      Parent.Top := Parent.Top - oldPos.Y + newPos.Y;
      oldPos := newPos;
    

    and in the MouseUp event release the form, set the controls parent back to the original parent and translate the screen position to the new position relative to it:

    frm := TWinControl(Sender).Parent;
    P := Point(frm.Left, frm.Top);
    P := ScreenToClient(P);
    TWinControl(Sender).Parent := Self;
    TWinControl(Sender).Left := P.X;
    TWinControl(Sender).Top := P.Y;
    frm.Free;
    Screen.Cursor := crDefault;
    ReleaseCapture;
    inReposition := False;
    
    0 讨论(0)
  • 2020-12-14 04:45

    The VCL gives you the opportunity to specify a drag image list to be used during drag-and-drop, here's a quick example: enter image description here

    unit Unit1;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
    
    type
      TPanel = class(Vcl.ExtCtrls.TPanel)
      protected
        function GetDragImages: TDragImageList; override;
      end;
    
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        CheckBox1: TCheckBox;
        Edit1: TEdit;
        Label1: TLabel;
        Panel1: TPanel;
        Panel2: TPanel;
        Panel3: TPanel;
        procedure FormCreate(Sender: TObject);
        procedure FormDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
        procedure PanelStartDrag(Sender: TObject; var DragObject: TDragObject);
        procedure PanelEndDrag(Sender, Target: TObject; X, Y: Integer);
      private
        FDragImages: TDragImageList;
      public
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    { TPanel }
    
    function TPanel.GetDragImages: TDragImageList;
    begin
      Result := (Owner as TForm1).FDragImages;
    end;
    
    type
      TControlProc = reference to procedure(Control: TControl);
    
    procedure IterateControls(Control: TControl; Proc: TControlProc);
    var
      I: Integer;
    begin
      if Assigned(Control) then
        Proc(Control);
      if Control is TWinControl then
        for I := 0 to TWinControl(Control).ControlCount - 1 do
          IterateControls(TWinControl(Control).Controls[I], Proc);
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FDragImages := nil;
      // set display drag image style
      IterateControls(Self,
        procedure(Control: TControl)
        begin
          Control.ControlStyle := Control.ControlStyle + [csDisplayDragImage];
        end
      );
    end;
    
    procedure TForm1.FormDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
    begin
      Accept := Source is TPanel;
    end;
    
    procedure TForm1.PanelEndDrag(Sender, Target: TObject; X, Y: Integer);
    begin
      FreeAndNil(FDragImages);
    end;
    
    procedure TForm1.PanelStartDrag(Sender: TObject; var DragObject: TDragObject);
    var
      Image: TBitmap;
    begin
      if not (Sender is TPanel) then
        Exit;
    
      Image := TBitmap.Create;
      try
        Image.PixelFormat := pf32bit;
        Image.Width := TControl(Sender).Width;
        Image.Height := TControl(Sender).Height;
        TPanel(Sender).PaintTo(Image.Canvas, 0, 0);
    
        FDragImages := TDragImageList.Create(nil);
        FDragImages.Width := Image.Width;
        FDragImages.Height := Image.Height;
        FDragImages.SetDragImage(FDragImages.Add(Image, nil), 0, 0);
        FDragImages.ShowDragImage;
      except
        Image.Free;
        FreeAndNil(FDragImages);
        raise;
      end;
    end;
    
    end.
    
    0 讨论(0)
提交回复
热议问题