Te "sygnały" to są właśnie komunikaty
(na komunikatach system leży)... Wysyłasz w Timer'ze całą masę komunikatów, nie wszystkie są wykonywane natychmiast, gdyż system nie nadąża je wykonywać, więc trafiają na kolejkę komunikatów. System potem przetwarza tą kolejkę z opóźnieniem. Niektóre komunikaty z kolejki z różnych przyczyn mogą być już nieaktualne, więc zostają pominięte przez system. Wprowadzenie opóźnienie za pomocą funkcji Sleep daje czas systemowi na przetworzenie otrzymanych komunikatów nim nadejdą nowe. Funkcja Sleep ma jednak tą wadę, że zamraża aplikację.
Arnold_S napisał(a):Problem w tym, że Interval w Timerze nie może mieć więcej niż 750ms.
Ależ jak najbardziej może być dłuższy. Chyba, że ty ustaliłeś sobie limit na 750.
Arnold_S napisał(a):Wychodzi na to, że czas wykonania funkcji umieszczonej w timerze jest dłuższy niż mogę przeznaczyć na Interval.
Czas ich wykonywania wcale nie musi być dłuższy. Jak już napisałem, komunikaty trafiają do kolejki i system przetwarza je po kolei. Problem w tym, że system musi przetworzyć całą masę komunikatów, nie tylko tych pochodzących z twojej aplikacji, więc je kolejkuje. Gdy dotrze do komunikatu wysłanego przez twoją aplikację, może się okazać, że jest on już nieaktualny lub z innych przyczyn nie można go już wykonać, gdyż np.aplikacja do której go wysyłasz nie może go przyjąć.
Wysyłasz komunikaty do kolejki nie czekając na to czy zostały przetworzone. Dla przykładu funkcja SendMessage wywołuje procedurę okna dla określonego okna i nie wraca, dopóki procedura okna nie przetworzy komunikatu.
Kolejna rzecz to pętla wewnątrz zdarzenia OnTimer wprowadza dodatkowe opóźnienie. Czy próbowałeś funkcję ProcessMessages, by odświeżać kolejkę komunikatów? Spróbuj właśnie ProcessMessages zamiast Sleep, dasz czas na przetworzenie komunikatów oczekujących w kolejce.
Ten Sleep może być jednak konieczny. Mam klawiaturę z programowalnymi dodatkowymi klawiszami. Mogę im przypisać makro zawierające kombinację nawet kilkudziesięciu klawiszy, by wykonywały się po kolei. I muszę wprowadzać opóźnienia by to zadziałało, ale nie wywołuję tego makra z częstotliwością ¾ sekundy.
Problem leży w tym, że system nie przetworzy odpowiednio szybko takiej kolejki komunikatów i część komunikatów odrzuci.
Czy istnieje jakiś sposób aby na funkcji SendInput wymusić nie wysyłanie następnego "sygnału" litery/znaku do puki ten wcześniejszy nie został odebrany przez okno.
Użyj funkcji SendMessage, ta funkcja wraca dopiero gdy komunikat zostanie przetworzony. Nie wiem jednak czy to rozwiąże twój problem, gdyż częstotliwość komunikatów spadnie, czyli będą wysyłane z mniejszą częstotliwością. Podobny efekt osiągniesz zmniejszając częstotliwość zegara Timer.
SendInput łatwo może zostać zablokowana przez inny wątek. Możesz jednak przecież sprawdzać, czy komunikat doszedł czy nie. Przecież funkcja zwraca 0 jeżeli została zablokowana przez inny wątek, wtedy możesz ponownie wysłać komunikat, aż do skutku, czyli aż dojdzie. To jedyny sposób na sprawdzenie, czy komunikat doszedł.
//wyslanie do okna slowa "qwertyui "
for(int i = 0 ; i < 8 ; i++)
{
do
{
aaa.ki.wScan = slowo[i];
aaa.ki.dwFlags = KEYEVENTF_SCANCODE; //wcisniecie klawisza
}
while( SendInput(1, &aaa, sizeof(INPUT) == 0);
Application->ProcessMessages();
do
{
aaa.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; //podniesienie klawisza
}
while(SendInput(1, &aaa, sizeof(INPUT) == 0);
}
W podanym przykładzie funkcja SendInput będzie wysyłać komunikaty o tej samej wartości tak długo jak długo funkcja zwraca wartość 0. Jeżeli komunikat dojdzie, funkcja zwróci wartość różną od 0 i przejdzie do następnego bloku kodu. Pętla for jest w tym czasie wstrzymywana. Dodałem ProcessMessages by możliwe było wykonania komunikatów po każdym obiegu pętli, a nie gdy pętla zakończy działanie. Pętle wstrzymują zegar, więc interwał będzie ulegał wydłużeniu, jeżeli komunikaty nie będą dochodziły.