If you want to implement the copy/paste yourself, the mechanism is almost identical to drag and drop. The drag and drop code that you have will create an IDataObject
. To copy, instead of calling DoDragDrop
to initiate a drag, simply call OleSetClipboard
passing the IDataObject
. And for pasting you call OleGetClipboard
to get the IDataObject
from the clipboard. And then you simply use the exact same code as for a drop operation to decode the IDataObject
. That's all there is to it.
There is another way to do it, probably a better approach in my view. And that is to use IContextMenu
to do the work. And example of this can be found in the TurboPower tpShellShock project. Have a look for ShellMenuExecute
in the StShlCtl
unit. So long as the DevExpress component is using the shell interfaces, i.e. IShellFolder
, then you will be able to use that same approach. The advantage of this shell based approach is that you are getting the shell to do the work. If a copy dialog needs to be shown, then the shell will do so. This will give you the most integrated user experience.
This code looks like this:
procedure ShellMenuExecute(
const Sender : TObject; const Folder : IShellFolder;
var Pidl : PItemIDList; const Count : Integer;
const AHandle : THandle; ClipboardAction : TStMenuAction);
var
CM : IContextMenu;
CI : TCmInvokeCommandInfo;
begin
if Folder <> nil then begin
if (Folder.GetUIObjectOf(AHandle, Count, Pidl,
IID_IContextMenu, nil, Pointer(CM)) = NOERROR)
then begin
ZeroMemory(@CI, SizeOf(CI));
CI.cbSize := SizeOf(TCmInvokeCommandInfo);
CI.hwnd := AHandle;
case ClipboardAction of
caCut : CI.lpVerb := 'cut';
caCopy : CI.lpVerb := 'copy';
caPaste : CI.lpVerb := 'paste';
caProperties : CI.lpVerb := 'properties';
end;
CM.InvokeCommand(CI);
CM := nil;
end;
end;
end;
I think you should be able to use this code pretty much as is. I would point out that the handle parameter is declared incorrectly. It should be HWND
. It's used as the owning window for any dialog that is shown during the call to InvokeCommand
.