本帖最后由 happy886rr 于 2016-12-6 16:21 编辑
[2016/12/06]修复一处设计错误。
由于微软的choice.exe无法实现小于1秒的延时,遂用C语言高仿了choice.exe,功能、性能与微软原版毫无差别,但支持0.0几秒延迟,需要的可以自行编译下面的源码。- /*
- CONSOLE KEY TOOL, COPYRIGHT@2016~2018 BY HAPPY
- High imitation CHOICE.EXE
- VERSION 1.0
- */
-
- #include <stdio.h>
- #include <Windows.h>
- #include <conio.h>
- #include <time.h>
-
- #define HELP_INFORMATION "\
- CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]\n\n\
- Description:\n\
- This tool allows users to select one item from a list \n\
- of choices and returns the index of the selected choice.\n\n\
- Parameter List:\n\
- /C choices Specifies the list of choices to be created.\n\
- Default list is \"YN\".\n\n\
- /N Hides the list of choices in the prompt.\n\
- The message before the prompt is displayed\n\
- and the choices are still enabled.\n\n\
- /CS Enables case-sensitive choices to be selected.\n\
- By default, the utility is case-insensitive.\n\n\
- /T timeout The number of seconds to pause before a default \n\
- choice is made. Acceptable values are from 0.000 to \n\
- 9999... If 0 is specified, there will be no pause \n\
- and the default choice is selected.\n\n\
- /D choice Specifies the default choice after nnnn seconds.\n\
- Character must be in the set of choices specified\n\
- by /C option and must also specify nnnn with /T.\n\n\
- /M text Specifies the message to be displayed before \n\
- the prompt. If not specified, the utility \n\
- displays only a prompt.\n\n\
- /? Displays this help message.\n\n\
- NOTE:\n\
- The ERRORLEVEL environment variable is set to the index of the\n\
- key that was selected from the set of choices. The first choice\n\
- listed returns a value of 1, the second a value of 2, and so on.\n\
- If the user presses a key that is not a valid choice, the tool \n\
- sounds a warning beep. If tool detects an error condition,\n\
- it returns an ERRORLEVEL value of 255. If the user presses \n\
- CTRL+BREAK or CTRL+C, the tool returns an ERRORLEVEL value\n\
- of 0. When you use ERRORLEVEL parameters in a batch program, list\n\
- them in decreasing order.\n\n\
- Examples:\n\
- CHOICE /?\n\
- CHOICE /C YNC /M \"Press Y for Yes, N for No or C for Cancel.\"\n\
- CHOICE /T 10 /C ync /CS /D y \n\
- CHOICE /C ab /M \"Select a for option 1 and b for option 2.\"\n\
- CHOICE /C ab /N /M \"Select a for option 1 and b for option 2.\"\n"
-
- /***************功能函数群***************/
- //帮助信息
- void HelpInfomation(int code)
- {
- fputs(HELP_INFORMATION, stdout);
- exit(code);
- }
- //核心函数
- int ChoiceCore(const unsigned char FLAG, char* list, char* text, clock_t timeout, unsigned char deft)
- {
- unsigned char KEY_V;
- char* p;
-
- //选择列表为空则退出
- if(list==NULL)
- {
- fputs("Missing choice list\n", stdout);
- exit(255);
- }
-
- //警告/T开关和/D开关必须同时指定,或同时未指定
- if((((FLAG&0x04)>>2)^((FLAG&0x08)>>3))==0x01)
- {
- fputs("The /T swith and /D swith must be specified at the same time,\nType \"CHOICE /?\" for usage.\n", stdout);
- exit(255);
- }
-
- //显示/M开关之后的消息
- if(text!=NULL)
- {
- fputs(text, stdout);
- fputc( ' ', stdout);
- }
-
- //如未开启CS开关,则将选择列表转为大写
- if((FLAG&0x01) ==0x00)
- {
- list=strupr(list);
- deft=('a'<=deft && deft<='z')?deft-32:deft;
- }
-
- //如未开启N开关,则显示/M之后的消息
- if((FLAG&0x02) ==0x00)
- {
- p=(char*)list;
- fputc('[', stdout);
- fputc( *p, stdout);
- while( *(++p) !='\0')
- {
- fputc(',', stdout);
- fputc( *p, stdout);
- }
- fputs("]?", stdout);
- }
-
- clock_t start=clock();
- do
- {
- if(kbhit())
- {
- KEY_V=getch();
- p=(char*)list;
- while(*p!='\0')
- {
- if(
- ((FLAG&0x01)==0x00 && (*p==KEY_V-32)) ||
- (*p ==KEY_V)
- )
- {
- fputc( *p, stdout);
- fputc('\n', stdout);
- return p-list+1;
- }
- p++;
- }
- }
- //缓解CPU占用
- Sleep(1);
-
- }
- while(clock()-start <timeout || timeout==-255);
-
- //超时则抛出/D开关指定的默认选项
- fputc(deft, stdout);
- fputc('\n', stdout);
- p=(char*)list;
- while(*p!='\0'){
- if(*p==deft){break;}
- p++;
- }
- if(*p=='\0'){return 255;}
- return p-list+1;
- }
-
- /*************MAIN主函数入口*************/
- int main(int argc, char** argv)
- {
- unsigned char FLAG=0;
- unsigned char deft='Y';
- clock_t timeout=(clock_t)(-255);
- char* list="YN";
- char* text=NULL;
-
- int i=0;
- while(++i<argc)
- {
- if(argv[i][0]!='/')
- {
- continue;
-
- }
- else if(argv[i][1]=='?')
- {
- //显示帮助消息
- HelpInfomation(255);
-
- }
- else if(
- (argv[i][1]=='C'||argv[i][1]=='c') &&
- (argv[i][2]=='S'||argv[i][2]=='s')
- )
- {
- //区分大写小
- FLAG|=0x01;
- continue;
-
- }
- else if(argv[i][1]=='N'||argv[i][1]=='n')
- {
- //隐藏选项列表
- FLAG|=0x02;
- continue;
-
- }
- else if(i+1 >=argc ||argv[i+1][1]=='/')
- {
- fputs("Missing parameters\n", stdout);
- return 255;
- }
-
- switch(argv[i][1])
- {
-
- //从选择列表选择一项并返回选项索引
- case 'C':
- case 'c':
- list=argv[i+1];
- break;
-
- //做出默认选择之前,暂停的秒数
- case 'T':
- case 't':
- timeout=(clock_t)(atof(argv[i+1])*1000);
- FLAG|=0x04;
- break;
-
- //在等待...秒之后指定默认选项
- case 'D':
- case 'd':
- deft=(unsigned char)argv[i+1][0];
- FLAG|=0x08;
- break;
-
- //指定提示之前要显示的消息
- case 'M':
- case 'm':
- text=argv[i+1];
- break;
-
- //错误反馈
- default:
- fputs("Error option\n", stdout);
- return 255;
- }
- i++;
- }
- //调用核心函数
- return ChoiceCore(FLAG, list, text, timeout, deft);
- }
复制代码 使用说明:- -----------------------------------------------------------------------------
- CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]
- -----------------------------------------------------------------------------
- 参数列表:
- /C choices "YN"。
-
- /N 在提示符中隐藏选项列表。提示前面的消息得到显示,
- 选项依旧处于启用状态。
-
- /CS 允许选择分大小写的选项。在默认情况下,这个工具
- 是不分大小写的。
-
- /T timeout 做出默认选择之前,暂停的秒数。可接受的值是从0.000
- 到 9999...。如果指定了 0,就不会有暂停,默认选项
- 会得到选择。
-
- /D choice 在 nnnn 秒之后指定默认选项。字符必须在用 /C 选
- 项指定的一组选择中; 同时,必须用 /T 指定 nnnn。
-
- /M text 指定提示之前要显示的消息。如果没有指定,工具只
- 显示提示。
-
- /? 显示此帮助消息。
- -----------------------------------------------------------------------------
复制代码
|