Захват сообщения окна и затем запуск кода

1

У меня есть код окна, и в нем у меня есть функция, подписанная на получение системных сообщений:

... IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)

В этой функции, когда я вижу сообщение, которое я ожидаю, я запускаю свой класс

... IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    ...some code checking the type of the mesage, etc....

    new MyClass(); //Trigger my class
}

Если я сделаю это так, то получаю эту ошибку "RPC_E_CANTCALLOUT_ININPUTSYNCCALL". После некоторых исследований, если я это правильно пойму, это не позволит мне запускать MyClass или аналогичный код, потому что я пытаюсь выполнить его, когда система еще не завершена, доставляя все сообщения или какую-то аналогичную проблему.

Поэтому, чтобы обойти эту проблему, я отправляю сообщение себе так:

[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);      

private static  IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    ...some code checking the type of the mesage, etc....

   if (msg != 0xD903) //If msg is not 55555 this message is not a repost and therefore repost it
   {
       var devType = Marshal.ReadInt32(lParam, 4); 
       Debug.WriteLine(devType); //This correctly prints out "2"  which i get from lParam

       PostMessage(hwnd, 55555, wParam, lParam);     //repost message
   }
   else //If the msg is 55555 this message is my repost and I can execute MyClass with no problems
   {
       var devType = Marshal.ReadInt32(lParam, 4); 
       Debug.WriteLine(devType); //This should also print out "2", since I am merely reposting the lParam, without changing it in any way, but instead it prints "0"

      new MyClass(); //Trigger my class
   }
}

Чтобы решить мою проблему, мне нужно либо знать:

Почему devType 0 при отправке сообщения?

или

Есть ли какой-нибудь (простой) способ, с помощью которого я могу запускать MyClass напрямую, когда получаю системное сообщение, не переписывая сообщение самому себе?

Теги:
wpf
.net-4.5

1 ответ

1

Что касается вашего LParam, то 0... Вы обрабатываете IntPtr как размер 4, что не так, если ваш Targeting AnyCpu и вы находитесь на 64-битной ОС. Так что, если размер на самом деле равен 8, и он хранится в Little Endian в памяти (который находится в окнах), тогда чтение 4 будет получать первые 4 байта, который будет равен 0, если значения меньше максимального значения 4 байт. В Little Endian значение сохраняется справа налево (наивысший адрес до наименьшего адреса). Так что, вероятно, ничего не было в первых 4 байтах, и вы не читали последние 4 байта, потому что вы предполагали, что IntPtr имеет 4 байта.

Попробуйте использовать

Marshal.ReadInt32 (lParam, lParam.Size)

IntPtr.Size вернет 4, когда он будет 32-битным Runtime и 8, когда он будет работать в 64-битной среде исполнения (управляя этим dilmma для вас).

Что касается остальной части,

Также имейте в виду, если вы пытаетесь сделать глобальный крючок,

Единственными глобальными перехватами, которые вы можете использовать в.Net для обработчика MSG, например SetWindowsHookEx, являются "крюк низкого уровня WH_KEYBOARD_LL и WH_MOUSE_LL".

Теперь вы можете подключить свой собственный процесс просто отлично, но вы не можете перехватывать другие процессы глобально в.Net.

И если вы подключаете свой собственный процесс, почему бы вам просто не переопределить WndProc в классе формы, тогда вам не нужно ничего делать в DllImport и оно будет в правильном порядке (например, вы не получите его на ранней стадии или до конца).

  • 0
    Если я пытаюсь использовать lParam.Size, он говорит: «Не удается получить доступ к статическому размеру свойства в нестатическом контексте». Вот как я подключаюсь: HwndSource.FromHwnd ((новый WindowInteropHelper (Parent)). Handle) .AddHook (WndProc); Я думаю, что я подключаюсь к своему собственному процессу, не так ли? Я не очень хорошо это понимаю. Если вы можете опубликовать пример того, как сделать это лучше, чтобы я мог выполнить свой класс напрямую, как мне грустно, это было бы здорово.
  • 0
    Извините, используйте IntPtr.Size, а не lParam.Size Size - статическое свойство IntPtr. Если вы расскажете нам, что вы пытаетесь сделать и почему вы подключаетесь, я найду вам несколько ссылок.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню