ADD: Context menu for some objects

This commit is contained in:
Alexander Koblov 2007-12-19 21:59:41 +00:00
commit bfa96e7c01
6 changed files with 189 additions and 176 deletions

View file

@ -14,4 +14,5 @@
подставляется имя исходного файла/каталога
24.11.2007 ADD: Возможность использовать на панели инструментов значки из *.exe и *.dll
файлов под Windows
28.11.2007 Добавил блокировку, если выполняется операция c архивом
28.11.2007 Добавил блокировку, если выполняется операция c архивом
19.12.2007 ADD: Контекстное меню для нескольких объектов

View file

@ -5,4 +5,5 @@
удалить в контекстное меню
15.08.2007 ADD: Обновление списка дисков
19.08.2007 ADD: Функции отображения файла в память
23.11.2007 ADD: Функцию ShowOpenIconDialog, которая открывает диалог выбора значка
23.11.2007 ADD: Функцию ShowOpenIconDialog, которая открывает диалог выбора значка
19.12.2007 ADD: Контекстное меню для нескольких объектов

View file

@ -4,11 +4,11 @@ object frmMain: TfrmMain
Top = 278
Width = 540
HorzScrollBar.Page = 539
VertScrollBar.Page = 316
VertScrollBar.Page = 315
VertScrollBar.Range = 79
ActiveControl = pnlNotebooks
Caption = 'Double Commander'
ClientHeight = 317
ClientHeight = 316
ClientWidth = 540
Font.Color = clBlack
Font.Height = 13
@ -81,34 +81,34 @@ object frmMain: TfrmMain
end
end
object pnlNotebooks: TPanel
Height = 240
Height = 239
Top = 50
Width = 540
Align = alClient
ClientHeight = 240
ClientHeight = 239
ClientWidth = 540
FullRepaint = False
TabOrder = 1
TabStop = True
object MainSplitter: TSplitter
Left = 171
Height = 200
Height = 199
Top = 1
Width = 4
ResizeStyle = rsLine
end
object pnlLeft: TPanel
Left = 1
Height = 200
Height = 199
Top = 1
Width = 170
Align = alLeft
BevelOuter = bvNone
ClientHeight = 200
ClientHeight = 199
ClientWidth = 170
TabOrder = 0
object nbLeft: TNotebook
Height = 176
Height = 175
Hint = 'Left'
Top = 24
Width = 170
@ -177,16 +177,16 @@ object frmMain: TfrmMain
end
object pnlRight: TPanel
Left = 175
Height = 200
Height = 199
Top = 1
Width = 364
Align = alClient
BevelOuter = bvNone
ClientHeight = 200
ClientHeight = 199
ClientWidth = 364
TabOrder = 1
object nbRight: TNotebook
Height = 176
Height = 175
Hint = 'Right'
Top = 24
Width = 364
@ -256,7 +256,7 @@ object frmMain: TfrmMain
object pnlCommand: TPanel
Left = 1
Height = 38
Top = 201
Top = 200
Width = 538
Align = alBottom
Anchors = [akLeft, akRight]
@ -306,7 +306,7 @@ object frmMain: TfrmMain
end
object pnlKeys: TPanel
Height = 27
Top = 290
Top = 289
Width = 540
Align = alBottom
Anchors = [akLeft, akRight]

View file

@ -481,11 +481,15 @@ end;
procedure TfrmMain.actContextMenuExecute(Sender: TObject);
var
pfri : PFileRecItem;
fl : TFileList;
begin
pfri := ActiveFrame.GetActiveItem;
pfri^.sPath := ActiveFrame.ActiveDir;
ShowContextMenu(Handle, pfri, Mouse.CursorPos.x, Mouse.CursorPos.y);
fl := TFileList.Create;
with ActiveFrame do
begin
SelectFileIfNoSelected(GetActiveItem);
CopyListSelectedExpandNames(pnlFile.FileList, fl, ActiveDir, False);
end;
ShowContextMenu(Handle, fl, Mouse.CursorPos.x, Mouse.CursorPos.y);
end;
procedure TfrmMain.actLeftOpenDrivesExecute(Sender: TObject);
@ -2192,14 +2196,10 @@ end;
{ Show context menu on right click }
procedure TfrmMain.framedgPanelMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
pfri : PFileRecItem;
begin
if Button = mbRight then
begin
pfri := ActiveFrame.GetActiveItem;
pfri^.sPath := ActiveFrame.ActiveDir;
ShowContextMenu(Handle, pfri, Mouse.CursorPos.x, Mouse.CursorPos.y);
actContextMenu.Execute;
end;
end;

View file

@ -1560,7 +1560,7 @@ msgstr "Копир F5"
#: TFRMMAIN.ACTRENAME.CAPTION
msgid "Rename F6"
msgstr "Переимен F6"
msgstr "Переместить F6"
#: TFRMMAIN.ACTMAKEDIR.CAPTION
msgid "MakeDir F7"

View file

@ -47,13 +47,13 @@ type
procedure SetMyWndProc(Handle : THandle);
procedure ShowFilePropertiesDialog(FileList:TFileList; const aPath:String);
procedure ShowContextMenu(Handle : THandle; pfri : PFileRecItem; X, Y : Integer);
procedure ShowContextMenu(Handle : THandle; FileList : TFileList; X, Y : Integer);
function ShowOpenIconDialog(Owner: TCustomControl; var sFileName : String) : Boolean;
implementation
uses
fMain, uVFSutil, uOSUtils, uExts, uGlobs;
LCLProc, fMain, uVFSutil, uOSUtils, uExts, uGlobs;
var
{$IFDEF MSWINDOWS}
@ -67,7 +67,7 @@ var
function MyWndProc(hwnd: HWND; Msg, wParam, lParam: Cardinal): Cardinal; stdcall;
begin
case Msg of
(* For working wuth submenu of contex menu *)
(* For working with submenu of contex menu *)
WM_INITMENUPOPUP,
WM_DRAWITEM,
WM_MENUCHAR,
@ -118,74 +118,86 @@ begin
end;
end;
procedure ShowContextMenu(Handle : THandle; pfri : PFileRecItem; X, Y : Integer);
var
fri : TFileRecItem;
{$IFDEF MSWINDOWS}
desktop: IShellFolder;
mycomputer: IShellFolder;
folder: IShellFolder;
pidl: PItemIDList;
function GetIContextMenu(Handle : THandle; FileList : TFileList): IContextMenu;
type
TPIDLArray = array[0..0] of PItemIDList;
PPIDLArray = ^TPIDLArray;
var
Folder,
DesktopFolder: IShellFolder;
PathPIDL,
tmpPIDL: PItemIDList;
malloc: IMalloc;
chEaten: ULONG;
S: WideString;
List: PPIDLArray;
I : Integer;
pchEaten,
dwAttributes: ULONG;
begin
Result := nil;
if not Succeeded(SHGetMalloc(malloc)) then Exit;
if not Succeeded(SHGetDesktopFolder(DeskTopFolder)) then Exit;
try
List := malloc.Alloc(SizeOf(PItemIDList)*FileList.Count);
for I := 0 to FileList.Count - 1 do
begin
//********** if s <> sPath then
S := FileList.GetItem(I)^.sPath;
OleCheck(DeskTopFolder.ParseDisplayName(Handle, nil, PWideChar(S), pchEaten, PathPIDL, dwAttributes));
try
OleCheck(DeskTopFolder.BindToObject(PathPIDL, nil, IID_IShellFolder, Folder));
finally
malloc.Free(PathPIDL);
end;
//*****************
S:=FileList.GetItem(I)^.sName;;
OleCheck(Folder.ParseDisplayName(Handle, nil, PWideChar(S), pchEaten, tmpPIDL, dwAttributes));
List^[i] := tmpPIDL;
end;
Folder.GetUIObjectOf(Handle, FileList.Count, PItemIDList(List^), IID_IContextMenu, nil, Result);
finally
for I := 0 to FileList.Count - 1 do
malloc.Free(List^[i]);
malloc.Free(List);
end;
end;
{$ENDIF}
procedure ShowContextMenu(Handle : THandle; FileList : TFileList; X, Y : Integer);
var
{$IFDEF MSWINDOWS}
contMenu: IContextMenu;
menu: HMENU;
cmd: UINT;
iCmd: Integer;
HR: HResult;
cmici: CMINVOKECOMMANDINFO;
pwPath,
pwFileName : PWideChar;
bHandled : Boolean;
ZVerb: array[0..255] of char;
sVerb : String;
{$ELSE}
fri : TFileRecItem;
mi, miActions : TMenuItem;
i:Integer;
sCmd:String;
sl: TStringList;
{$ENDIF}
begin
fri := pfri^;
if fri.sName = '..' then
begin
fri.sName := ExtractFileName(ExcludeTrailingPathDelimiter(fri.sPath));
fri.sPath := LowDirLevel(fri.sPath);
end;
if FileList.Count = 0 then Exit;
{$IFDEF MSWINDOWS}
OleCheck( SHGetMalloc(malloc) );
OleCheck( SHGetDesktopFolder(desktop) );
OleCheck( SHGetSpecialFolderLocation(Handle, CSIDL_DRIVES, pidl) );
try
OleCheck( desktop.BindToObject(pidl, nil, IShellFolder, mycomputer) );
finally
malloc.Free(pidl);
end;
dwAttributes := 0;
pwPath := StringToOleStr(fri.sPath);
OleCheck( mycomputer.ParseDisplayName(Handle, nil, pwPath, chEaten, pidl, dwAttributes) );
try
OleCheck( mycomputer.BindToObject(pidl, nil, IShellFolder, folder) );
finally
malloc.Free(pidl);
end;
dwAttributes := 0;
pwFileName := StringToOleStr(fri.sName);
OleCheck( folder.ParseDisplayName(Handle, nil, pwFileName, chEaten, pidl, dwAttributes) );
try
OleCheck( folder.GetUIObjectOf(Handle, 1, pidl, IID_IContextMenu, nil, contMenu) );
finally
malloc.Free(pidl);
end;
contMenu := GetIContextMenu(Handle, FileList);
menu := CreatePopupMenu;
try
OleCheck( contMenu.QueryContextMenu(menu, 0, 1, $7FFF, CMF_EXPLORE or CMF_CANRENAME) );
AppendMenu(menu,0,0,'Test');
contMenu.QueryInterface(IID_IContextMenu2, ICM2); //To handle submenus.
//AppendMenu(menu,0,0,'Test');
contMenu.QueryInterface(IID_IContextMenu2, ICM2); // to handle submenus.
cmd := UINT(TrackPopupMenu(menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD, X, Y, 0, Handle, nil));
finally
DestroyMenu(menu);
@ -199,21 +211,33 @@ begin
sVerb := StrPas(ZVerb);
bHandled := False;
if SameText(sVerb, sCmdVerbRename) then
if SameText(sVerb, sCmdVerbDelete) then
begin
frmMain.RenameFile('');
frmMain.actDelete.Execute;
bHandled := True;
end
else if SameText(sVerb, sCmdVerbRename) then
begin
if FileList.Count = 1 then
frmMain.RenameFile('')
else
frmMain.actRename.Execute;
bHandled := True;
end
else if SameText(sVerb, sCmdVerbOpen) then
begin
if FPS_ISDIR(fri.iMode) or (fri.bLinkIsDir) then
begin
if pfri^.sName = '..' then
frmMain.ActiveFrame.pnlFile.cdUpLevel
else
frmMain.ActiveFrame.pnlFile.cdDownLevel(@fri);
bHandled := True;
end;
if FileList.Count = 1 then
with FileList.GetItem(0)^ do
begin
if FPS_ISDIR(iMode) or (bLinkIsDir) then
begin
if sName = '..' then
frmMain.ActiveFrame.pnlFile.cdUpLevel
else
frmMain.ActiveFrame.pnlFile.cdDownLevel(FileList.GetItem(0));
bHandled := True;
end; // is dir
end; // with
end;
if not bHandled then
@ -233,6 +257,7 @@ begin
frmMain.ActiveFrame.RefreshPanel;
end; // if cmd > 0
FileList.Free;
end;
{$ELSE}
if not Assigned(CM) then
@ -249,78 +274,78 @@ end;
mi.Caption:='-';
CM.Items.Add(mi);
miActions:=TMenuItem.Create(CM);
miActions.Caption:='Actions';
CM.Items.Add(miActions);
if FileList.Count = 1 then
begin
miActions:=TMenuItem.Create(CM);
miActions.Caption:='Actions';
CM.Items.Add(miActions);
{ Actions submenu }
// Read actions from doublecmd.ext
sl:=TStringList.Create;
try
if FPS_ISDIR(fri.iMode) or (fri.bIsLink) then Exit;
if gExts.GetExtCommands(lowercase(ExtractFileExt(fri.sName)),sl) then
begin
//founded any commands
for i:=0 to sl.Count-1 do
begin
sCmd:=sl.Strings[i];
if pos('VIEW=',sCmd)>0 then Continue; // view command is only for viewer
frmMain.ActiveFrame.pnlFile.ReplaceExtCommand(sCmd, @fri);
mi:=TMenuItem.Create(miActions);
mi.Caption:=sCmd;
mi.Hint:=Copy(sCmd, pos('=',sCmd)+1, length(sCmd));
// length is bad, but in Copy is corrected
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
mi.Tag:=Integer(@fri);
miActions.Add(mi);
end;
{ Actions submenu }
// Read actions from doublecmd.ext
sl:=TStringList.Create;
try
fri := FileList.GetItem(0)^;
if FPS_ISDIR(fri.iMode) or (fri.bIsLink) then Exit;
if gExts.GetExtCommands(lowercase(ExtractFileExt(fri.sName)),sl) then
begin
//founded any commands
for i:=0 to sl.Count-1 do
begin
sCmd:=sl.Strings[i];
if pos('VIEW=',sCmd)>0 then Continue; // view command is only for viewer
frmMain.ActiveFrame.pnlFile.ReplaceExtCommand(sCmd, @fri);
mi:=TMenuItem.Create(miActions);
mi.Caption:=sCmd;
mi.Hint:=Copy(sCmd, pos('=',sCmd)+1, length(sCmd));
// length is bad, but in Copy is corrected
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
mi.Tag:=Integer(@fri);
miActions.Add(mi);
end;
end;
// now add delimiter
mi:=TMenuItem.Create(miActions);
mi.Caption:='-';
miActions.Add(mi);
// now add VIEW item
mi:=TMenuItem.Create(miActions);
mi.Caption:='{!VIEWER}' + fri.sPath + fri.sName;
mi.Hint:=mi.Caption;
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
miActions.Add(mi);
// now add EDITconfigure item
mi:=TMenuItem.Create(miActions);
mi.Caption:='{!EDITOR}' + fri.sPath + fri.sName;
mi.Hint:=mi.Caption;
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
miActions.Add(mi);
finally
FreeAndNil(sl);
end;
// now add delimiter
mi:=TMenuItem.Create(miActions);
mi.Caption:='-';
miActions.Add(mi);
{ /Actions submenu }
// now add VIEW item
mi:=TMenuItem.Create(miActions);
mi.Caption:='{!VIEWER}' + fri.sPath + fri.sName;
mi.Hint:=mi.Caption;
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
miActions.Add(mi);
// now add EDITconfigure item
mi:=TMenuItem.Create(miActions);
mi.Caption:='{!EDITOR}' + fri.sPath + fri.sName;
mi.Hint:=mi.Caption;
mi.OnClick:=TContextMenu.ContextMenuSelect; // handler
miActions.Add(mi);
finally
FreeAndNil(sl);
end;
{ /Actions submenu }
mi:=TMenuItem.Create(CM);
mi.Caption:='-';
CM.Items.Add(mi);
end; // if count = 1
mi:=TMenuItem.Create(CM);
mi.Caption:='-';
mi.Action := frmMain.actRename;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
mi.Caption:='Cut';
mi.Action := frmMain.actCopy;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
mi.Caption:='Copy';
mi.Action := frmMain.actDelete;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
mi.Caption:='Delete';
mi.Hint := 'actDelete';
mi.OnClick:=TContextMenu.ContextMenuSelect;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
mi.Caption:='Rename';
mi.Hint := 'actShiftF6';
mi.OnClick:=TContextMenu.ContextMenuSelect;
mi.Action := frmMain.actRenameOnly;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
@ -328,12 +353,12 @@ end;
CM.Items.Add(mi);
mi:=TMenuItem.Create(CM);
mi.Caption:='Properties';
mi.Hint := 'actFileProperties';
mi.OnClick:=TContextMenu.ContextMenuSelect;
mi.Action := frmMain.actFileProperties;
CM.Items.Add(mi);
CM.PopUp(X, Y);
FileList.Free;
end;
{$ENDIF}
@ -345,41 +370,27 @@ begin
end;
{$ELSE}
var
SExInfo: TSHELLEXECUTEINFO;
Error: LongInt;
iCurrent : Integer;
FName : String;
(* Find first selected file *)
function FindNextSelected:Boolean;
var
i:Integer;
begin
for i:=iCurrent to FileList.Count-1 do
begin
if FileList.GetItem(i)^.bSelected then
begin
iCurrent:=i;
Result:=True;
Exit;
end;
end;
Result:=False;
end;
cmici: CMINVOKECOMMANDINFO;
contMenu: IContextMenu;
fl : TFileList;
begin
iCurrent := 0;
if FindNextSelected then
if FileList.Count = 0 then Exit;
fl := TFileList.Create;
CopyListSelectedExpandNames(FileList, fl, aPath, False);
contMenu := GetIContextMenu(frmMain.Handle, fl);
FillChar(cmici, sizeof(cmici), #0);
with cmici do
begin
FName := aPath + FileList.GetItem(iCurrent)^.sName;
//DebugLN(FName);
ZeroMemory(Addr(SExInfo),SizeOf(SExInfo));
SExInfo.cbSize := SizeOf(SExInfo);
SExInfo.lpFile := PChar(FName);
SExInfo.lpVerb := 'properties';
SExInfo.fMask := SEE_MASK_INVOKEIDLIST;
ShellExecuteExA(Addr(SExInfo));
cbSize := sizeof(cmici);
hwnd := frmMain.Handle;
lpVerb := 'properties';
nShow := SW_SHOWNORMAL;
end;
OleCheck(contMenu.InvokeCommand(cmici));
fl.Free;
end;
{$ENDIF}