• 0
Авторизация  
neo

Проблемы с хуком WH_KEYBOARD_LL + PeekMessage/GetMessage

Вопросы

Ребята здарова!
выручайте) весь уже измучился =( не получается =(

Тема такая, работаю с хуком, использую WH_KEYBOARD_LL
тк нужно работать и с 32 битной и 64 битной разрядностью.
и вообще мне нравится с ним работать всё очень просто и удобно но появилось одно НО =(

WH_KEYBOARD_LL работает до добавления сообщения в очередь в контексте потока.

и это действительно так =(

дело в том что я через хук ловлю введённую информацию и потом обрабатываю это через
idHTTP (ищу в интернете ответ)... если сигнал хороший то всё круть... а когда связь не очень..
и происходят небольшие задержки..
как я понимаю в WH_KEYBOARD_LL складируются результаты которые он не может передать
и затем хук выбивается... тоесть чтобы всё вновь заработало нужно сделать так
 
KeyboardHandle:=SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);

и хук по прежнему работает до тех пор пока не вылетит вновь.

Чтобы решить эту проблему как я понял нужно использовать PeekMessage или GetMessage
и удалять излишки... Но в сети очень мало информации о том как ими пользоваться я не понимаю
куда и как их вставлять.
Я делал вот так... писал в ДЛЛке

function KeyboardHook(code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
msg:TMsg;
begin
 if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then exit;

 if code>=0 then
  begin
    if (wParam=WM_KEYDOWN) then
    begin

    SendMessage(FindWindow('TForm1', 'Form1'), KeyboardEvent, 0,PBDLLHOOKSTRUCT(lParam).vkCode);

    end;
  end;
  Result:=CallNextHookEx(KeyboardHandle, code, wParam, lParam)

end;
// if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then exit;
// типа если есть излишки выходи


так же вставлял там это:
    while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
    begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;

но не помогает =(

Может это где-то в ЕХЕшнике нужно вставлять? я не понимаю как с ним работать =(
Может кто на форуме знает? помогите пожалуйста ответом

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 ответа на этот вопрос

  • 0

PeekMessage - бессмысленно и даже вредно с флагом PM_REMOVE. Убрать.

SendMessage - эта функция отправляет данные окну и дожидается, пока окно их обработает. А хук ждать не должен, его задача - максимально быстро отработать. Заменить на PostMessage.

длл здесь не нужна. LL-хуки работают из любого места. Просто перенести весь код в exe.

 

Изменено пользователем kami

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
5 часов назад, kami сказал:

PeekMessage - бессмысленно и даже вредно с флагом PM_REMOVE. Убрать.

SendMessage - эта функция отправляет данные окну и дожидается, пока окно их обработает. А хук ждать не должен, его задача - максимально быстро отработать. Заменить на PostMessage.

длл здесь не нужна. LL-хуки работают из любого места. Просто перенести весь код в exe.

 

да уже пробовал в ехе делать но всё также...пост тоже пробовал но всё криво тогда работает... неправильно ответы приходят... там в любом случае должна быть небольшая синхронизации тк нужно дожидаться ответа от idHTTP

пробовал даже через таймер и отдельный поток но всё не так качественно работает как через SendMEssage... вот вроде решение этой проблемы на Си но я его не понимаю =(

#include "stdafx.h"
#include <windows.h>
     
LRESULT CALLBACK LLKeyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode <= 0)
    {
        if(wParam == WM_KEYDOWN)
            keybd_event( 0x41, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0 );
 
        return 1;
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
     
int main()
{
    HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, LLKeyProc, GetModuleHandle(NULL), 0);
    if(hook)
    {
        while(WaitMessage())
        {
            MSG msg = {0};
            while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                if(msg.message == WM_QUIT)
                {
                    UnhookWindowsHookEx(hook);
                    return 0;
                }
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
    return 0;
}

кстати Подскажите... а как узнать что
 KeyboardHandle:=SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0); - слетел?
я думал что хендл должен стать 0 но он не меняется =(

также я писал в основной функции lastError:=GetLastError;

но после того как она слетает lastError так и остаётся 0 =(
вот как получить код этой моей ошибки??? =( 

через try except тоже выявить ошибку не получается =(

так бы я на таймер просто повесил: если слетел -подгрузи снова

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
6 часов назад, neo сказал:

всё криво тогда работает

Исчерпывающее описание проблемы.

6 часов назад, neo сказал:

там в любом случае должна быть небольшая синхронизации тк нужно дожидаться ответа от idHTTP

Вам сама операционная система говорит - нельзя так делать, вы тормозите ВСЁ что только можно, в результате ваш хук признается вредоносным и исключается из цепочки. Но вы упорный...

Ждите ответа. Но в своем коде, а не в хуке. А в свой код передавайте данные асинхронно, через тот же postMessage

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Похожий контент

    • От notricky
      Интересует вопрос и ноу-хау.
      Если есть код на Питоне, который нужно выполнять в рамках Андроид и айОС приложений - как это лучше всего делать и как это будет выглядеть?
      Читал, что есть Python4Delphi и это речь про DLL. Хотелось бы понять, как это будет выглядеть на iOS и Android - это дополнительный файл надо с собой такскать как в Windows или он будет внутри APK/APP ?
    • От bigjorj
      Win32 приложение на Firemonkey
      Есть DLL написанная на C++. В ней есть экспортная функция.
      int getStatusFlags (int *fatalStatus, int *currentFlagsStatus, int *documentStatus); импортирую функцию следующим способом 
      function getStatusFlags (var fatalStatus, currentFlagsStatus, documentStatus:Integer):integer; stdcall; external DllName; В режиме компиляции Debug все идеально, но если откомпилировать в Release то приложение наглухо виснет при вызове функции.
      Подозреваю что я неправильно импортирую функцию и происходит неправильная работа с памятью. Пробовал менять тип передаваемых переменных на PInteger с передачей указателей, но все равно падает.
      Кто сталкивался. Помогите!
       
       
       
       
    • От ivadimos
      Есть какой-то базовый класс. Необходимо расширить его функционал и вынести во внешний модуль(плагин). Модуль необходимо подгружать динамически из папки. 
      Каким образом могу это реализовать? 
    • От dnekrasov
      Создаю глобальный hook на несколько событий:
      {$IFDEF MACOS} var EvtTap: CFMachPortRef; RunLoopSource: CFRunLoopSourceRef; {$ENDIF} ... procedure CreateGlobalHook; {$IFDEF MACOS} var EvtMask: UInt64; {$ENDIF} begin {$IFDEF MACOS} if EvtTap = nil then begin EvtMask := (1 shl kCGEventKeyDown) or (1 shl kCGEventFlagsChanged) or (1 shl kCGEventLeftMouseUp); EvtTap := CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, EvtMask, @EventTapHandler, nil); RunLoopSource := CFMachPortCreateRunLoopSource(kCFAllocatorDefault, EvtTap, 0); CFRunLoopAddSource(CFRunLoopGetCurrent, RunLoopSource, kCFRunLoopCommonModes); end; CGEventTapEnable(EvtTap, 1); {$ENDIF} end; function EventTapHandler(proxy: CGEventTapProxy; type_: CGEventType; event: CGEventRef; refcon: Pointer): CGEventRef; cdecl; {$IFDEF MACOS} var iKey: Integer; iType: Integer; {$ENDIF} begin {$IFDEF MACOS} Result := event; iType := CGEventGetType(event); iKey := CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); case iType of kCGEventFlagsChanged: ...; kCGEventLeftMouseUp: ...; kCGEventKeyDown: ...; end; {$ENDIF} end; При обработке события возникает проблема: приходят все события кроме kCGEventKeyDown В документации нашел, что kCGEventKeyDown и kCGEventKeyUp приходят только в том случае если приложение запущено от root-а или внесено в список "System Preferences->Security & Privacy->Privacy->Accessibility"
       
      Может кто знает как мне программно получить доступ к этим событиям?
    • От Pulsarius
      Привет всем!  
      Кто-нибудь уже заметил, что приложения для десктоп, скомпилированные в последней версии C++ Builder (RAD Studio 10 Seattle), стали зависеть от BORLNDMM.dll? В предыдущих версиях студии такого не было. Я знаю, что это Борландовская библиотека для работы с памятью, и от неё зависели программы, написанные на ранних версиях C++ Builder, ещё будучи при Борланде. Чем же интересно обосновано возвращение такой зависимости и можно ли как-нибудь от неё избавиться?   P.S. Я пишу DLL. Пробовал избавиться от зависимости, отключив в настройках проекта "Use 'classic' Borland compiler", т.е. чтобы использовать Clang. Пришлось немного отредактировать код. Зависимость исчезла, но, при выгрузке моей DLL в главной программе функцией FreeLibrary, вылетает ошибка типа access violation. Такая ошибка возникает только тогда, когда DLL скомпилирована в режиме Release, в режиме Debug всё работает нормально, и поэтому отследить в чём дело очень сложно. Когда возникает ошибка, при отладке главной программы, отладчик перебрасывает в окно дизассемблера, где вместо ассемблерных команд знаки вопроса. Т.е. такое ощущение, что при вызове функции FreeLibrary, в каком-то месте происходит "прыжок" на адрес в памяти, где нет никаких инструкций. Если скомпилировать DLL с использованием классического компилятора Borland, то и в режиме Debug, и в режиме Release всё работает нормально.
    • От Alexander616
      Помогите пожалуйста разобраться с кодом С#, в коде загружается dll и используются функции из неё, хочу перевести на дельфи.
       
      загрузка dll
      [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr opus_decoder_create(int Fs, int channels, out IntPtr error); [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] internal static extern void opus_decoder_destroy(IntPtr decoder); [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] internal static extern int opus_decode(IntPtr st, byte[] data, int len, byte[] pcm, int frame_size, int decode_fec); public static OpusDecoder Create(int outputSampleRate, int outputChannels) { if (outputSampleRate != 8000 && outputSampleRate != 12000 && outputSampleRate != 16000 && outputSampleRate != 24000 && outputSampleRate != 48000) throw new ArgumentOutOfRangeException("inputSamplingRate"); if (outputChannels != 1 && outputChannels != 2) throw new ArgumentOutOfRangeException("inputChannels"); IntPtr error; IntPtr decoder = API.opus_decoder_create(outputSampleRate, outputChannels, out error); if ((Errors)error != Errors.OK) { throw new Exception("Exception occured while creating decoder"); } return new OpusDecoder(decoder, outputSampleRate, outputChannels); } public unsafe byte[] Decode(byte[] inputOpusData, int dataLength, out int decodedLength) { if (disposed) throw new ObjectDisposedException("OpusDecoder"); byte[] decoded = new byte[MaxDataBytes]; int frameCount = FrameCount(MaxDataBytes); int length = 0; if (inputOpusData != null) length = API.opus_decode(_decoder, inputOpusData, dataLength, decoded, frameCount, 0); else length = API.opus_decode(_decoder, null, 0, decoded, frameCount, (ForwardErrorCorrection) ? 1 : 0); decodedLength = length * 2; if (length < 0) throw new Exception("Decoding failed - " + ((Errors)length).ToString()); return decoded; } private void button3_Click(object sender, EventArgs e) { OpusDecoder _dec= OpusDecoder.Create(48000, 1); byte[] segDec = new byte[4000]; byte[] seg = new byte[4000]; seg[0] = 8; seg[1] = 11; seg[2] = 230; seg[3] = 61; seg[4] = 36; seg[5] = 236; seg[6] = 195; seg[7] = 220; seg[8] = 192; int len = 9; segDec = _dec.Decode(seg, len, out len); } код на C# работает, но когда перевожу его на дельфи он начинает ругаться "stackoverflow"
       
      загрузка dll
      function opus_decoder_create(Fs:LongInt; channels:Integer; var Error:Integer):OpusDecoder; cdecl; external 'opus.dll'; function opus_decode(st:OpusDecoder; data:array of Byte; len:Integer;var pcm: array of Byte; frame_size: Integer; decode_fec:Integer):Integer; cdecl; external 'opus.dll'; procedure opus_decoder_destroy(st:OpusEncoder); cdecl; external 'opus.dll'; использование функций
      procedure TMain.Decode_2Click(Sender: TObject); var OPDecoder: OpusDecoder; Error: Integer; PreEnc:array of Byte; PreDec:array of Byte; begin Error := 0 ; OPDecoder := opus_decoder_create(48000, 1, Error); SetLength(PreEnc, 4000); SetLength(PreDec, 4000); PreEnc[0] := 8; PreEnc[1] := 11; PreEnc[2] := 230; PreEnc[3] := 61; PreEnc[4] := 36; PreEnc[5] := 236; PreEnc[6] := 195; PreEnc[7] := 220; PreEnc[8] := 192; Error := opus_decode(OPDecoder, PreEnc, 9, PreDec, 2000, 0); end; в процедуру dll ки значения подаются одинаковые в обеих случаях, никак не могу разобраться в чём дело.
    • От Morfi
      Всем доброго времени суток.
       
      Возможно ли описать и создать визуальные компоненты в dll, а отобразить их на форме (или, например на TLayout этой формы) приложения, использующего эту dll?
       
      Среда: Delphi XE7.
    • От Maximus
      Здравствуйте. Возникла следующая проблема. Создал dll библиотеку с формой FireMonkey. Из приложения на VCL подключаю библиотеку, вызываю функцию создания формы
      procedure CreateHD; begin   FormHD := TFormHD.Create(nil);   FormHD.Caption := 'HD';   FormHD.Show; end; форма создаётся, далее вызываю функцию закрытия и уничтожения формы FM
      procedure CloseHD; begin   FormHD.Close;   FreeAndNil(FormHD); end; Но при попытке выгрузить dll приложение зависает.
       
      Возможно уничтожение формы FM как-то отличается от VCL и нужно что-то вызвать ещё кроме FreeAndNil или проблема в другом?
       
      (dll и приложение написаны в Delphi XE6)
      Приложение.zip
    • От Ethernet
      Здравствуйте.
       
      Есть проблема, с которой не могу разобраться уже на протяжении какого-то времени.
       
      Суть проблемы.
      Создаю dll библиотеку и сую туда форму со своим функционалом (Delphi, RAD Studio XE5). Динамически подгружаю в приложение и по сути всё работает, но... Когда же я хочу выгрузить приложение я получаю, либо ряд ошибок AV, либо зависание всего приложение при выполнении FreeLibrary, либо неизвестную мне ошибку "DXGI ERROR: CreateDXGIFactory cannot be called from DllMain. [ MISCELLANEOUS ERROR #76: ]".
      Так же не могу понять, как передать Handle приложения в библиотеку (в VSL это было довольно просто).
       
      К сожалению никакой информации по данным вопросам я не смог найти, кроме не больших вырезок со своими недочётами.
       
      Прошу вас помочь в решении данных проблем.
      Большое спасибо.
       
      С уважением, Ethernet.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу