How to change drop hint (Delphi application) when doing drag-drop from Explorer Shell to Virtual TreeView? How to change drop hint (Delphi application) when doing drag-drop from Explorer Shell to Virtual TreeView? shell shell

How to change drop hint (Delphi application) when doing drag-drop from Explorer Shell to Virtual TreeView?


Shortly:
use IDataObject.SetData with FormatEtc.cfFormat=RegisterClipboardFormat(CFSTR_DROPDESCRIPTION)and DROPDESCRIPTION structure as TStgMedium content.

Drag source should call IDragSourceHelper2.SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT) before IDragSourceHelper.InitializeFromBitmap or IDragSourceHelper.InitializeFromWindow. VirtualTreeView set this flag automatically when it is used as drag source.


First, register special clipboard format.

constructor TForm12.Create(AOwner: TComponent);begin  inherited;  FDragDescriptionFormat := RegisterClipboardFormat(PChar(CFSTR_DROPDESCRIPTION));end;

Next, create method to set hint for IDataObject:

procedure TForm12.SetDragHint(DataObject: IDataObject; const Value: string; Effect: Integer);var  FormatEtc: TFormatEtc;  Medium: TStgMedium;  Data: Pointer;  Descr: DROPDESCRIPTION;  s: WideString;begin  ZeroMemory(@Descr, SizeOf(DROPDESCRIPTION));  {Do not set Descr.&type to DROPIMAGE_INVALID - this value ignore any custom hint}  {use same image as dropeffect type}  Descr.&type := DROPIMAGE_LABEL;  case Effect of    DROPEFFECT_NONE:      Descr.&type := DROPIMAGE_NONE;    DROPEFFECT_COPY:      Descr.&type := DROPIMAGE_COPY;    DROPEFFECT_MOVE:      Descr.&type := DROPIMAGE_MOVE;    DROPEFFECT_LINK:      Descr.&type := DROPIMAGE_LINK;  end;  {format message for system}  if Length(Value) <= MAX_PATH then  begin    Move(Value[1], Descr.szMessage[0], Length(Value) * SizeOf(WideChar));    Descr.szInsert := '';  end  else  begin    s := Copy(Value, 1, MAX_PATH - 2) + '%1';    Move(s[1], Descr.szMessage[0], Length(s) * SizeOf(WideChar));    s := Copy(Value, MAX_PATH - 1, MAX_PATH);    Move(s[1], Descr.szInsert[0], Length(s) * SizeOf(WideChar));  end;  {prepare structures to set DROPDESCRIPTION data}   FormatEtc.cfFormat := FDragDescriptionFormat; {registered clipboard format}  FormatEtc.ptd := nil;  FormatEtc.dwAspect := DVASPECT_CONTENT;  FormatEtc.lindex := -1;  FormatEtc.tymed := TYMED_HGLOBAL;  ZeroMemory(@Medium, SizeOf(TStgMedium));  Medium.tymed := TYMED_HGLOBAL;  Medium.HGlobal := GlobalAlloc(GHND or GMEM_SHARE, SizeOf(DROPDESCRIPTION));  Data := GlobalLock(Medium.HGlobal);  Move(Descr, Data^, SizeOf(DROPDESCRIPTION));  GlobalUnlock(Medium.HGlobal);  DataObject.SetData(FormatEtc, Medium, True);end;

Last - use SetDragHint, for example - in VirtualTreeView.OnDragOver event:

procedure TForm12.vt1DragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; State: TDragState;  Pt: TPoint; Mode: TDropMode; var Effect: Integer; var Accept: Boolean);begin  Accept := True;  Effect := DROPEFFECT_LINK;  if State = dsDragMove then  begin    SetDragHint(vt1.DragManager.DataObject, Format('Point: (%d, %d)', [Pt.X, Pt.Y]), Effect);  end  else  begin    Accept := False;    Effect := DROPEFFECT_NONE;    SetDragHint(vt1.DragManager.DataObject, '', Effect);  end;end;

Result (drag file from Explorer to VirtualStringTree):

Screenshot