使用c ++从另一个内部菜单返回主菜单

时间:2018-03-13 06:50:40

标签: c++ codeblocks

我想过制作一种销售点(POS)计划。因此,当您打开程序时,菜单(主菜单)将打开,这是一个滚动菜单(您可以向上和向下移动以使用箭头键选择菜单中的项目),其中的项目是喜欢"开始营业日","统计","库存"等等等等。

现在,当您按下"开始营业日"(使用回车)时,您将获得另一个菜单,该菜单会询问诸如"接受订单" ........"返回主菜单"。这是我发现问题的地方。当我按下#34;返回主菜单"时,我无法返回主菜单。

MY ATTEMPT

#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<<"\t\t     ZAIKA KATHI ROLLS\n";
        cout<<"\t\t\tORDER MENU\n\n";

         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<<"\t\t     ZAIKA KATHI ROLLS\n";
            cout<<"\t\t\tMAIN MENU\n\n";

            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;

    }

我想到的最好的想法是让#34;开始营业日&#34;作为一个功能,当我们按下&#34;返回主菜单&#34;时,该功能将返回主功能将检测到的值,然后通过使用goto功能将程序控制转移到主菜单。显然这不起作用,所以有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

当您在“返回主菜单”上按Enter键时,它实际上会返回主菜单。如果您调试并逐步执行它,您将看到这一点。问题是,一旦它退出子菜单循环,它进入主菜单循环,检查是否按下了“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.您对该键当前是否已关闭感兴趣,但对自上次调用该函数后是否按下了该键更感兴趣。你只对右边的位感兴趣。按位运算符&amp; AND将比较两个位模式,当且仅当BOTH位为1时,它将结果位设置为1。这与掩码一起使用,因此您可以剔除某些值,可以这么说。

10000000 00000001 // Original value
00000000 00000001 // The mask
00000000 00000001 // Result

结果为1.然后您可以检查该值是否为1,如果是,则自上次调用后按下该键。这是一种非常低级的处理方式,但这有点像Windows的工作方式,Windows实际上通过提供执行相同操作的宏LOBYTE()来帮助解决问题。替代方案是函数可以为每个事物返回带有bool值的class / struct。

第二次编辑(进一步解释):

如果自上次调用GetAsyncKeyState后按下该键,则最低有效位将仅为1。因此,如果按下回车键并按住3秒钟,LSB将仅在第一次调用GetAsyncKeyState时设置。但是,MSB将继续返回MSB集,因为这表明密钥是否已关闭。以下快速程序应该很好地说明这一点。

在我们的情况下,短路有2个(字节)16位,所以我们将使用正确的bitshift运算符&gt;&gt;为拿到它,为实现它。我要将返回类型从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 loop\n";
            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()也可以解决这个问题,因为如果按下回车键400毫秒然后松开,让线程休眠500毫秒,下次检查密钥时不会向下,MSB将不会被设置。