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
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
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;
The VCL gives you the opportunity to specify a drag image list to be used during drag-and-drop, here's a quick example:
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.