#c #input #keyboard #mouse
#c #ввод #клавиатура #мышь
Вопрос:
Мне интересно, как принимать ввод с клавиатуры и мыши в C , используя Visual Studio 2010, для 32-разрядной версии Windows 7.
—РЕДАКТИРОВАТЬ: я забыл упомянуть, что мне нужен ввод с клавиатуры / мыши, не прерывая поток программы. Что-то вроде слушателя. Я не хочу приостанавливать программу и запрашивать ввод, а затем заставлять пользователя вводить его и нажимать enter. То, что я ищу, больше похоже на:
Если пользователь нажимает W, S, A, D -> что-то происходит.
Или: если пользователь нажимает левую кнопку мыши в -> что-то происходит.
Я должен упомянуть, что я все еще новичок в программировании в целом. Я знаю основы программирования ООП, но это все. Я определенно уверен, что это будет связано с вещами, о которых я еще не знаю, и я не возражаю, я просто прошу вас подробно объяснить это и, возможно, привести пример, чтобы я знал, как его использовать.
Спасибо.
Комментарии:
1. Если вы пишете консольное приложение на C , это немного сложнее, чем вы думаете. Вам придется прослушивать поток сообщений Windows для различных сообщений и интерпретировать их. Что открывает целую банку червей.
Ответ №1:
ввод с клавиатуры / мыши без прерывания потока
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hIn;
HANDLE hOut;
COORD KeyWhere;
COORD MouseWhere;
COORD EndWhere;
bool Continue = TRUE;
int KeyEvents = 0;
int MouseEvents = 0;
INPUT_RECORD InRec;
DWORD NumRead;
hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
cout << "Key Events : " << endl;
cout << "Mouse Events : " << flush;
KeyWhere.X = 15;
KeyWhere.Y = 0;
MouseWhere.X = 15;
MouseWhere.Y = 1;
EndWhere.X = 0;
EndWhere.Y = 3;
while (Continue)
{
ReadConsoleInput(hIn,
amp;InRec,
1,
amp;NumRead);
switch (InRec.EventType)
{
case KEY_EVENT:
KeyEvents;
SetConsoleCursorPosition(hOut,
KeyWhere);
cout << KeyEvents << flush;
if (InRec.Event.KeyEvent.uChar.AsciiChar == 'x')
{
SetConsoleCursorPosition(hOut,
EndWhere);
cout << "Exiting..." << endl;
Continue = FALSE;
}
break;
case MOUSE_EVENT:
MouseEvents;
SetConsoleCursorPosition(hOut,
MouseWhere);
cout << MouseEvents << flush;
break;
}
}
return 0;
}
Комментарии:
1. Мне было интересно, не могли бы вы показать мне, как я мог бы проверить, когда клавиша нажата / отпущена по отдельности, а не ключевые события в целом?
Ответ №2:
За этим стоит ряд связанных концепций.
На самом низком уровне клавиатура и мышь являются аппаратными устройствами, которые генерируют некоторые «прерывания» (в виде электрических сигналов) для центрального процессора. Операционная система предоставляет некоторые драйверы, которые обрабатывают такие прерывания путем декодирования протокола, специфичного для связи с устройством, и «стандартизации» (на уровне ОС) этих сигналов в форме событий.
С помощью «консольных приложений» операционная система обрабатывает эти события (в частности, клавиатуру), заполняя буфер ввода (по существу, char[] ), который становится доступным в виде «практически бесконечной последовательности символов» (сложное имя для «файла») с именем «CON», таким образом имитируя»бесконечная модель телетайпа» первых компьютеров. В программе на C стандартная библиотека — при запуске программы — связывает с этим «файлом» объекты std::cin
и std::cout
stream , поэтому вы можете прочитать вводимую последовательность символов с помощью std::istream
функций и операторов.
К сожалению, в «графических приложениях» нет «модели ранних дней» для имитации, а «события» остаются доступными в качестве собственной структуры операционной системы. Разные операционные системы отличаются способом представления и обработки таких событий, но можно заметить определенное сходство. Для Windows (поскольку ваш вопрос касается) типичная программа последовательно извлекает эти события с помощью «цикла сообщений», в котором вызываются определенные API-интерфейсы ОС. В этом цикле типичная программа также вызовет другой API ОС для отправки этих событий в соответствующую процедуру «обратного вызова», связанную с ранее созданным «окном». Эта процедура обратного вызова должна обнаруживать код события, приводить соответствующий параметр и управлять ими, выполняя требуемое действие.
Более точную информацию можно увидеть в руководстве по программированию WIN32, например http://www.winprog.org/tutorial /. Большая часть кода, по сути, на C, поскольку C — это язык, на котором формализованы API. Для C затем было написано несколько библиотек для представления объектов ОС в форме классов C и сопоставления API-интерфейсов ОС с членами этих классов. Эти библиотеки могут быть либо специфичными для ОС (например, MFC, WTL …), либо «мультиплатформенными» (они существуют в разных версиях, отображая API различных ОС в один и тот же интерфейс C ), такие как wxWidget, Qt, Gtk, Fltk …
Надеюсь, это даст вам больше подсказок для размышления.
Комментарии:
1. Большое спасибо ^^. Это действительно помогает, когда дело доходит до теории, лежащей в основе этого.
2. Полезно и, я думаю, необходимо для OP.
Ответ №3:
Если вы пишете консольное приложение, вы можете использовать scanf или cin для ввода с клавиатуры. Консольные приложения не поддерживают мышь.
Если вы пишете приложение с графическим интерфейсом, вы создадите приложение на основе стандартных элементов управления Windows, которые имеют встроенные функции для ввода с помощью мыши и клавиатуры. Вы можете использовать эти многоразовые элементы управления как есть, или вы можете дополнить их, чтобы они вели себя именно так, как вы хотите для своего приложения.
Например, в приложении с графическим интерфейсом есть стандартный элемент управления редактированием, который вы можете использовать, чтобы пользователь мог вводить. Ваша программа получает сообщения, когда пользователь вводит в нее текст, и на основе этих сообщений или других событий вы можете извлечь текст и выполнять с ним действия, требуемые вашей программой.
Комментарии:
1. Извините, я забыл упомянуть, что я пытаюсь принять ввод, не прерывая программу. Я отредактировал свой первоначальный вопрос, чтобы отразить это сейчас. Спасибо, что нашли время ответить
Ответ №4:
Windows или консоль?
Если консоль, используйте:
std::cin >> myVar;
Комментарии:
1. Извините, я забыл упомянуть, что я пытаюсь принять ввод, не прерывая программу. Я отредактировал свой первоначальный вопрос, чтобы отразить это сейчас. Спасибо, что нашли время ответить.