Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.12.2017, 15:04   #1
DmitryCREDO
Новичок
Джуниор
 
Регистрация: 21.12.2017
Сообщений: 2
По умолчанию Выполнение действия по событию

Доброго времени суток!
Я новичок в C#. Пытаюсь реализовать маленькие проектики, которые сам же и придумываю, чтобы набраться опыта. Сейчас хочу реализовать программку - триггер бот и столкнулся с проблемой. Прошу помощи!

Суть программы:
  • Программа должна постоянно мониторить значение цвета пикселя с дисплея. Когда значение цвета пикселя дисплея становится определенным ("==" сравнение), то выполнять действие, на пример нажатие на левую кнопку мыши.
  • Программа должна работать в неактивном состоянии, то есть если я под указанный пиксель подведу картинку, и тот пиксель получит значение цвета прописанное хардкодом в проверку, то выполнится действие.
Уже реализовал:
  • Оболочку программы:
    - Простая форма с двумя кнопками - "старт", "стоп".
    - После запуска программы, кнопка "старт" активна, а кнопка "стоп" неактивна.
    - При нажатии на активную кнопку, вторая кнопка становится активной, а нажатая неактивной.
  • Часть кода самой задачи:
    - Объявил переменную, которой присвоил значение цвета конкретного пикселя.
Проблема:
Я не знаю какой подход будет правильным в реализации этой задачи.
Пробовал просто банально в метод прописать бесконечный цикл:
Код:
while (true)
{
     Цвет = ЦветПикселяN;
     if (Цвет == НеобходимыйЦвет)
     {
           Выполнить нажатие на левую кнопку мыши;
     }
}
В результате чего у меня просто зависала программа.
Пробовал так же в конце метода вызывать его повторно, результат тот же.

Что я хочу от вас ?:
Прошу помочь выбрать правильный путь и решение это задачи. Расскажите что правильно использовать для решения такой задачи? Так же хотел бы увидеть наброски кода. Как сделать эту задачу максимально простой - максимально ресурсоёмкой.

И давайте упростим задачу, чтобы было легче разобраться в проблеме:
- На форму добавим текст бокс, в который просто будем записывать цвет пикселя (Это я могу сделать).
- И задачей будет: Мониторинг в реальном времени, то есть как только будет изменяться цвет пикселя (например под пиксель подведут картинку), так сразу в текст боксе будет меняться текст.
DmitryCREDO вне форума Ответить с цитированием
Старый 21.12.2017, 23:10   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,520
По умолчанию

Забудьте такую вещь как реальное время, когда работаете в винде. Кратковременное изменение пикселя всегда можете прозевать, такова особенность ОС. Можно конечно посмотреть, например, в сторону создания драйвера монитора и в нём цвет ловить, но тут явно не тот случай.
Можно по таймеру проверять пиксель. Типа примерно раз в мс проверяется пиксель.
Или же вынести в отдельный поток свой бесконечный цикл, чтобы программа не "зависала".
Или на async/await написать бесконечный цикл и не возиться вручную с потоками.
pu4koff вне форума Ответить с цитированием
Старый 22.12.2017, 00:03   #3
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от DmitryCREDO Посмотреть сообщение
В результате чего у меня просто зависала программа.
Видимо потому что вы выполняли это в основном (UI) потоке, вот он и не смог обрабатывать сообщения и обновлять UI.
Либо создавайте новый поток (Task, BackgroundWorker, Thread, ...), либо используйте таймер.

Если поток, то стоит добавить например небольшой Sleep в цикл, чтобы не грузить процессор зря.
https://en.wikipedia.org/wiki/Busy_waiting
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 22.12.2017, 13:32   #4
DmitryCREDO
Новичок
Джуниор
 
Регистрация: 21.12.2017
Сообщений: 2
По умолчанию

Спасибо большое! Понял свою ошибку. Действительно, проблема была в том, что я выполнял этот бесконечный цикл в основном (UI) потоке. Получается, что все вычисления желательно выполнять вне потока, в котором обрабатывается UI, так? Или, как минимум, выносить хотя бы тяжёлые вычисления за этот поток?

Теперь появилась еще одна загвоздка:
Программа отрабатывает правильно, подумал, что осталось только немного оптимизировать и по мелочи добавить функционал такого рода как "Запуск по нажатию клавиши.., стоп по нажатию клавиши..", но не тут то было!
Проблема заключается в выполнении клика мыши. В винде, на Windows Forms клик отрабатывает, а вот в игре не воспринимается.. Игра открыта в оконном режиме, цвет пикселя фиксируется правильно и проверка отрабатывает, проблема именно в клике левой кнопки мыши.
Сейчас клик реализован так:

Код:
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

[Flags]
public enum MouseEventFlags
{
    LEFTDOWN = 0x00000002,
    LEFTUP = 0x00000004,
    MIDDLEDOWN = 0x00000020,
    MIDDLEUP = 0x00000040,
    MOVE = 0x00000001,
    ABSOLUTE = 0x00008000,
    RIGHTDOWN = 0x00000008,
    RIGHTUP = 0x00000010
}

public void TriggerBot()
{
    LeftClick();
}

public static void LeftClick()
{
    mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
    mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
}
Есть альтернативные способы попробовать?

Последний раз редактировалось DmitryCREDO; 22.12.2017 в 13:51.
DmitryCREDO вне форума Ответить с цитированием
Старый 22.12.2017, 22:51   #5
vaDS
Пользователь
 
Регистрация: 16.04.2017
Сообщений: 94
По умолчанию

DmitryCREDO, Application.DoEvents() вам в помощь: этой командой вы говорИте "винде", что ваши действия или расчеты могут занять много машинного времени. - и на это не нужно обращать оной внимания.
Пусть работает, как работает(Винда).

Можете эту команду объявить перед "серьезным" циклом, который проц грузит по-полной, перед опросом COM-портов, прочее.
(Это чтоб не зависало).

>>Прошу помочь выбрать правильный путь и решение это задачи. Расскажите что правильно использовать для решения такой задачи? Так же хотел бы увидеть наброски кода. Как сделать эту задачу максимально простой
- максимально ресурсоёмкой.
Может быть, минимально ресурсоёмкой?

Последний раз редактировалось vaDS; 22.12.2017 в 22:57.
vaDS вне форума Ответить с цитированием
Старый 22.12.2017, 23:10   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от vaDS Посмотреть сообщение
этой командой вы говорИте "винде", что ваши действия или расчеты могут занять много машинного времени. - и на это не нужно обращать оной внимания.
Нет, винда и время тут не причем. И вы говорите, что надо обработать сообщения в очереди.
Со всеми последствиями этого. Например возможностью снова нажать кнопку запускающую этот цикл. Или закрыть окно (при этом цикл продолжит работать).
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 22.12.2017 в 23:12.
Alex11223 вне форума Ответить с цитированием
Старый 22.12.2017, 23:46   #7
vaDS
Пользователь
 
Регистрация: 16.04.2017
Сообщений: 94
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Нет, винда и время тут не причем. И вы говорите, что надо обработать сообщения в очереди.
Со всеми последствиями этого. Например возможностью снова нажать кнопку запускающую этот цикл. Или закрыть окно (при этом цикл продолжит работать).
Таки, брат, этой командой мы говорим Винде, что не нужно говорить нам что "Программа не отвечает" в Диспетчере, а она занимается расчетами, которые нам нужны. И мы говорим Винде, что "занимайся своими делами", а мы тут просто расчитываем то что нам нужно.

Alex11223, Вы ж программируете на VB6 и на VB.NET, неужели никогда не сталкивались с DoEvents()?

Последний раз редактировалось vaDS; 22.12.2017 в 23:50.
vaDS вне форума Ответить с цитированием
Старый 23.12.2017, 00:07   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Причем тут винда? Вы читали мое сообщение? Я говорю, что этот метод просто обрабатывает сообщения в очереди. Можете в документации посмотреть если не верите.

И да, на VB я никогда не писал.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 23.12.2017, 00:24   #9
vaDS
Пользователь
 
Регистрация: 16.04.2017
Сообщений: 94
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Причем тут винда? Вы читали мое сообщение? Я говорю, что этот метод просто обрабатывает сообщения в очереди. Можете в документации посмотреть если не верите.

И да, на VB я никогда не писал.
Извините, спутал вас с "Alex111223" или типа Ник есть, бывает, извините.
Этот метод говорит ОС(Винде) что мы грубо говоря "ЗатормОзим систему", но ты, Система, продолжай свои действия, и не обращай внимания на нас.

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Я говорю, что этот метод просто обрабатывает сообщения в очереди.
Нет, эта функция говорит что "здесь будут сложные расчеты", и что не нужно меня в очередь записывать на обработку(я буду тупо и долго считать) в вашей терминологии. А вы со своими задачами можете становиться в очередь или как вы там поступаете.

Последний раз редактировалось vaDS; 23.12.2017 в 00:33.
vaDS вне форума Ответить с цитированием
Старый 23.12.2017, 00:43   #10
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Вы документации не верите?
https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
Цитата:
Processes all Windows messages currently in the message queue.

......

When you run a Windows Form, it creates the new form, which then waits for events to handle. Each time the form handles an event, it processes all the code associated with that event. All other events wait in the queue. While your code handles the event, your application does not respond. For example, the window does not repaint if another window is dragged on top.

If you call DoEvents in your code, your application can handle the other events.

......

Caution

Calling this method causes the current thread to be suspended while all waiting window messages are processed. If a message causes an event to be triggered, then other areas of your application code may execute. This can cause your application to exhibit unexpected behaviors that are difficult to debug. If you perform operations or computations that take a long time, it is often preferable to perform those operations on a new thread.
Цитата:
Сообщение от vaDS Посмотреть сообщение
Можете эту команду объявить перед "серьезным" циклом
Сами-то пробовали?
Код:
        private void button1_Click(object sender, EventArgs e)
        {
            Application.DoEvents();
            while (true)
            {
            }
        }
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Выполнение действия через промежуток времени chingiz Общие вопросы Delphi 37 03.10.2012 11:33
Выполнение действия над другими прогами. webprogrammer Помощь студентам 2 24.03.2012 22:01
Символ и выполнение действия grafgrial Общие вопросы Delphi 5 27.12.2011 15:00
Выполнение действия с компонентами в цикле Ermiss Общие вопросы Delphi 4 01.11.2007 23:54
Выполнение действия в заданное время WOWan234 Помощь студентам 6 02.05.2007 01:52