Как я могу запустить две функции, одну для клавиатуры и одну для мыши, параллельно, используя Turbo C++?

Я пытаюсь получить ввод с помощью мыши и клавиатуры одновременно, используя Turbo-C++.

Я хочу использовать две функции. Первой функцией будет функция main, которая может принимать ввод с клавиатуры или вызывать delay функция от dos.h, чтобы временно остановить нормальное функционирование main().

Вторая функция обрабатывает ввод мыши:

void mouse()
 {
    union REGS in,out;
    in.x.ax=1; // Show mouse pointer
    int86(0x33,&in,&out); //interrupt call
    while(1)
     {
       //print the location whenever it changes (not required)
     }
 }

person Son of Stackoverflow    schedule 07.09.2019    source источник
comment
Ваши возможности увеличатся, если вы перейдете на текущий компилятор. Сообщество Microsoft msvc бесплатное. Скорее всего, вы можете делать то, что вам нужно, с потоками.   -  person EvilTeach    schedule 07.09.2019
comment
Хотел бы я, чтобы у меня была такая возможность. @EvilTeach   -  person Son of Stackoverflow    schedule 07.09.2019
comment
У меня был другой вопрос... Почему обобщенные вопросы не принимаются в SO? Чтобы другим было выгодно...   -  person Son of Stackoverflow    schedule 07.09.2019
comment
получить одновременный ввод с мыши и клавиатуры довольно далеко от параллельного запуска двух функций. Первый, вероятно, требует использования некоторого специфичного для платформы API.   -  person user7860670    schedule 07.09.2019
comment
Не могли бы вы предоставить решение в виде ответа?   -  person Son of Stackoverflow    schedule 07.09.2019
comment
Может ли kbhit() из conio.h решить проблему?   -  person Son of Stackoverflow    schedule 07.09.2019
comment
На какой операционной системе (если есть) и оборудовании будет работать ваша программа?   -  person Scott McPeak    schedule 07.09.2019
comment
@Скотт МакПик Windows   -  person Son of Stackoverflow    schedule 07.09.2019
comment
Какая версия виндовс? Это 16-битная программа или 32-битная?   -  person Scott McPeak    schedule 07.09.2019
comment
Извините, это 32-битная версия x86.   -  person Son of Stackoverflow    schedule 07.09.2019
comment
Это программа, работающая на 32-битном (x86) эмуляторе, который находится в 64-битной ОС.   -  person Son of Stackoverflow    schedule 07.09.2019
comment
@н.м. Я сомневаюсь, что сарказм разрешен в SO   -  person Son of Stackoverflow    schedule 07.09.2019
comment
Таким образом, универсальным ответом на все вопросы по SO может быть Прекращение кодирования.   -  person Son of Stackoverflow    schedule 07.09.2019
comment
@н.м. Ничего подобного ... Я просто имел в виду, что этот комментарий не решит мой ответ.   -  person Son of Stackoverflow    schedule 07.09.2019
comment
Давайте продолжим это обсуждение в чате.   -  person Son of Stackoverflow    schedule 07.09.2019


Ответы (2)


Контекст

Если я правильно понял вопрос, вы пишете программу, которая будет работать под 16-битной MS-DOS, внутри DosBox. Ожидается, что эта программа будет реагировать как на ввод с помощью мыши, так и на клавиатуру. Он также может захотеть выполнить некоторые вычисления во время ожидания ввода.

Опрос

Самое простое и прямолинейное решение — использовать опрос, то есть вы сидите в цикле, спрашивая клавиатуру и мышь, есть ли у них новый ввод для ответа. В псевдокоде:

  while (true) {
    while (keyboard_has_activity()) {
      process_keyboard_input();
    }
    while (mouse_has_activity()) {
      process_mouse_input();
    }
    do_other_computation_for_a_short_time();
  }

Как написать keyboard_has_activity? Вы упомянули kbhit от conio.h в комментарии; это должно работать. Вы также можете использовать прерывания более низкого уровня (хотя я не знаю причин не использовать kbhit).

Примечание. process_keyboard_input следует читать только то количество символов, которое доступно в данный момент. Если ваша программа предполагает ожидание нажатия пользователем Enter, то вам придется хранить введенные символы (скажем) в массиве до тех пор, пока вы действительно не увидите клавишу Enter, а затем обработать весь ввод сразу.

Как написать mouse_has_activity? Насколько мне известно, для запросите текущее состояние мыши и сравните его с тем, что было при последнем вызове.

Как написать do_other_computation_for_a_short_time? Вам нужно будет разработать какой-то временной интервал в алгоритме. Например, если вы пишете шахматный движок, он будет проверять часы после каждой (скажем) оценки доски и останавливаться при необходимости, чтобы вы могли опросить ввод. Когда алгоритм останавливается, он должен запомнить в структуре данных, где он был, чтобы позже возобновить работу с этой точки. Одной из распространенных стратегий является ведение рабочего списка: списка всех частей вычислений, которые еще необходимо выполнить. Это форма совместной многозадачности.

В любом случае вы хотите, чтобы время было не более 10 мс, иначе вы можете пропустить щелчки мышью (пользователь может нажать и отпустить кнопку, прежде чем вы это заметите).

Это решение простое, но не обязательно самое эффективное, и потенциально ненадежное из-за вышеупомянутой проблемы с пропущенными щелчками мыши, если ограничение по времени слишком велико.

прерывания

Другой способ сделать это — подключиться к низкоуровневым прерываниям клавиатуры и мыши. Таким образом, вы устанавливаете код, который запускается только при прикосновении к устройству ввода, что более эффективно. Однако также намного сделать это правильно по ряду причин, в том числе из-за того, что у вас мало контроля над тем, что делает тот или иной фрагмент кода, когда он прерывается.

Отсутствие ответа: многопоточность

В этой среде нецелесообразно пытаться организовать вашу программу как два потока (мышь и клавиатура) с двумя функциями, работающими одновременно. В DOS нет средств для работы с потоками, и я не знаю, как добавить их, не переписывая ОС. Вместо этого вам нужно будет делать все из одного потока управления.

person Scott McPeak    schedule 07.09.2019
comment
Что делать, если действие мыши предшествует действию клавиатуры? - person Son of Stackoverflow; 07.09.2019
comment
Я хочу, чтобы оба запускались одновременно.. если возможно - person Son of Stackoverflow; 07.09.2019
comment
Нет проблем, если действие мыши происходит первым из-за внешнего цикла. Вычисление должно выполняться, скажем, 10 мс, поэтому программа вскоре снова проверит оба источника ввода. Почему вы хотите запустить их одновременно? Какую проблему это призвано решить? - person Scott McPeak; 07.09.2019
comment
Спасибо за ответ и поддержку. - person Son of Stackoverflow; 07.09.2019
comment
Что, если я хочу, чтобы операция возобновилась с того места, где она была прервана? - person Son of Stackoverflow; 07.09.2019
comment
do_other_computation_for_a_short_time(); == {i++;задержка(700);i++;задержка(200);i=100;} - person Son of Stackoverflow; 07.09.2019
comment
Я отредактировал свой пост, упомянув об использовании рабочего списка на этапе вычислений. Если вам нужны дополнительные рекомендации по разработке алгоритма, который можно остановить и возобновить, вы можете задать новый вопрос и предоставить подробную информацию о том, что именно делает ваш алгоритм. - person Scott McPeak; 07.09.2019
comment
Можем ли мы что-то сделать с прерываниями? Возможно, получить позицию/координаты при щелчке мыши и выполнить определенный набор инструкций. - person Son of Stackoverflow; 07.09.2019
comment
Да, и мой ответ ссылается на ресурс, который вы могли бы использовать в качестве отправной точки. Я думаю, этот подход покажется вам гораздо более сложным, но его, безусловно, можно заставить работать. - person Scott McPeak; 07.09.2019

Вы говорите в комментариях, что пишете код для Windows. У Microsoft есть функция ReadConsoleInput(), которая считывает ввод с клавиатуры и мыши в консольное окно. См. Чтение событий входного буфера в MSDN.

Например:

#include <windows.h>

int main()
{
    HANDLE hStdIn;
    INPUT_RECORD input[128];
    DWORD dwOldMode, dwNumRead;

    hStdIn = GetStdHandle(STD_INPUT_HANDLE);

    GetConsoleMode(hStdIn, &dwOldMode);
    SetConsoleMode(hStdIn, ENABLE_MOUSE_INPUT);

    while (ReadConsoleInput(hStdIn, input, 128, &dwNumRead))
    {
        for (DWORD i = 0; i < dwNumRead; ++i)
        {
            switch (input[i].EventType)
            {
                case KEY_EVENT:
                    // process input[i].Event.KeyEvent data as needed...
                    break;

                case MOUSE_EVENT:
                    // process input[i].Event.MouseEvent data as needed...
                    break;
            }
        } 
    }

    SetConsoleMode(hStdIn, dwOldMode);
    return 0;
}
person Remy Lebeau    schedule 07.09.2019
comment
утверждать(IDE==TURBOC++); // истинный - person Son of Stackoverflow; 07.09.2019
comment
Чтобы реализовать это решение, мне придется задать еще один вопрос о том, как включить «windows.h» в Turbo C++. - person Son of Stackoverflow; 07.09.2019
comment
@SonofStackoverflow IIRC TurboC++ только 16-битный и MS-DOS ... так что вы будете ограничены Win3x (и юридическими проблемами). Я сомневаюсь, что вы могли бы запустить какие-либо другие окна в DOSBOX, даже 3.11 - это натяжка. для достижения многозадачности вы можете использовать подпрограмму службы прерывания PIT, но перемежение, как в принятом ответе, было более распространенным и простым в реализации... - person Spektre; 09.09.2019