使用 c++ 从另一个内部菜单返回到主菜单
Returning to main menu from another inner menu using c++
我想做一个销售点(POS)程序。因此,当您打开程序时,将打开一个菜单(主菜单),这是一个滚动菜单(您可以使用箭头键上下移动以选择菜单中的项目),其中的项目就像"开始工作日","统计","库存"等等。
现在,当您按"开始工作日"(使用回车键)时,您将获得另一个菜单,该菜单会要求诸如"接受订单"之类的内容........"返回主菜单"。这就是我发现问题的地方。当我按"返回主菜单"时,我无法移回主菜单。
我的尝试
#include<iostream>
#include<conio.h>
#include<string>
#include<windows.h>
using namespace std;
int chk=0;
int sbd(void) //the order menu (start business day -> ' press ENTER')
{
int pointer=0;
string order[4]={"TAKE ORDER","CHECK MENU","MEMO","RETURN TO MAIN MENU"};
while(true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),14);
cout<<"tt ZAIKA KATHI ROLLSn";
cout<<"tttORDER MENUnn";
for(int i=0;i<=3;i++)
{
if( i==pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),11);
cout<<"-> "<<order[i]<<endl<<endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
cout<<" "<<order[i]<<endl<<endl;
}
}
while(true)
{
if(GetAsyncKeyState(VK_UP)!=0)
{
pointer-=1;
if(pointer==-1)
{
pointer=3;
}
break;
}
else if(GetAsyncKeyState(VK_DOWN)!=0)
{
pointer+=1;
if(pointer==4)
{
pointer=0;
}
break;
}
else if(GetAsyncKeyState(VK_RETURN)!=0)
{
switch(pointer)
{
case 3 : return 1;
}
}
}
Sleep(150);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
int pointer=0;
int flag=1;
string menu[6]={"START BUSINESS DAY","CONTINUE BUSINESS DAY","END BUSINESS DAY","INVENTORY MANAGEMENT","STATISTICS","SETTINGS"};
Mainmenu : while(true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),14);
int i=0;
cout<<"tt ZAIKA KATHI ROLLSn";
cout<<"tttMAIN MENUnn";
for(i=0;i<=5;i++)
{
if(i==pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),11);
cout<<"-> "<<menu[i]<<endl<<endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
cout<<" "<<menu[i]<<endl<<endl;
}
}
while(true)
{
if(GetAsyncKeyState(VK_UP)!=0)
{
pointer-=1;
if(pointer==-1)
{
pointer=5;
}
break;
}
else if(GetAsyncKeyState(VK_DOWN)!=0)
{
pointer+=1;
/* if(flag==0 && pointer==1)
pointer=3;
if(flag==1 && pointer==0)
pointer=1;*/
if(pointer==6)
{
pointer=0;
}
break;
}
else if(GetAsyncKeyState(VK_RETURN)!=0)
{
switch(pointer)
{
case 0 :chk=sbd();
if(chk==1)
goto Mainmenu;
}
}
}
Sleep(150);
}
return 0;
}
我想到的最好的想法是将"开始工作日"作为一个函数,在该函数中,当我们按"返回主菜单"时,该功能将返回一个主功能将检测到的值,然后通过使用 goto 函数程序控件将转移到主菜单。显然这是行不通的,所以任何人都可以帮助我解决这个问题吗?
发生的事情是,当您在"返回主菜单"上按回车键时,它实际上是回到主菜单。如果调试并单步执行,则会看到此信息。问题是,一旦它走出子菜单循环,它就会进入主菜单循环,检查是否按下了"Enter",传递条件并再次进入子菜单循环。
问题是你没有在代码中正确使用GetAsyncKeyState函数:
if (GetAsyncKeyState(VK_RETURN) != 0)
它检查该值是否为零。但根据文档,此函数返回一个 SHORT。
如果按下键,则最高有效位为 1,如果未按下,则为 0。
如果自上次调用 GetAsyncKeyState 以来按下了该项,则最低有效位为 1。我想这就是你想要的。因此,首先更改代码中的两个位置:
if (GetAsyncKeyState(VK_RETURN) != 0)
自:
if (GetAsyncKeyState(VK_RETURN) & 0x01 != 0)
我们只想检查最低有效位,以查看自上次调用该函数以来是否按下了该键。如果你这样做,它应该可以工作。
您也可以使用 Windows 宏这样编写它:
if (LOBYTE(GetAsyncKeyState(VK_RETURN)) != 0)
我还应该提到,您可能应该以相同的方式进行向上键和向下键。
不过我真的很喜欢它,干得不错。
编辑:GetAsyncKeyState() 返回一个短整数。它很可能是两个字节。当函数返回此值时,它会设置某些位或标志来告诉您信息。就像我说的,最高有效位(最高)告诉您键是否关闭,最低有效位告诉您自上次调用该函数以来是否按下了该键。
因此,二进制返回的数字将如下所示 (MSB) 最重要,(LSB) 最不重要:
10000000 00000001
^ MSB ^ LSB
如果这是一个无符号整数,则其值将为 32769。你对键当前是否关闭不感兴趣,但对自上次调用函数以来是否按下了键更感兴趣。你只对右边的位感兴趣。按位运算符 & AND 将比较两个位模式,当且仅当两个位均为 1 时,它将结果位设置为 1。可以这么说,这是与掩码一起使用的,因此您可以提取某些值。
10000000 00000001 // Original value
00000000 00000001 // The mask
00000000 00000001 // Result
结果为 1。然后,您可以检查该值是否为 1,如果是,则自上次调用以来按下了该键。这是一种非常低级的做事方式,但这就是Windows的工作方式,Windows实际上通过提供执行相同操作的宏LOBYTE()来提供帮助。另一种方法是该函数可以返回带有每个事物的布尔值的类/结构。
第二次编辑(进一步解释):
如果自上次调用 GetAsyncKeyState 以来按下了密钥,则最低有效位将仅为 1。因此,如果按下回车键并按住 3 秒钟,LSB 将仅在第一次调用 GetAsyncKeyState 时设置。但是,MSB 将继续返回 MSB 集,因为这指示密钥是否已关闭。我认为下面的快速程序应该很好地说明这一点。
在我们的例子中,短指令有 2(字节)16 位,因此我们将使用正确的 bitshift 运算符>>来获取它。我将返回类型从 SHORT 转换为 USHORT。这是因为对于负数的有符号整数未定义位移位,因为右移可以传播最左边的位。例如:
// Right shifting 7 bits
UNSIGNED INT
1000 0000 >> 7 = 0000 0001
SIGNED INT
1000 0000 >> 7 = 1111 1111 // We may get this instead which is not what we want
启动一个新项目并粘贴并运行,尝试按回车键:
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
while (true)
{
int count = 0;
USHORT funcResult = 0;
while ((funcResult = GetAsyncKeyState(VK_RETURN)) != 0)
// If MSB or LSB is set then condition is true
{
count++;
cout << "Return pressed " << count << " times in one loopn";
cout << "MSB = " << (funcResult >> 15) << 'n';
cout << "LSB = " << (funcResult & 1) << 'n';
}
// You will see that the MSB is always 1, because it tells us
// if the key is down.
// However the LSB is 1 only on the first run of the while loop
}
}
所以这就是为什么添加 Sleep() 也可以解决问题的原因,因为如果你按下 Enter 键 400 毫秒并松开,并使线程休眠 500 毫秒,下次它检查时,键不会关闭,并且不会设置 MSB。
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- 从子菜单返回后,正确的输入至少进入验证循环一次
- 数组在返回时失去价值(库存/菜单程序)C++
- 使用 c++ 从另一个内部菜单返回到主菜单
- 从另一个菜单返回菜单
- 需要帮助按 "enter or new line" 以允许用户返回主菜单
- 如何返回我的菜单C++
- 如何在返回菜单C++时不更新switch语句
- 返回主菜单(嵌套列表,c ++)
- IContextMenu::QueryContextMenu 返回不相关的菜单
- 返回菜单并退出程序
- 在a++中返回菜单选择
- 切换不打开的箱子,通过返回菜单功能获得选择
- 如何做一个功能,将返回我的主菜单从程序的任何地方