01:33 

Функция GetAsyncKeyState() в языке C

Помогите разобраться с функцией GetAsyncKeyState()
Мне надо прописать каким-то образом в условии, что кнопка была до этого нажата и в данный момент нажата - тогда делать то. И что кнопка была не нажата и в данный момент нажата - тогда делать сё.
Данная программа открывает бесконечный цикл из первых эн чисел последовательности Фибоначчи и гоняет эту последовательность по кругу до тех пор пока пользователь не нажмёт клавишу 0. Собственно сама клавиша принципиальна, нужна именно она, код её 0x30.
GetAsyncKeyState() определяет, нажата ли клавиша на момент вызова и была ли нажата клавиша после предыдущего вызова функции.
Некоторое описание функции есть тут help.prognoz.com/ru/mergedProjects/UiLib/interf... но оно не на Си.
Ещё тут есть на дэлфи vwsb.blogspot.ru/2008/10/api-delphi.html
И вот ещё по поиску нашлась книга букс.гугл.ру Программирование игр для Microsoft Windows. Советы профессионала, 2-е издание, про функцию

Но всё равно не пойму как с ней в данном случае работать...

#include
#include
#include
int func1(int N){
if(N == 1) {
printf("0 \n");
}
else if(N == 2){
printf("0 \n");
printf("1 \n");
}
}
int func2(int a, int b, int c, int N) {
int i;
printf("0 \n");
printf("1 \n");
for(i = 0; i < N-2; ++i){
c=a+b;
a=b;
b=c;
printf("%d\n", c);

}
printf("\n");
}

int main() {
setlocale (LC_ALL, "Rus");
int a=0;
int b=1;
int c;
int N;
int i;
printf("Введите N=");
scanf("%d", &N);
while(2 > 1) {
func1(N);
func2(a,b,c,N);
if( тут надо условие с функцией GetAsyncKeyState(0x30) такое, что в результате его выполнения программа шла в тело
ифа тогда и только тогда, когда клавиша 0 была до этого момента нажата и в данный момент нажата) {
break;
}
if( тут надо условие с функцией GetAsyncKeyState(0x30) такое, что в результате выполнения программа шла в тело
ифа тогда и только тогда, когда клавиша 0 была до этого момента не нажата и в данный момент нажата) {
break;
}
}
}


p.s. не знаю почему не отобразились инклуды, подключал эстэдио, локейл и виндоус

@темы: C++, Windows

Комментарии
2016-10-16 в 10:32 

alba-longa
На свете есть всего 10 разновидностей людей. Те, которые понимают бинарный код, и те, кто не понимают
Так а в чем именно проблема?
Студия ошибку выдает или что?
Ссылка на MSDN, описана спецификация функции. Она возвращает значение типа short, которое можно анализировать. В вашем примере предлагают сделать побитовое И с битовой маской 0x8000. Не умеете пользоваться #define?

2016-10-16 в 12:41 

dixie_flatline
А пошли вы все к Ефесянам.
Сохраняй значение GetAsyncKeyState в цикле, пример:

short prev_state = GetAsyncKeyState();
while(...) {
...
short current_state = GetAsyncKeyState();
if(current_state == нажата) {
if(prev_state == нажата) {
...
} else { // не была нажата
...
}
}
...
// в конце итерации сохранить текущее состояние:
prev_state = GetAsyncKeyState();
}


p.s. не знаю почему не отобразились инклуды
Потому что они в угловых скобках, которые парсер дайри пытается распознать как теги.

2016-10-16 в 22:08 

All_ex
Эллипс - это круг, который можно вписать в квадрат 25х40
Груша Вильямс, p.s. не знаю почему не отобразились инклуды
Есть же кнопка CODE... там всё должно отображаться...



2016-10-16 в 23:22 

alba-longa, я вот собственно и не понимаю как это сделать. Скажем вызвал я функцию GetAsyncKeyState(0x30), она отработала и возвращает значение, пусть это значение в памяти представляется несколькими ячейками-битами, то что она в эти ячейки запишет, если до этого я клавишу 0 не нажимал, а сейчас нажал и как обратиться к этой ячейке и поставить на неё условие проверки? Пишу про одну ячейку потому, что вычитал Если старший значащий бит установлен, клавиша находится в нажатом состоянии, а если самый младший значащий бит установлен, клавиша была нажата после предыдущего вызова. Тогда по логике надо как-то обратиться либо к первой, либо к последней ячейке и проверить что там стоит 0 или 1. А вот как это сделать я действительно не знаю. Скажем запись через амперсанд, которую Вы предложили (если я правильно понял) выглядит так GetAsyncKeyState(0x30) & 0x8000, но что оно значит? Проверка первой/последней ячейки на 0/1 или это только обращение к ячейке, а затем надо проверку делать, например так GetAsyncKeyState(0x30) & 0x8000 == 0 ?
Почитаю про битовые маски, впервые этот термин попался просто. Ещё один вопрос - а что за значение такое short? Мне доводилось лишь использовать short int i в цикле фора при работе с небольшими массивами, причем понимал это как короткое целое число, мол память не заполнять - целое число может принимать 2^32 значения (32 ячейки), а короткое в два раза меньше. То есть short - это по умолчанию и есть short int или что-то иное? В инете не нашел...
А пишу не в студии, а в дэвке - Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup и компилирую этим Compiler Name: TDM-GCC 4.9.2 32-bit Debug и ради интереса этим Compiler Name: TDM-GCC 4.9.2 32-bit Release. Один раз заметил интересную штуку между ними и с того момента все программы смотрю то в одном, то в другом)

dixie_flatline, с previous_state и current_state понравилось, надо попробовать... А слово нажата чем заменить? 0 - нажата, 1 - не нажата или иначе?
В общем поэкспериментировать надо.

All_ex, надо запомнить) Я просто воспользовался советом, что в шапке сообщества Можно скопировать полученный там код вместе с подсветкой сюда (для этого его нужно выделить, скопировать исходный код выделенного фрагмента и поместить его в вашу запись с тегом
 


p.s. я с этой штукой полмесяца уж сижу, лабу сдавать надо, а так и не разобрался как с этим работать всем :(

2016-10-16 в 23:47 

alba-longa
На свете есть всего 10 разновидностей людей. Те, которые понимают бинарный код, и те, кто не понимают
Груша Вильямс, Тогда по логике надо как-то обратиться либо к первой, либо к последней ячейке и проверить что там стоит 0 или 1.
Да, все верно.

выглядит так GetAsyncKeyState(0x30) & 0x8000, но что оно значит?
& — это побитовое И. Переведите оба числа в двоичную систему счисления и выполните операцию И побитово, т.е. для каждого бита отдельно. Получившееся в результате значение и будет результатом операции. В отличие от логического И (&&), где перед сравнением числовые значения приводятся к логическому типу (не ноль в true, ноль в false), а после этого выполняется операция.

например так GetAsyncKeyState(0x30) & 0x8000 == 0
Ну как-то так, да. Надо спецификацию уточнить, с чем именно сравнивать в смысле :) пробуйте.

битовые маски, впервые этот термин попался просто.
Они используются в операционных системах семейства UNIX, например, для задания прав доступа к файлу. Поскольку язык С изначально был задуман как системный для юникса, в нем такой способ получения результата довольно популярен. Получается очень экономно, на целую кучу вариантов расходуется только один байт.

Ещё один вопрос - а что за значение такое short
Краткое название short int.

целое число может принимать 2^32 значения (32 ячейки)
Чаще всего да, но в стандарте языка размер типа int не указан. Он зависит от компилятора, поэтому для лучшей переносимости программ, когда размер типа критичен (как в этой задаче), рекомендуется использовать более строго заданные типы short и long. Про типы можете здесь почитать, но это для студии только.

2016-10-17 в 00:52 

alba-longa, x xxxxx xxxxx xxxxx & 1 00000 00000 00000
Побитовое И — это бинарная операция, действие которой эквивалентно применению логического И к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях операндов. Другими словами, если оба соответствующих бита операндов равны 1, результирующий двоичный разряд равен 1; если же хотя бы один бит из пары равен 0, результирующий двоичный разряд равен 0.
Если я вызвал гетасинк и впервые нажимаю 0, то получаю в соответствии если старший значащий бит установлен, клавиша находится в нажатом состоянии
1 xxxxx xxxxx xxxx0 & 1 00000 00000 00000 = 1 aaaaa aaaaa aaaa0
Если я вызвал второй раз гетасинк и опять нажал на 0, то в соответствии если старший значащий бит установлен, клавиша находится в нажатом состоянии, а если самый младший значащий бит установлен, клавиша была нажата после предыдущего вызова получим
1 xxxxx xxxxx xxxx1 & 1 00000 00000 00000 = 1 bbbbb bbbbb bbbb0.
И непонятно с чем сравнивать... А что самое отвратное, так ещё и старший и младший биты после данных операций одинаковые :-(
То есть после указанных операций мы просто получим два каких то числа 1 aaaaa aaaaa aaaa0 и 1 bbbbb bbbbb bbbb0...

2016-10-17 в 01:51 

Просто знаете я на самом деле знаю как цикл останавливать, но случайно так вышло, интуитивно. То есть я до сих пор не понимаю как прога моя работает, но она работает.
Вот код

То есть я ввожу что хочу, хоть 10, хоть 100 и цикл идёт бесконечно, а не однократно мол я 0 уже нажимал. Вроде работает и славно. Но писать надо дальше, мне надо потом всё это зациклить, чтоб после остановки нулём программа повторялась.
Делаю так, тут я код поправил малость, запихал весь счёт последовательности в одну функцию, тем самым при вводе 1, избавился от 0 0 1 и получил требуемый 0.

Но проблема в том, что перед тем как остановить всё это дело, то есть во время работы бесконечного цикла пользователь может нажимать что попало, и вот это всё потом выводится. Скажем если бы цикл останавливался не нулём, а скажем двойкой, то после остановки двойка автоматически будет вводится, и если потом введём например 5, он будет считать первые 25 чисел. А мне вот эти все автоматически закинутые символы вовсе не нужны, более того в результате непонимания как это всё работает, я не могу даже найти инструкцию в результате которой это всё происходит - то ли сканэф это, то ли гетасинк. Как убрать этот поток тоже не знаю, никогда с таким не сталкивался. Откуда и мысль, что если всё нормально сделать ручками, может нормально и будет...:nope:
Вот что на выходе

2016-10-17 в 03:32 

Что-то меня подглючило насчёт с чем сравнивать, эта же функция дословно получить асинхронно состояние клавиши, то есть ей без разницы какая клавиша по идее, её возвращаемое значение будет говорить о состоянии - нажата, не нажата, зажата (ну в системе неизвестно какой таймер касания установлен), таким образом три значения ей вполне достаточно, а если она запоминает предыдущее то вроде 4. Таким образом надо как-то написать программу и отловить её значения. Сравнение с ними мне и надо вроде как. И тип short сразу понятен, а зачем тут больше)))

2016-10-17 в 04:31 

Как написать программу чтобы отловить её значения не пришло в голову. Надо же вроде таймер тогда как-то ставить, включать сканэф, а затем с каким-то таймингом выводить в цикле. В общем совсем не понятно как это сделать, хотя интересно. Нашел в сети её возвращаемые значения.
Возвращаемые значения:
0 - клавиша не нажата и не была нажата при предыдущем вызове этой функции.
1 - не нажата, но была нажата в прошлый вызов.
-32767 - нажата, но не была нажата в прошлый вызов.
-32768 - нажата, и была нажата в прошлый вызов.
Написал

И всё та же ерундень! Почему она пишет то, что нажал, если функция должна срабатывать лишь на состояние клавиши, что в её аргументе. И до сканэфа там далеко, перед ним же принтэф отрабатывается, а цикл тормозится до инструкции принтэф. Как-нибудь можно убирать весь этот поток нажимаемых клавиш в попытках остановить цикл, почитстить как-нибудь его или сразу как-то прописать, что вот это вся информация нам не нужна ?

2016-10-17 в 11:53 

alba-longa
На свете есть всего 10 разновидностей людей. Те, которые понимают бинарный код, и те, кто не понимают
Скажем если бы цикл останавливался не нулём, а скажем двойкой, то после остановки двойка автоматически будет вводится, и если потом введём например 5, он будет считать первые 25 чисел. А мне вот эти все автоматически закинутые символы вовсе не нужны
Ну так добавьте в условие проверки нажатия клавиши еще и чтение в какую-нибудь левую переменную. Перед брейком.

2016-11-02 в 23:15 

alba-longa, спасибо, всё написал. Но так и не понял как функция GetAsyncKeyState работает.
Вот пишут, что она делает две операции.
1) Старший бит возвращаемого значения установлен в 1, если указанная клавиша была нажата в момент вызова функции. Если этот бит равен 0, клавиша не была нажата.
2) Младший бит возвращаемого значения установлен в 1, если указанная клавиша была нажата с момента последнего вызова функции GetAsyncKeyState.

Проверяю её работу на этой программке

Функция GetAsyncKeyState вызывается нажатием клавиш как понимаю.
Допустим вначале нажал 1 (0 xxxxx xxxxx xxxx0), затем 0 (1 xxxxx xxxxx xxxx1) и 5 (0 xxxxx xxxxx xxxx0), то есть на экране "Введите N=205" и фактически произошло три вызова функции GetAsyncKeyState. Нажимаю Enter, получаю бесконечный цикл, таким образом в условие if не заходим, таким образом значение 0 xxxxx xxxxx xxxx0 = 0 00000 00000 00000 = 0 (т.е. x=0). Так как надо зайти в if чтобы остановить цикл, вызываю в четвёртый раз функцию GetAsyncKeyState, нажимая на 0 (1 xxxxx xxxxx xxxx1), и цикл останавливается, так как очевидно, что число 1 xxxxx xxxxx xxxx1 отлично от 0 00000 00000 00000 = 0 нуля.
Если же по новой перезапустить программу и сразу ввести 10, то есть вначале нажал 1 (0 xxxxx xxxxx xxxx0), затем 0 (1 xxxxx xxxxx xxxx1), то сразу уходим в цикл.
Таким образом фактически получаем, что функция GetAsyncKeyState может возвращать только три числа - 0 xxxxx xxxxx xxxx0, 1 xxxxx xxxxx xxxx1 и если сразу бы ввели 0, то получили бы 1 xxxxx xxxxx xxxx0. Применяя битовые операции к этим возвращаемым значениям и сравнивая с тем или иным числом мы и будем задавать условия.
Например для бесконечного вывода и остановки можно использовать "побитовое и" GetAsyncKeyState(0x30) & 0x8000 !=0. Но если поставить это условие if(GetAsyncKeyState(0x30) & 0x8000) и ввести 10 (1 xxxxx xxxxx xxxx1 & 1 00000 00000 00000 = 1 00000 00000 00000 = 32768), то программа не идёт в if. Что здесь не так?

Комментирование для вас недоступно.
Для того, чтобы получить возможность комментировать, авторизуйтесь:
 
РегистрацияЗабыли пароль?

ru_programming

главная