Можно ли добавить что-то однократно вверху программы, или мне придется добавлять это в каждый цикл/условие по отдельности?
Я думаю, что вы можете добавить что-то один раз и использовать это, чтобы легко перехватывать события нажатия клавиш во всей вашей программе.
Ниже приведен фрагмент кода, показывающий функцию, которую я использовал для обработки событий нажатия клавиш в консольном приложении. Он использует GetAsyncKeyState()
. Включен раздел, в котором показано, как захватить клавишу CTRL и как вы можете что-то сделать, когда увидите ее. (приведенный фрагмент показывает, как я фиксирую последовательность клавиш <ctrl><shift><h>
, чтобы отобразить меню справки для использования этой конкретной процедуры.
Примечание. В описании delay_x(float delay)
– это просто настраиваемая неблокирующая функция сна или задержки, которая включает вызов следующего фрагмента. Он вызывается из основного цикла программы while(1){...}
. Выход из программы предусмотрен одной из комбинаций клавиш: <CTRL><SHIFT><K>
Фрагмент кода:
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// SetAppState() is called continuously from within delay_x()
// to capture keystroke combinations as they occur asynchronously
// with this application, Keystroke combinations are listed below
//
// Note: GetAsyncKeyState() can maintian information regarding the
// state of a key instantaineously by use the MSB,
// and recently by using the LSB.
//
// For this application
// only instantaineous information will be kept, minimizing
// conflicts with other keyboard shortcut definitions
// defined by other applications that may be running
// simultaineously.
//
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
void SetAppState(void)
{
short state=0;
short state1=0;
state = GetAsyncKeyState(VK_CONTROL);
if (0x80000000 & state) //check instantaineous state of key
{
state = GetAsyncKeyState(VK_SHIFT);
if (0x80000000 & state) //check instantaineous state of key
{
state = GetAsyncKeyState('h');
state1 = GetAsyncKeyState('H');
if ((0x80000000 & state) ||
(0x80000000 & state1))
{ sprintf(gTempBuf, "Usage - keystrokes to access and control the PaAutoStartSlot application:\n\n"
"<CTRL><SHIFT> H (H)elp - \n"
"<CTRL><SHIFT> V o(V)erride - \n"
"<CTRL><SHIFT> S (S)tatus - \n"
"<CTRL><SHIFT> K (K)ill - \n"
"<CTRL><SHIFT> N (N)o - \n"
"<CTRL><SHIFT> I (I)Inside - \n"
"<CTRL><SHIFT> O (O)Outside- \n"
"\nSee log file at this location for runtime errors: \n\n%s", LOGFILE);
MessagePopup("Usage Menu",gTempBuf);
}
///// ... more code ...
End of snippet
Правка — ответьте на вопросы в комментариях как вызвать GetAsyncKeyState()
Есть много способов, которыми вы могли бы вызвать GetAsyncKeyState()
в то время, когда происходят другие действия. Нитки — хороший способ. Вы также можете сделать все это в строке, используя комбинацию while()/switch(){}
. Вот очень простой пример того, как вы могли бы это сделать (в псевдокоде)
int gRunning = 1;
int state = 1;
int main(void)
{
//create variables, initialize stuff
while(gRunning)//this is your main program loop
{
delay_x(1.0);//check for keystrokes
switch(state) {
case 1:
//do some stuff here
//and experiment with values passed to delay_x(n)
delay_x(10000);//check for keystrokes
state++;
break;
case 2:
//do some different stuff here
delay_x(10000);//check for keystrokes
state++;
break;
... Add as many cases as you need for your program.
case n://last case, set execution flow to top
//do some more different stuff here
delay_x(10000);//check for keystrokes
state = 1;//loop back to top
break;
}
}
return 0;
}
void delay_x (float delay)
{
static clock_t time1;
static clock_t time2; clock();
time1 = clock();
time2 = clock();
while ((time2 - time1) < delay)
{
time2 = clock();
SetAppState(); //see partial definition in my original answer above.
}
}
Примечание. Используя этот метод, вы можете иметь столько cases
, сколько вам нужно. Важно поддерживать постоянный поток вызовов GetAsyncKeyState()
. Это делается через вызов delay_x()
.
Примечание 2. Вот сегмент (добавленный к приведенному выше определению), который приведет к завершению работы вашей программы:
state = GetAsyncKeyState('k');
state1 = GetAsyncKeyState('K');
if ((0x80000000 & state) ||
(0x80000000 & state1))
{
printf("Kill Program");
gRunning = FALSE;
}
person
ryyker
schedule
24.02.2015
Ctrl+C
вместоesc
? - person ForceBru   schedule 24.02.2015scanf
, и выйдите, если оно меньше ожидаемого. - person Austin Mullins   schedule 24.02.2015scanf
сделает паузу для ввода. - person musiphil   schedule 24.02.2015repeat
здесь можно заменить рекурсивным вызовомquadratic
, или, что еще лучше, бросить все это в циклwhile(1) or for(;;)
. Если ваш компилятор не может преобразовать хвостовую рекурсию в цикл, это в конечном итоге взорвет стек вызовов. - person Brian McFarland   schedule 24.02.2015switch()
для обработки множества различных сценариев ответа ключ/ответ. один простой пример здесь - person ryyker   schedule 24.02.2015