doublecmd/uMenuReader.pas
Alexander Koblov ab667f7acc Create SVN.
2007-02-08 19:46:07 +00:00

203 lines
6.2 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.