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

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

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

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

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

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Всё супер, огромное спасибо!!! Удивляюсь как заработало у Константин75

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Удивляюсь как заработало у Константин75
Видимо он использовал AutoCAD 2012  там "acad.exe", а не "accore.dll" и другая сигнатура функции.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Не подскажите, как вернуть прежний хук?

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

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

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
В данном примере, мы установили хук и отлавливаем нажатие на клавиши и выводим сообщение. Как сделать, чтобы, например, по нажатию кнопки на ленте (или по вызову функции, не важно) отменить вывод сообщений, а вернуть стандартную реакцию на нажатие клавиш.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
а вернуть стандартную реакцию на нажатие клавиш.
Т.е. убрать свой хук? Тогда нужно использовать обертку для функции acedRemoveFilterWinMsg.
Без проверки:
Код - C# [Выбрать]
  1. [DllImport("accore.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl,
  2.   EntryPoint = "?acedRemoveFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")]
  3. private static extern bool acedRemoveFilterWinMsg(WindowHookProc callBackFunc);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Я в начале воспользовался ссылкой https://www.caduser.ru/forum/post195914.html#p195914, у меня после команды UnregisterHook хук не отменился, а стал дублироваться, т.е. сообщение теперь стало выводиться дважды. Увидел, что Вы подкорректировали ответ, и
Код - C# [Выбрать]
  1. private static extern int acedRemoveFilterWinMsg(WindowHookProc callBackFunc);
стало
Код - C# [Выбрать]
  1. private static extern bool acedRemoveFilterWinMsg(WindowHookProc callBackFunc);
Но, к сожалению, сообщения так дважды и выводятся. На всякий случай, привожу свой код. Может у меня глаз "замылился"
Код - C# [Выбрать]
  1. // Для AutoCAD 2013 64 бит
  2.         // Для предыдущих версий импортируем из acad.exe (вместо accore.dll)
  3.         [DllImport("accore.dll",
  4.             CharSet = CharSet.Unicode,
  5.             CallingConvention = CallingConvention.Cdecl,
  6.             //EntryPoint = "?acedRegisterFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
  7.             EntryPoint = "?acedRegisterFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")] //с версии AutoCAD2019
  8.         private static extern int acedRegisterFilterWinMsg(WindowHookProc callBackFunc);
  9.  
  10.         // For AutoCAD 2013 64 bit
  11.         // On previous versions, import from acad.exe (instead accore.dll)
  12.         [DllImport("accore.dll", CharSet = CharSet.Unicode,
  13.             CallingConvention = CallingConvention.Cdecl,
  14.             EntryPoint = "?acedRemoveFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")]
  15.         private static extern bool acedRemoveFilterWinMsg(WindowHookProc callBackFunc);
  16.  
  17.         const int WM_KEYDOWN = 0x100; // Нажатие клавиши
  18.         const int WM_KEYUP = 0x101; // Отжатие клавиши
  19.         const int VK_ADD = 0x6B; // Клавиша +
  20.         const int VK_OEM_PLUS = 0xBB; // Клавиша + на цифровой клавиатуре
  21.  
  22.  
  23.         // Функция обратного вызова для хука
  24.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  25.         public delegate int WindowHookProc(ref System.Windows.Forms.Message msg);
  26.  
  27.         private static int WindowsHook(
  28.           ref System.Windows.Forms.Message msg)
  29.         {
  30.             // проверяем структуру msg на то, что нас интересует,
  31.             // например, клавиши, движения мыши, и т.д.
  32.  
  33.             if (msg.Msg == WM_KEYDOWN)
  34.             {
  35.                 if (msg.WParam == (IntPtr)VK_ADD || msg.WParam == (IntPtr)VK_OEM_PLUS)
  36.                     // делаем что нужно
  37.                     MessageBox.Show("Нажата клавиша +");
  38.             }
  39.  
  40.             return 0;
  41.         }
  42.  
  43.         private static WindowHookProc callBackFunc = null;
  44.  
  45.         [CommandMethod("registerHook")]
  46.         public static void CmdRegisterHook()
  47.         {
  48.             callBackFunc = new WindowHookProc(WindowsHook);
  49.             acedRegisterFilterWinMsg(callBackFunc);
  50.         }
  51.  
  52.         [CommandMethod("UnregisterHook")]
  53.         public static void CmdUnRegisterHook()
  54.         {
  55.             acedRemoveFilterWinMsg(callBackFunc);
  56.         }
« Последнее редактирование: 02-10-2022, 20:56:12 от Александр Ривилис »

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Странно, вы вроде только переформатировали моё сообщение (не нашел отличий в тексте), но сейчас оно работает нормально. Где-то я что-то не так делал. Еще раз, большое спасибо

Отмечено как Решение Александр Ривилис 07-10-2022, 20:31:05

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь 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(WinHook.MyCommands))]
  10.  
  11. namespace WinHook
  12. {
  13.   public class MyCommands
  14.   {
  15.     [DllImport("accore.dll",
  16.         CharSet = CharSet.Unicode,
  17.         CallingConvention = CallingConvention.Cdecl,
  18.         EntryPoint = "?acedRegisterFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")] //с версии AutoCAD2019
  19.     private static extern bool acedRegisterFilterWinMsg(WindowHookProc callBackFunc);
  20.  
  21.     [DllImport("accore.dll", CharSet = CharSet.Unicode,
  22.         CallingConvention = CallingConvention.Cdecl,
  23.         EntryPoint = "?acedRemoveFilterWinMsg@@YA_NQ6A_NPEAUtagMSG@@@Z@Z")]
  24.     private static extern bool acedRemoveFilterWinMsg(WindowHookProc callBackFunc);
  25.  
  26.     const int WM_KEYDOWN = 0x100; // Нажатие клавиши
  27.     const int WM_KEYUP = 0x101; // Отжатие клавиши
  28.     const int VK_ADD = 0x6B; // Клавиша +
  29.     const int VK_OEM_PLUS = 0xBB; // Клавиша + на цифровой клавиатуре
  30.  
  31.  
  32.     // Функция обратного вызова для хука
  33.     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  34.     public delegate bool WindowHookProc(ref System.Windows.Forms.Message msg);
  35.  
  36.     private static bool WindowsHook(
  37.       ref System.Windows.Forms.Message msg)
  38.     {
  39.       // проверяем структуру msg на то, что нас интересует,
  40.       // например, клавиши, движения мыши, и т.д.
  41.  
  42.       if (msg.Msg == WM_KEYDOWN)
  43.       {
  44.         if (msg.WParam == (IntPtr)VK_ADD || msg.WParam == (IntPtr)VK_OEM_PLUS)
  45.           // делаем что нужно
  46.           MessageBox.Show("Нажата клавиша +");
  47.       }
  48.  
  49.       return false;
  50.     }
  51.  
  52.     private static WindowHookProc callBackFunc = null;
  53.  
  54.     [CommandMethod("registerHook")]
  55.     public static void CmdRegisterHook()
  56.     {
  57.       if (callBackFunc != null)
  58.       {
  59.         acedRemoveFilterWinMsg(callBackFunc);
  60.       }
  61.       callBackFunc = new WindowHookProc(WindowsHook);
  62.       acedRegisterFilterWinMsg(callBackFunc);
  63.     }
  64.  
  65.     [CommandMethod("UnregisterHook")]
  66.     public static void CmdUnRegisterHook()
  67.     {
  68.       if (callBackFunc != null)
  69.       {
  70.         acedRemoveFilterWinMsg(callBackFunc);
  71.         callBackFunc = null;
  72.       }
  73.     }
  74.  
  75.   }
  76.  
  77. }
  78.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Александр, не подскажите еще как сделать, чтобы на событие был ответ только моего плагина, а сам AutoCAD его не получал? Сейчас получается, что после отработки WindowsHook, например, обработки нажатия клавиши, AutoCAD также обрабатывает это нажатие

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis

Александр, не подскажите еще как сделать, чтобы на событие был ответ только моего плагина, а сам AutoCAD его не получал? Сейчас получается, что после отработки WindowsHook, например, обработки нажатия клавиши, AutoCAD также обрабатывает это нажатие
Нужно возвращать из WindowsHook значение true
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Если заменить на true, то после запуска плагина и ввода команды "registerHook" AutoCAD зависает. С false всё работает нормально, но не так как хочется

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Если заменить на true, то после запуска плагина и ввода команды "registerHook" AutoCAD зависает.
Нужно отлаживать. Возможно ты зацикливаешь хук или наоборот не передаёшь в AutoCAD необходимые ему вещи.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Если заменить на true, то после запуска плагина и ввода команды "registerHook" AutoCAD зависает. С false всё работает нормально, но не так как хочется
О! Сообразил. Нужно вставить return true; сразу после MessageBox.Show("Нажата клавиша +");
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение