自编menu下拉菜单使用技巧
近期闲来无事,整理过去的部分工作成果,记忆较深的是dos下的菜单程序。有直接在dos环境下使用的,也有在foxplus2.1、foxpro2.5b环境下使用的。fox环境下由于基础条件较好,编写类似的工具相对容易,而dos环境下编写实用且美观的下拉菜单程序还是有一定难度。下面介绍dos环境下自编下拉菜单的使用方式、方法,也打包提供相关的程序。
windows已经发展到非常成熟完善的地步,为何还要dos呢?大家知道,windows并不能用作实时操作系统,因为用户的选择和机器的动作之间间隔了很多层,但dos是实时操作系统,用户可以及时地、直接地控制硬件动作,在工业领域、医疗领域、军事领域等等还是需要类似dos这样的实时操作系统。所以这样的菜单程序仍有它的用武之地,这里花一些精力进行归纳总结有其现实意义。
一、菜单使用的种类
1、直接按照menuunit单元中mcd、zcd等数据定义的格式编写pascal程序对数据进行赋值,再调用单元中的菜单过程,以实现下拉菜单的功能,赋值时包括主菜单、子菜单、每个子菜单需要执行的dos程序(或pascal内部过程/函数)都要定义好。这是一种固化的下拉菜单程序生成方式,完成后,再要进行调整就麻烦一些。好处是程序所用的堆空间是可以预计的,留给调用程序的运行内存相对会大一些!
这里作为使用示例提供一个给masm宏汇编加上外壳的菜单程序源代码(mm.pas,见文后所附),详细地演示了菜单单元所需数据的预定义、调用菜单单元、菜单单元返回选项后的后期功能实现都有包含,且能长期正常使用。
2、按照规范化的格式编辑一个文本文件(缺省名称为menu.mnu),系统已经编写了一个通用的程序menuu.exe直接读取上面的文本文件,并自动运行。由于也是一个固化的程序,且是相对考虑最多的菜单项设定的堆空间,程序运行时占用的内存空间在25kB~60kB左右。所以,这种方式留给被调用程序的运行空间是最小的!
3、减少菜单程序本身的内存占用。方式一:编写一个汇编语言程序,用它来调用前面用pascal编写的菜单程序(com程序调用同名的exe程序),pascal程序实现下拉菜单,并将用户的选择以返回码的方式返回汇编语言程序,然后,由汇编语言程序去调用所要执行的dos程序。这样作的好处是汇编语言程序短小,占用的内存也就2kB左右,相对于pascal程序就小太多了。
直接按绝对路径调用也就占用这点内存,但这种情况很少或几乎没有!所以,通常是借用command加载相应的dos程序,需要再加约7kB的内存空间(dos7的command)。总共占用的内存资源在10kB以内。比纯pascal编写的菜单程序少占较多的内存。
编写汇编语言程序难度很高,普通使用者难以完成!系统提供了一个程序asmpas.exe,它能读入menu.mnu文件自动同时生成汇编语言、pascal语言程序,并自动编译、链结、com转化等功能,直接以menu.asm、menu.pas、menu.obj、menu.com、menu.exe呈现给使用者。用户只需要运行menu.com程序即可。
4、减少菜单程序本身的内存占用。方式二:编写一个批处理程序,用它来调用前面用pascal编写的菜单程序(bat程序调用同名的exe程序),pascal程序实现下拉菜单,并将用户的选择以返回码的方式返回给批处理程序,然后,由批处理程序去调用所要执行的dos程序。这样作的好处是批处理程序几乎不占用内存,相对于汇编语言程序就更节省内存了!
同样,系统提供了一个程序batpas.exe,它能读入menu.mnu文件自动同时生成批处理、pascal语言程序,并自动编译,直接以menu.bat、menu.pas、menu.exe呈现给使用者。用户只需要运行menu.bat程序即可。
二、使用方式的优选
其实在上面“种类表述”中已经进行了一定程度地比较。方法一需普通用户编程;方法二、三、四完全不用编程,只要提供合规的menu.mnu文本文件即可。另一方面,方法一可利用方法三、或四生成的menu.pas程序(只显示一次下拉菜单,等待用户选择后退出)修改、扩充成自己的菜单程序;此外,系统也提供了一个也是基于格式化的menu.mnu自动转化成全功能(指用户选择执行某功能退出相应程序后会回到菜单)的pascal程序的menuconv.exe程序。
其实怎么选择是很容易判断的。推荐用batpas方式,即bat程序调用exe程序的方式;退而其次的是用asmpas方式,即com程序调用exe程序方式。两者占用的内存都很少,不影响其调用的dos程序的执行。
三、使用的稳定性
由于是1996年底编写的程序,当时在dos5、dos6的环境中运行都正常。现在在dos7的环境下运行,部分表现有些不太一样,asmpas方式最稳定,batpas方式其次,通用程序menuu.exe运行也基本正常;但menuconv.exe转化的程序运行不正常,目前暂未查出问题点!所以这种方式不建议使用。
最近,在dosbox-x环境进行了试用,batpas方式较正常。
附录
一、程序列表
1、menuunit.tpu 下拉菜单单元
2、menuu.exe 通用下拉菜单程序
3、asmpas.exe com调用exe方式下拉菜单自动生成程序
4、batpas.exe bat调用exe方式下拉菜单自动生成程序
5、menuconv.exe 自动生成pascal下拉菜单的程序(有bug)
6、menu.mnu 格式化的菜单文本文件示例
7、tpc.exe turbo pascal 7.0 编译程序
8、turbo.tpl turbo pascal 7.0 系统程序库
9、mm.pas masm宏汇编语言简易ide环境pascal源程序
二、说明
这里最关键的是两个东西:menuunit、asmpas,是具有创新价值的所在!对原代码有兴趣的可以通过我的邮箱(gcbjoy@163.com)咨询。
gcbjoy
2025年6月17日下午 整理于武汉家中
{$m,2000,0,20480}
program mm;
uses menuunit,DOS,crt;
var
FNAME,FNAME1:STRING;
dirinfo:searchrec;
procedure setmode(x1,y1,x2,y2:word;color1,color2:byte);
begin
window(x1,y1,x2,y2);
textcolor(color1);
textbackground(color2);
clrscr;
setcur(12,14);
end;
procedure findfile;
var i:integer;
dirinfo:searchrec;
begin
i:=0;
findfirst('*.asm',$27,dirinfo);
while (doserror=0)and(i<=138) do begin
i:=i+1;
if i mod 6=0 then writeln(dirinfo.name:13)
else write(dirinfo.name:13);
findnext(dirinfo);
end;
end;
procedure deleteext(VAR name:string);
var i,j,k:integer;
s:string;
begin
i:=pos('.',name);
j:=length(name);
if i>1 then name:=copy(name,1,i-1);
end;
begin
strr[1]:=' File';
strr[2]:=' Edit';
strr[3]:=' Assemble';
strr[5]:=' Exe2bin';
strr[4]:=' Link';
strr[6]:=' RUN';
STRR[7]:=' QUIT';
MENUNUM[1]:=8;
MENUWIDE[1]:=12;
MENU[1,1]:=' New';
menu[1,2]:=' Locate';
menu[1,3]:=' Save as...';
MENU[1,4]:=' DOSSHELL';
MENU[1,5]:=' DIR *.ASM';
MENU[1,6]:=' DIR *.EXE';
MENU[1,7]:=' DIR *.*';
menu[1,8]:=' DIR *.COM';
menunum[2]:=1;
menuwide[2]:=11;
menu[2,1]:=' PE editor';
menunum[3]:=3;
menuwide[3]:=18;
menu[3,1]:=' MASM ';
menu[3,2]:=' LIST *.lst';
menu[3,3]:=' LIST compile msg';
menunum[5]:=2;
menuwide[5]:=18;
menu[5,1]:=' CONVERT TO *.COM';
MENU[5,2]:=' CONVERSION MSG';
menunum[4]:=2;
menuwide[4]:=18;
menu[4,1]:=' LINK';
MENU[4,2]:=' LIST linker msg';
menunum[6]:=2;
menuwide[6]:=18;
menu[6,1]:=' EXECUTE';
MENU[6,2]:=' LIST result';
menunum[7]:=1;
menuwide[7]:=10;
menu[7,1]:=' CANCEL ';
hh:=1;k:=1;
while true do begin
menuproc(5,1,7,strr,menu,menunum,menuwide,k,hh);
CASE K OF
1:case hh of
1:begin
setmode(1,2,80,24,BLACK,cyan);
findfile;
setmode(1,25,80,25,15,blue);
write('PLEASE INPUT FILE NAME(*.ASM): ');
READLN(FNAME);
DELETEEXT(FNAME);
setmode(1,2,80,24,BLACK,cyan);
END;
2:BEGIN
setmode(1,2,80,24,BLACK,CYAN);
findfile;
setmode(1,25,80,25,15,blue);
write('PLEASE INPUT FILE NAME(*.ASM): ');
READLN(FNAME);
DELETEEXT(FNAME);
setmode(1,2,80,24,BLACK,cyan);
END;
3:BEGIN
setmode(1,2,80,24,BLACK,cyan);
findfile;
setmode(1,25,80,25,15,blue);
write('PLEASE TARGET FILE NAME(*.ASM): ');
READLN(FNAME1);
DELETEEXT(FNAME1);
setmode(1,2,80,24,BLACK,cyan);
RUN('COPY '+FNAME+'.ASM '+FNAME1+'.ASM');
repeat until keypressed;
END;
4:RUN('');
5:BEGIN
MODE;
RUN('DIR *.ASM|MORE');
repeat until keypressed;
END;
6:BEGIN
MODE;
RUN('DIR *.EXE|MORE');
repeat until keypressed;
END;
7:BEGIN
MODE;
RUN('DIR *.*|MORE');
repeat until keypressed;
END;
8:BEGIN
MODE;
RUN('DIR *.COM|MORE');
repeat until keypressed;
END;
end;
2:case hh of
1:BEGIN
IF FNAME='' THEN BEGIN
setmode(1,2,80,24,BLACK,cyan);
findfile;
setmode(1,25,80,25,15,blue);
write('PLEASE INPUT FILE NAME(*.ASM): ');
READLN(FNAME);
DELETEEXT(FNAME);
setmode(1,2,80,24,BLACK,cyan);
END;
run('pe '+FNAME+'.ASM');
END;
end;
3:case hh of
1:begin
run('del a.c1');
run('MASM '+FNAME+','+FNAME+','+FNAME+';>a.c1');
run('readme a.c1');
end;
2:run('readme '+FNAME+'.lst');
3:run('readme a.c1');
end;
5:case hh of
1:begin
run('del a.c2');
run('EXE2BIN '+FNAME+'.EXE '+FNAME+'.COM>a.c2');
run('readme a.c2');
end;
2:run('readme a.c2');
end;
4:case hh of
1:begin
run('del a.lin');
run('link '+FNAME+','+FNAME+';>a.lin');
run('readme a.lin');
end;
2:run('readme a.lin');
end;
6:case hh of
1:begin
run('del a.out');
findfirst(fname+'.com',$23,dirinfo);
if doserror=0 then begin
run(FNAME+'.com> A.OUT');
RUN('README A.OUT');
end
else begin
run(FNAME+'.exe> A.OUT');
RUN('README A.OUT');
end;
end;
2:RUN('README A.OUT');
end;
7:RUN('end');
end;
end;
end.

3555

被折叠的 条评论
为什么被折叠?



