Перейти к содержанию
  • 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;

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

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

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


Ссылка на сообщение

Рекомендуемые сообщения

  • 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

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


Ссылка на сообщение

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


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

    • От 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 пользователей онлайн

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

×
×
  • Создать...