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

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

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 14.10.2009, 04:31   #1
Hintman
Пользователь
 
Регистрация: 14.04.2007
Сообщений: 28
По умолчанию Как дождаться завершения процедуры?

Есть процедура, которая многократно выполняется в головной программе:
Код:
procedure mEmDmU(i,j: Cardinal);
begin

SetCursorPos(i,j);
Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);

end;
Проблема в том, что при многократных вызовах иногда не успевают обработаться или вовсе не обрабатываются процедуры SetCursorPos, Mouse_Event.
Помогает вставка процедуры Sleep(X), но на разных компьютерах и при разной загрузке процессора это X может быть меньше или больше, а время работы программы очень нужно сократить, и минимальное оптимальное X неизвестно.

Application.ProcessMessages - не помогает.

5 часов копался в интернете, так и не понял. Запутался в этих процедурах WaitForInputIdle, SleepEx, WaitForSingleObject, GetQueueStatus и т.д. Что же здесь может помочь, чтобы заставить эти процедуры выполняться последовательно, без неразберихи? И неужели без потоков решить проблему не удастся? Это что же, на каждый Mouse_Event теперь поток создавать?
Hintman вне форума Ответить с цитированием
Старый 14.10.2009, 13:13   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Application.ProcessMessages
оно и не должно помочь если сообщения идут не вашему окну.

вообще если вы такие процедуры многократно юзаете, то стоит помоему сначало разобратся в том как винда работает...а именно я говори про сообщения.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 14.10.2009, 13:53   #3
Hintman
Пользователь
 
Регистрация: 14.04.2007
Сообщений: 28
По умолчанию

Ага, как видно из кода, сообщения идут не нашему окну.

Вот предположим мы вызываем эту процедуру, в которой выполняется код:
Код:
SetCursorPos(i,j);
Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
И иногда получается так, что курсор еще переместиться не успел (SetCursorPos), а кнопка мыши уже нажалась (т.е. сработало Mouse_Event до того, как полностью завершилось SetCursorPos). Что призвано помочь в этой и им подобных ситуациях?

Может проверять позицию курсора после вызова SetCursorPos(i,j)? Например, вот так:
Код:
repeat
GetCursorPos(PT);
until ((i<>PT.X) or (j<>PT.Y))
И каким-то образом определять положение кнопки мыши (нажата, отпущена) после каждого вызова Mouse_Event? Это вообще может помочь?

Как заставить любую процедуру, любой код, будь то SetCursorPos, Mouse_Event или любая другая процедура отработать полностью до конца, не передавая дальнейшее управление программе, т.е. не выполняя дальнейший код, пока процедура полностью не отработает?
Hintman вне форума Ответить с цитированием
Старый 14.10.2009, 14:01   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

А что ты хочешь сделать в принципе?
Почему именно этот способ?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.10.2009, 14:34   #5
Hintman
Пользователь
 
Регистрация: 14.04.2007
Сообщений: 28
По умолчанию

Мне не важен способ, мне главное чтобы не нарушалась последовательность выполнения кода...

Программа должна перемещать курсор в определенную область экрана и делать там нажатие кнопки мыши, затем перемещать в другую область и нажимать там. Каким способом это реализовать мне не важно, главное лишь безошибочность работы и быстродействие. Дело в том, что в настоящий момент есть проблема: как я уже сказал, не успевает еще завершиться обработчик первого вызова процедуры SetCursorPos или Mouse_Event, как уже вызывается следующий.

Приведу код полностью:
Код:
    for i:=0 to 6 do begin
      mEmDmU(h_rect.Left+088+36*i,h_rect.Top+145+j);
      mEmDmU(h_rect.Left+504+36*i,h_rect.Top+145+j);
      mEmDmU(h_rect.Left+088+36*i,h_rect.Top+145+j);
      mEmDmU(h_rect.Left+088+36*i,h_rect.Top+145+j);
      mEmDmU(h_rect.Left+088+36*i,h_rect.Top+145+j);
      end;
Как видим, здесь идет многократный вызов процедуры mEmDmU. Вот она

Код:
procedure mEmDmU(i,j: Cardinal);
begin
SetCursorPos(i,j);
Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);
end;
Ну а когда программу запускаем, перемещения и кликанье мышью начинает срабатывать не в том порядке, как должны бы. На лицо тот факт, что не успевают завершаться обработчики процедур Mouse_Event, вызванных ранее, как происходит новый вызов.

Устроит любое, желательно конечно же простое решение.

Простановка Sleep(10) после каждого вызова Mouse_Event помогает, в этом случае уже практически не возникает сбоя в порядке перемещений мыши. Но 10 мс не всегда достаточно. Можно ставить 15. Но и этой задержки может не хватить для корректного срабатывания программы. И не красивый этот способ. Да к тому же еще и длительный по времени.

Прошу, помогите...
Hintman вне форума Ответить с цитированием
Старый 14.10.2009, 14:38   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Программа должна перемещать курсор в определенную область экрана и делать там нажатие кнопки мыши, затем перемещать в другую область и нажимать там.
А не проще посылать сообщения о нажатии мышки окну по тем координатам не двигая курсор физически?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.10.2009, 14:46   #7
Hintman
Пользователь
 
Регистрация: 14.04.2007
Сообщений: 28
По умолчанию

Помогло! Большое спасибо! Пока что работает. При этом оказалось достаточно использования Sleep(0). Пока вопросов больше нет.
Код:
procedure mEmDmU(i,j: Cardinal);
var
lp: Integer;

begin
  lp:=i or j shl 16; //as MakeLParam
  SendMessage(H,WM_MOUSEMOVE,  0,lp);
  SendMessage(H,WM_LBUTTONDOWN,0,lp);
  SendMessage(H,WM_LBUTTONUP,  0,lp);
  Sleep(0);
  end;

Последний раз редактировалось Hintman; 14.10.2009 в 15:23.
Hintman вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ожидание завершения потоков Voody Общие вопросы Delphi 11 14.06.2016 06:10
Как программно вызвать окно завершения работы UfoRoot Win Api 4 21.01.2009 11:15
Перехват завершения работы ОС vynt Win Api 7 19.05.2008 08:59
Ждать завершения чужого процесса ERASERROR Win Api 2 04.02.2008 08:23
Как запустить приложение, дождаться его исполнения и только потом выполнять код? il76 Win Api 6 19.07.2007 14:00