自编menu下拉菜单使用技巧


自编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.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值