Russian Qt Forum
Июнь 11, 2024, 09:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] mouse_event застревает  (Прочитано 7137 раз)
Alatey
Гость
« : Май 30, 2012, 18:09 »

Здравствуйте уважаемые форумчане Улыбающийся. У меня нетривиальный случай.

Пишу клиент-серверное приложение для удалённого управления рабочим столом.
Эмулирую нажатие мыши с помощью mouse_event:
Код:
#include <windows.h>
typedef void (*ME)(__in DWORD dwFlags, __in DWORD dx, __in DWORD dy, __in DWORD dwData, __in ULONG_PTR dwExtraInfo);
...
QLibrary myLib("user32.dll");
ME me= (ME)myLib.resolve("mouse_event");
me(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
me(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
// mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); <- так выдаёт ошибку компиляции.
Тестирую на VmVare. Всё работает... пока эмулированно не нажмёшь кнопку "свернуть окно" своего приложения, после чего на процедуре "me(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);" приложение "зависает" пока вручную не "отожмёшь" мышку (MOUSEEVENTF_LEFTUP), после чего приложение "отмерзает" и работает нормально. Как это преодолеть?

Хотел выкрутиться: вызывать "me(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);" из другого потока, чтобы основной поток не "зависал". Но так процедура не вызывается - выдаёт ошибку.
Код:
class DownMouseButtonThread : public QThread
{
    Q_OBJECT
public:
    DownMouseButtonThread()
{
     moveToThread(this);
    this->myLib = new QLibrary("user32.dll");
    this->me = (ME)this->myLib->resolve("mouse_event");
}
    ~DownMouseButtonThread() { delete this->myLib; }

    void run() { this->exec(); }

// вызываем из главного потока после me(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
// убеждаемся, что "зависшее" зажимание "отвисло" после отпускания, которое вызвано из главного потока
    void WaitOnButtonDown() { this->sem.acquire(); }

public slots:
    void onSetButtonDown()
{ // зажимаем мышь в этом потоке
    this->me(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); // здесь ошибка выполнения
    this->sem.release();
}

private:
    QSemaphore sem;
    QLibrary *myLib;
    ME me;
};
« Последнее редактирование: Июнь 01, 2012, 02:25 от Alatey » Записан
Bepec
Гость
« Ответ #1 : Май 30, 2012, 18:28 »

Хм. Вроде я отписывался уже тут, однако сообщенька потерялась видимо.

Вопрос - зачем ты извращаясь подгружаешь user32dll???
Инклудь windows.h и не парься с функциями.
Записан
Alatey
Гость
« Ответ #2 : Май 30, 2012, 19:37 »

чё-то не пойму куда писать. И там - не там и там -не там .... В qt-форуме нет раздела Win32API.
Уже подключил:
Код:
#include <windows.h>
#pragma comment (lib, "user32.lib")

И... блин... заработало (с моим потоком-выкрутасом) Улыбающийся Весьма Вам благодарен "Bepec" !!!! Целующий

Записан
Bepec
Гость
« Ответ #3 : Май 30, 2012, 19:40 »

В заголовке темы допиши [РЕШЕНО].
Всегда пожалуйста, за ваши деньги любой каприз Подмигивающий
Записан
Alatey
Гость
« Ответ #4 : Май 30, 2012, 20:13 »

Один раз заработало, а потом перестало, но это что-то с потоком.
Записан
Bepec
Гость
« Ответ #5 : Май 30, 2012, 20:23 »

Сделайте простой пример потока. Который допустим будет надпись изменять.
И сделайте простой пример, который двигает мышкой. Без потока Подмигивающий

И вот вы поймаете бага. Убейте бага. Веселый
Записан
Alatey
Гость
« Ответ #6 : Май 30, 2012, 23:21 »

Поток переписал, но приложение всё равно застревает.
Код:
class DownMouseButtonThread : public QThread
{
    Q_OBJECT
public:
    DownMouseButtonThread() { moveToThread(this); }
    void run()
{
   do
    {
        this->OnCommandSem.acquire();
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); // !!! застревает здесь !!!
        this->sem.release();
    }
    while(true);
}

    void SetButtonDown() { this->OnCommandSem.release(); }

    // убеждаемся, что "зависшее" зажимание "отвисло" после отпускания, которое вызвано из главного потока
    void WaitOnButtonDown() { this->sem.acquire(); }

private:
    QSemaphore sem;
    QSemaphore OnCommandSem;
};
...
// создаём поток
DownMouseButtonThread DownMouseButtonThread;
DownMouseButtonThread.start();
...
// при зажатии кнопки мыши
DownMouseButtonThread.SetButtonDown();
...
// при отжатии кнопки
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
DownMouseButtonThread.WaitOnButtonDown();
Моё мнение одно из двух:
1. нажатие на системную кнопку окна способно останавливает выполнение всех потоков приложения. Но не всегда (не могу пока уловить такие условия).
2. зажатие кнопки в потоке не отвисает, даже когда в главном потоке кнопка уже отжата. (что маловероятно)

Вижу 2 выхода:
1. не использовать (скрыть) системные кнопки форм (свернуть, развернуть закрыть), в место них сделать соответствующие кнопки на самих формах.
2. перенести эмуляцию мыши в отдельное приложение, т.е. эмуляция мыши и интерфейс всегда должны быть в разных приложениях.
Записан
Bepec
Гость
« Ответ #7 : Май 31, 2012, 06:53 »

Кстати да, факт - windows при нажатии на системные кнопки окна, тормозит GUI приложения. Потоки же в это время вроде не тормозятся.

Счас проверю Улыбающийся

Потоки не тормозятся. Но если у тебя он работает синхронно с основным потоком, тогда да - капец до отжатия кнопачки Веселый
« Последнее редактирование: Май 31, 2012, 10:39 от Bepec » Записан
Alatey
Гость
« Ответ #8 : Май 31, 2012, 17:01 »

Сделал зажимание и отпускание в одном неосновном потоке - застревает Шокированный.
Мне кажется что при клике блокируется поток который "издаёт" клик, и тот поток который его принимает (основной). Т.е. эмуляция зажатия и отжатия должно происходить в разных потоках, при том не являющихся основными. Буду проверять эту версию.

ПС: Интересная закономерность: если время между зажатием и отпусканием относительно маленькое, то не застревает Смеющийся.
Записан
Bepec
Гость
« Ответ #9 : Май 31, 2012, 18:04 »

Я те по секрету скажу. Наверно у тебя где то потоки связаны. И основной поток блокирует дополнительный. Вот тебе и весь сказ, а не глюк.
Записан
Alatey
Гость
« Ответ #10 : Май 31, 2012, 19:49 »

да, вероятно так и есть, в главном потоке сокет принимает команды из сети. Теперь нужно перенести сокет в другой поток.

Проблема решена!
mouse_event всегда вызываю из одного неглавного потока.

ПС: меня запутало то, что команды эмуляции приходили через сокет, который блокировался в главном потоке и команда отпускания миши не поступала. Поэтому сокет теперь выполняется в неглавном потоке.
Верес был прав Смеющийся
« Последнее редактирование: Июнь 01, 2012, 02:25 от Alatey » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.059 секунд. Запросов: 17.