2004. január 15., csütörtök
How to load a menu from a file
Problem/Question/Abstract:
How do I load or recreate a menu stored in a text file? I'm looking for a recursive function.
Answer:
The following seems to work if the data is always organized the way you gave (depth-first recursion).
Level|Name|Caption|
0|miItem1|Item 1|
1|miItem11|Sub Item 1-1|
1|miItem12|Sub Item 1-2|
2|miItem121|Sub sub Item 1-2-1|
0|miItem2|Item 2|
1|miItem21|Sub Item 2-1|
1|miItem22|Sub Item 2-2|
I found it easier to use a stack instead of recursion, however:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, Menus;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
MainMenu1: TMainMenu;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure MenuClick(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses contnrs;
{$R *.DFM}
function IScan(ch: Char; const S: string; fromPos: Integer): Integer;
var
i: Integer;
begin
Result := 0;
for i := fromPos to Length(S) do
begin
if S[i] = ch then
begin
Result := i;
Break;
end;
end;
end;
procedure SplitString(const S: string; separator: Char; substrings: TStringList);
var
i, n: Integer;
begin
if Assigned(substrings) and (Length(S) > 0) then
begin
i := 1;
repeat
n := IScan(separator, S, i);
if n = 0 then
n := Length(S) + 1;
substrings.Add(Copy(S, i, n - i));
i := n + 1;
until
i > Length(S);
end;
end;
procedure LoadMenuFromText(aMenu: TMenu; text: TStrings; aHandler: TNotifyEvent);
type
TMenuData = record
level: Integer;
name: string;
caption: string
end;
procedure SplitLine(const line: string; var data: TMenuData);
var
sl: TStringlist;
begin
sl := TStringlist.Create;
try
SplitString(line, '|', sl);
Assert(sl.count >= 3);
data.level := StrToInt(sl[0]);
data.name := sl[1];
data.caption := sl[2];
finally
sl.free
end;
end;
var
itemStack: TStack;
level: Integer;
i: Integer;
menudata: TMenuData;
newitem: TMenuItem;
begin
level := 0;
itemstack := TStack.Create;
try
itemstack.Push(aMenu.Items);
{skip header line}
for i := 1 to text.count - 1 do
begin
SplitLine(text[i], menudata);
newitem := Menus.NewItem(menudata.caption, 0, false, true, aHandler, 0,
menudata.name);
while level > menudata.level do
begin
itemstack.Pop;
Dec(level);
end;
TMenuItem(itemstack.Peek).Add(newitem);
Itemstack.Push(newitem);
Inc(level)
end;
finally
itemstack.free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
LoadMenuFromText(mainmenu1, memo1.lines, MenuClick);
end;
procedure TForm1.MenuClick(Sender: TObject);
begin
label1.caption := (Sender as TMenuItem).Name;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése