Как реализовать Windows хук с использованием acedRegisterFilterWinMsg в .NET

Автор Тема: Как реализовать Windows хук с использованием acedRegisterFilterWinMsg в .NET  (Прочитано 28710 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин75

  • ADN OPEN
  • Сообщений: 5
  • Карма: 0
Добрый день!
У меня есть вопрос по данному коду, заранее прошу меня извинить за незнание матчасти.

Пытаюсь применить данный код, для того чтобы отследить нажатие пользователем определённой клавиши, но никаких событий не происходит.
Создал AutoCAD .NET Wizard для VS 2015 (2013, 2012) шаблон и поместил в раздел MyCommands.cs внутрь процедуры (функции) данный код - получил ошибку. Вставил код  после объявления пространства имён и имя класса, то всё компилируется без ошибок, но в AutoCade срабатывания не происходит.

AutoCad 2012x64



Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Выложи проект полностью - проверю.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин75

  • ADN OPEN
  • Сообщений: 5
  • Карма: 0

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Приложил архив
Проверь этот код:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using System.Runtime.InteropServices;
  6. using System.Windows;
  7.  
  8. // This line is not mandatory, but improves loading performances
  9. [assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in1.MyCommands))]
  10.  
  11. namespace AutoCAD_CSharp_plug_in1
  12. {
  13.   public class MyCommands
  14.   {
  15.     // Для AutoCAD 2013 64 бит
  16.     // Для предыдущих версий импортируем из acad.exe (вместо accore.dll)
  17.     [DllImport("acad.exe",
  18.       CharSet = CharSet.Unicode,
  19.       CallingConvention = CallingConvention.Cdecl,
  20.       EntryPoint = "?acedRegisterFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
  21.     private static extern int acedRegisterFilterWinMsg(
  22.       WindowHookProc callBackFunc);
  23.     const int WM_KEYDOWN = 0x100; // Нажатие клавиши
  24.     const int WM_KEYUP = 0x101; // Отжатие клавиши
  25.     const int VK_ADD = 0x6B; // Клавиша +
  26.  
  27.     // Функция обратного вызова для хука
  28.     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  29.     public delegate int WindowHookProc(
  30.           ref System.Windows.Forms.Message msg);
  31.  
  32.     private static int WindowsHook(
  33.       ref System.Windows.Forms.Message msg)
  34.     {
  35.       // проверяем структуру msg на то, что нас интересует,
  36.       // например, клавиши, движения мыши, и т.д.
  37.  
  38.       if (msg.Msg == WM_KEYDOWN)
  39.       {
  40.         if (msg.WParam == (IntPtr)VK_ADD)
  41.           // делаем что нужно
  42.           MessageBox.Show("Нажата клавиша +");
  43.       }
  44.  
  45.       return 0;
  46.     }
  47.  
  48.     private static WindowHookProc callBackFunc = null;
  49.  
  50.     [CommandMethod("registerHook")]
  51.     public static void CmdRegisterHook()
  52.     {
  53.       callBackFunc = new WindowHookProc(WindowsHook);
  54.       acedRegisterFilterWinMsg(callBackFunc);
  55.     }
  56.   }
  57. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин75

  • ADN OPEN
  • Сообщений: 5
  • Карма: 0
Нет. Не работает.
Почистил от мусора, вставил только этот код. Компилируется без ошибок. В Автокаде ничего не происходит. Нажимаю +, он отображается в командной строке и всплывают подсказки. Пробовал и другие символы - никакой реакции.
По идее всё должно работать. Может на рабочем компьютере не позволяет система безопасности, может уже установлены какие перехватчики?

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Нажимаю +, он отображается в командной строке и всплывают подсказки. Пробовал и другие символы - никакой реакции.
У меня работает. У тебя был совсем неправильный проект, который я очистил. В связи с тем, что пути к acad.exe и к ObjectARX SDK не совпадают я правил проект, удалял лишнее. Можешь попробовать с этим проектом.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Константин75,
Надеюсь команду registerHook ты не забываешь запустить?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин75

  • ADN OPEN
  • Сообщений: 5
  • Карма: 0
Константин75,
Надеюсь команду registerHook ты не забываешь запустить?
Конечно не запускал(. Прошу меня извинить. Всё заработало!
Реагирует на + который на основной клавиатуре, на дополнительной надеюсь разберусь.
Спасибо огромное за помощь!!!

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Константин75,
Надеюсь команду registerHook ты не забываешь запустить?
Конечно не запускал(. Прошу меня извинить. Всё заработало!
Реагирует на + который на основной клавиатуре, на дополнительной надеюсь разберусь.
Спасибо огромное за помощь!!!

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using System.Runtime.InteropServices;
  6. using System.Windows;
  7.  
  8. // This line is not mandatory, but improves loading performances
  9. [assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in1.MyCommands))]
  10.  
  11. namespace AutoCAD_CSharp_plug_in1
  12. {
  13.   public class MyCommands
  14.   {
  15.     // Для AutoCAD 2013 64 бит
  16.     // Для предыдущих версий импортируем из acad.exe (вместо accore.dll)
  17.     [DllImport("acad.exe",
  18.       CharSet = CharSet.Unicode,
  19.       CallingConvention = CallingConvention.Cdecl,
  20.       EntryPoint = "?acedRegisterFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
  21.     private static extern int acedRegisterFilterWinMsg(
  22.       WindowHookProc callBackFunc);
  23.     const int WM_KEYDOWN = 0x100; // Нажатие клавиши
  24.     const int WM_KEYUP = 0x101; // Отжатие клавиши
  25.     const int VK_ADD = 0x6B; // Клавиша +
  26.     const int VK_OEM_PLUS = 0xBB; // Клавиша + на цифровой клавиатуре
  27.  
  28.     // Функция обратного вызова для хука
  29.     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  30.     public delegate int WindowHookProc(
  31.           ref System.Windows.Forms.Message msg);
  32.  
  33.     private static int WindowsHook(
  34.       ref System.Windows.Forms.Message msg)
  35.     {
  36.       // проверяем структуру msg на то, что нас интересует,
  37.       // например, клавиши, движения мыши, и т.д.
  38.  
  39.       if (msg.Msg == WM_KEYDOWN)
  40.       {
  41.         if (msg.WParam == (IntPtr)VK_ADD || msg.WParam ==  (IntPtr)VK_OEM_PLUS)
  42.           // делаем что нужно
  43.           MessageBox.Show("Нажата клавиша +");
  44.       }
  45.  
  46.       return 0;
  47.     }
  48.  
  49.     private static WindowHookProc callBackFunc = null;
  50.  
  51.     [CommandMethod("registerHook")]
  52.     public static void CmdRegisterHook()
  53.     {
  54.       callBackFunc = new WindowHookProc(WindowsHook);
  55.       acedRegisterFilterWinMsg(callBackFunc);
  56.     }
  57.   }
  58. }

Так должно реагировать и на плюс на цифровой клавиатуре.

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин75

  • ADN OPEN
  • Сообщений: 5
  • Карма: 0
Да, Спасибо Большое, Всё работает!
Нужно где-то пометить правильный ответ? пока не нашёл такой кнопки.

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Нужно где-то пометить правильный ответ? пока не нашёл такой кнопки.
Эта кнопка появляется только у тех, кто начинает тему и у администраторов/модераторов. Я отметил решение.
Есть еще [+] и [-], для реакции на сообщение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Кулаков Михаил

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Добрый вечер! Подскажите, вроде бы всё сделал как в последнем примере, ошибок при компиляции никаких нет, вводить "registerHook" не забываю :-) , но как только ввожу, автокад (2022) зависает, а Visual Studio выводит сообщения


Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Кулаков Михаил,
Попробуй вместо:
Код - C# [Выбрать]
  1.     [DllImport("acad.exe",
  2.       CharSet = CharSet.Unicode,
  3.       CallingConvention = CallingConvention.Cdecl,
  4.       EntryPoint = "?acedRegisterFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
  5.     private static extern int acedRegisterFilterWinMsg(
  6.       WindowHookProc callBackFunc);
использовать:
Код - C# [Выбрать]
  1. //    [DllImport("acad.exe",
  2.     [DllImport("accore.dll",
  3.       CharSet = CharSet.Unicode,
  4.       CallingConvention = CallingConvention.Cdecl,
  5.       EntryPoint = "?acedRegisterFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")]
  6.     private static extern bool acedRegisterFilterWinMsg(
  7.       WindowHookProc callBackFunc);
Эта сигнатура начиная с версии AutoCAD 2019
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Кулаков Михаил

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Спасибо, что быстро ответили, но к сожалению, не помогло. Все тоже самое.

Концовка выходных данных VS2019 (если это как-то нужно):
Вызвано исключение: "System.EntryPointNotFoundException" в ClassLibrary1.dll
Поток 0x2bd8 завершился с кодом 0 (0x0).
Вызвано исключение: "System.AccessViolationException" в accoremgd.dll
Необработанное исключение типа "System.AccessViolationException" в accoremgd.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Программа "[26100] acad.exe" завершилась с кодом -1 (0xffffffff).