mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
203 lines
6.2 KiB
ObjectPascal
203 lines
6.2 KiB
ObjectPascal
unit uMenuReader;
|
||
|
||
interface
|
||
uses
|
||
Windows, SysUtils, Classes, Graphics, Menus, ExtCtrls, ShellAPI, DOM, xmlread;
|
||
|
||
|
||
|
||
type
|
||
// Переменную данного типа нужно будет передавать в процедуру AddItemsToMenu
|
||
TMenuClick = procedure(Sender: TObject; FileName, Params: string;
|
||
AddParamCount: Integer);
|
||
|
||
|
||
|
||
// С помощью данной процедуры вы можете добавить к пункту MenuItem пункты
|
||
// меню, описанные в xml-файле XMLFileName. Если файл не найден, или в нем
|
||
// содержатся какие-либо ошибки, то процедура молча завершит свою работу.
|
||
// В качестве обработчика выбора пункта меню по умолчанию устанавливается
|
||
// процедура MenuClickPerformer(), объявленная ниже
|
||
procedure AddItemsToMenu(MenuItem: TMenuItem; XMLFileName: string;
|
||
ClickPerformer: TMenuClick = nil);
|
||
|
||
// Внимание! Вы можете объявить свою статичную процедуру с такими же параметрами
|
||
// и указать ее в качестве ClickPerformer при вызове функции AddItemsToMenu
|
||
// Название пункта меню вы сможете извлечь с помощью такого кода:
|
||
// S := StripHotkey(TMenuItem(Sender).Caption);
|
||
// Данная функция по умолчанию вызывает функцию ShellExecute()
|
||
procedure MenuClickPerformer(Sender: TObject; Command, Params: string;
|
||
ParamId: Integer);
|
||
|
||
implementation
|
||
type
|
||
// Delphi требует, чтобы все обработчики находились в классах, поэтому
|
||
// создадим простенький класс с одной единственной процедурой
|
||
TEventOperate = class
|
||
procedure MenuItemClick(Sender: TObject);
|
||
end;
|
||
|
||
TMenuItemRec = packed record
|
||
Caption, // Название пункта меню
|
||
Command, // Имя запускаемого файла
|
||
IconFile, // Имя файла с иконкой
|
||
Params: string; // Передаваемые параметры
|
||
ParamId, // Номер набора параметров
|
||
IconIndex: Integer; // Индекс иконки
|
||
end;
|
||
|
||
var
|
||
recList: TList; // Список указателей
|
||
ClickPerf: TMenuClick = MenuClickPerformer; // Обработчик по умолчанию
|
||
EvOp: TEventOperate; // Переменная класса TEventOperate
|
||
PMenuItem: ^TMenuItemRec;
|
||
|
||
procedure MenuClickPerformer(Sender: TObject; Command, Params: string;
|
||
ParamId: Integer);
|
||
function GetDir: string;
|
||
begin
|
||
if Pos(PathDelim, Command) = 0 then Result := '' else
|
||
Result := ExtractFilePath(ExpandFileName(Command));
|
||
end;
|
||
begin
|
||
ShellExecute(GetActiveWindow, 'open', PChar(ExtractFileName(Command)),
|
||
PChar(Params), PChar(GetDir), SW_SHOWNORMAL);
|
||
end;
|
||
|
||
procedure AddItemsToMenu(MenuItem: TMenuItem; XMLFileName: string; ClickPerformer: TMenuClick);
|
||
var
|
||
Doc: TXMLDocument;
|
||
|
||
procedure GetChildNodes(vNode: TDOMNode; vMItem: TMenuItem);
|
||
var
|
||
I: Integer;
|
||
Node1: TDOMNode;
|
||
Mi1: TMenuItem;
|
||
Caption: string;
|
||
mir: ^TMenuItemRec;
|
||
Ic: TIcon;
|
||
|
||
procedure ReadData();
|
||
var
|
||
k: Integer;
|
||
ChildNode: TDOMNode;
|
||
begin
|
||
if Caption <> '' then
|
||
begin
|
||
New(mir);
|
||
FillChar(mir^, SizeOf(TMenuItemRec), 0);
|
||
mir^.Caption := Caption;
|
||
recList.Add(mir);
|
||
Mi1.Tag := Integer(mir);
|
||
for k := 0 to Node1.ChildNodes.Count -1 do
|
||
begin
|
||
ChildNode := Node1.ChildNodes.Item[k];
|
||
// Get command
|
||
if ChildNode.NodeName = 'command' then
|
||
begin
|
||
mir^.Command := ChildNode.FirstChild.NodeValue;
|
||
end;
|
||
|
||
// Get file and icon index
|
||
if ChildNode.NodeName = 'icon' then
|
||
begin
|
||
mir^.IconFile := ChildNode.FirstChild.NodeValue;
|
||
if ChildNode.attributes.length > 0 then
|
||
mir^.IconIndex := StrToInt(ChildNode.attributes[0].NodeValue);
|
||
end;
|
||
|
||
// Определяем набор параметров и его номер
|
||
if ChildNode.NodeName = 'params' then
|
||
begin
|
||
mir^.Params := ChildNode.FirstChild.NodeValue;
|
||
if ChildNode.attributes.length > 0 then
|
||
mir^.ParamId := StrToInt(ChildNode.attributes[0].NodeValue);
|
||
end;
|
||
end; //for k
|
||
|
||
if mir^.Command <> '' then
|
||
Mi1.OnClick := EvOp.MenuItemClick;
|
||
|
||
if mir^.IconFile <> '' then
|
||
begin
|
||
Ic := TIcon.Create;
|
||
Ic.Handle := ExtractIcon(HInstance, PChar(mir^.IconFile), mir^.IconIndex);
|
||
if Ic.Handle <> 0 then
|
||
with TImage.Create(nil) do begin
|
||
Width := Ic.Width;
|
||
Height := Ic.Height;
|
||
Canvas.Draw(0, 0, Ic);
|
||
Mi1.Bitmap.Assign(Picture.Bitmap);
|
||
Free;
|
||
end;
|
||
Ic.Free;
|
||
end; // Icon
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
for I := 0 to vNode.childNodes.Count - 1 do
|
||
begin
|
||
Node1 := vNode.childNodes.item[I];
|
||
if Node1.nodeName = 'item' then
|
||
begin
|
||
Caption := Node1.attributes.item[0].NodeValue;
|
||
if Caption = '' then Continue;
|
||
|
||
if (Caption <> '-') and (vMItem.IndexOfCaption(Caption) > 0) then
|
||
begin
|
||
if Node1.childNodes.Count > 0 then
|
||
GetChildNodes(Node1, vMItem.Items[vMItem.IndexOfCaption(Caption)]);
|
||
end else
|
||
begin
|
||
Mi1 := TMenuItem.Create(vMItem);
|
||
Mi1.Caption := Caption;
|
||
|
||
ReadData();
|
||
|
||
// Считываем дочерние пункты
|
||
if (Caption <> '-') and (Node1.childNodes.Count > 0) then
|
||
GetChildNodes(Node1, Mi1);
|
||
vMItem.Add(Mi1);
|
||
end;
|
||
end;
|
||
end; // of for I
|
||
end;
|
||
|
||
begin
|
||
if @ClickPerformer <> nil then ClickPerf := ClickPerformer;
|
||
Doc := TXMLDocument.Create;
|
||
ReadXMLFile(Doc, XMLFileName);
|
||
MenuItem.Clear;
|
||
if (Doc.documentElement <> nil) and (MenuItem <> nil) then
|
||
GetChildNodes(Doc.documentElement, MenuItem);
|
||
end;
|
||
|
||
{ TEventOperate }
|
||
|
||
procedure TEventOperate.MenuItemClick(Sender: TObject);
|
||
begin
|
||
PMenuItem := Pointer(TMenuItem(Sender).Tag);
|
||
ClickPerf(Sender, PMenuItem^.Command, PMenuItem^.Params, PMenuItem^.ParamId);
|
||
end;
|
||
|
||
procedure FreeRecList;
|
||
var
|
||
I: Integer;
|
||
mir: ^TMenuItemRec;
|
||
begin
|
||
for I := 0 to recList.Count - 1 do
|
||
begin
|
||
mir := recList.Items[I];
|
||
Dispose(mir);
|
||
end;
|
||
recList.Free;
|
||
end;
|
||
|
||
initialization
|
||
recList := TList.Create;
|
||
EvOp := TEventOperate.Create;
|
||
finalization
|
||
FreeRecList();
|
||
EvOp.Free;
|
||
end.
|