Вопрос

Я пытаюсь подключить стороннее приложение, чтобы я мог рисовать на его экране.Рисовать на экране легко, и мне не нужна с этим помощь, но, похоже, у меня возникли проблемы с использованием SetWindowsHookEx чтобы справиться WH_GETMESSAGE.Я не могу понять, что передать для последних двух параметров.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowDrawer
{
    public partial class Form1 : Form
    {
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static IntPtr hHook;
        IntPtr windowHandle;
        uint processHandle;

        HookProc PaintHookProcedure;     

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet =System.Runtime.InteropServices.CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        { 
            PaintHookProcedure = new HookProc(PaintHookProc);
            windowHandle = FindWindowByCaption(0, "Untitled - Notepad");
            uint threadID = GetWindowThreadProcessId(windowHandle, out processHandle);
            IntPtr hMod = System.Runtime.InteropServices.Marshal.GetHINSTANCE(typeof(Form1).Module);

            // HERE IS THE PROBLEM.  WHAT THE HECK DO I PASS INTO THE LAST 2 PARAMS?  I get a null pointer
            hHook = SetWindowsHookEx(WH_GETMESSAGE, PaintHookProcedure, hMod, threadID);
        }

        public int PaintHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
           // Do some painting here.
            return CallNextHookEx(hHook, nCode, wParam, lParam); 
        }

        private const int WM_PAINT = 15;
        private const int WH_GETMESSAGE = 3;
    }
}
Это было полезно?

Решение

SetWindowsHookEx Установить Windowshookex конкретизируйте последние два параметра таким образом:

  • hMod

[in] Дескриптор библиотеки DLL, содержащей процедуру перехвата, на которую указывает параметр lpfn .Параметр hMod должен быть установлен в значение NULL, если параметр dwThreadId указывает поток, созданный текущим процессом, и если процедура hook находится в коде , связанном с текущим процессом.

  • dwThreadId

[in] Указывает идентификатор потока, с которым должна быть связана процедура подключения .Если этот параметр равен нулю, процедура перехвата связана со всеми существующими потоками выполняется на том же рабочем столе, что и вызывающий поток.

Я не уверен, что вы можете использовать .NET dll требуемым образом, но вы, безусловно, можете попробовать.

Захватывать hMod через Маршал.GetHINSTANCE(typeof(Form1).Модуль) и dwThreadId через Процесс.Ветки.В качестве альтернативы, установите dwThreadId к 0, если вы хотите глобальный хук (т.е.крючок для всех GetMessage() вызовы на текущем рабочем столе), но остерегайтесь снижения производительности.

Другие советы

Следующее предполагает, что это не сработает:

  

" Глобальные хуки не поддерживаются в .NET Framework. За исключением низкоуровневого хука WH_KEYBOARD_LL и низкоуровневого хука WH_MOUSE_LL, вы не можете реализовать глобальные хуки в Microsoft .NET Framework. & Quot;

От " Как установить хук Windows в Visual C # .NET "

Полагаю, вам нужно P / Invoke < code> GetModuleHandle и используйте дескриптор, который он возвращает для третьего параметра SetWindowsHookEx . Я также считаю, что 0 является правильным для четвертого параметра, так как вы не хотите подключать какой-либо конкретный поток в стороннем приложении.

Если это не работает для вас, SetWindowsHookEx в MSDN может указать вам правильное направление.

Я не знаю, но если вы используете значения параметров, которые указывают, что вы хотите, как подсказывает API, «вставить DLL в другой процесс», то, насколько я знаю, это может сработать, только если вы написать неуправляемую библиотеку DLL, из которой она будет вызываться.

Я знаю, что это старый вопрос, но я надеюсь, что есть еще кто-то, кто найдет это полезным. Я думаю, что вы смешиваете int и IntPtr

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

Эта работа для меня использовать 13 ...

 private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(13, proc,
                GetModuleHandle(curModule.ModuleName), 0);
            }
        }
  internal enum HookType : uint {
    WH_JOURNALRECORD = 0,
    WH_JOURNALPLAYBACK = 1,
    WH_KEYBOARD = 2,
    WH_GETMESSAGE = 3,
    WH_CALLWNDPROC = 4,
    WH_CBT = 5,
    WH_SYSMSGFILTER = 6,
    WH_MOUSE = 7,
    WH_HARDWARE = 8,
    WH_DEBUG = 9,
    WH_SHELL = 10,
    WH_FOREGROUNDIDLE = 11,
    WH_CALLWNDPROCRET = 12,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
  }

Глобальные хуки не поддерживаются в .NET Framework

За исключением низкоуровневого хука WH_KEYBOARD_LL и низкоуровневого хука WH_MOUSE_LL, вы не можете реализовать глобальные хуки в Microsoft .NET Framework.

Чтобы установить глобальный хук, хук должен иметь собственный экспорт DLL, чтобы внедрить себя в другой процесс, для которого требуется допустимая, согласованная функция для вызова. Это поведение требует экспорта DLL.

.NET Framework не поддерживает экспорт DLL. Управляемый код не имеет понятия согласованного значения для указателя функции, поскольку эти указатели на функции являются прокси, которые создаются динамически.

Низкоуровневые процедуры подключения вызываются в потоке, который установил подключение Низкоуровневые хуки не требуют, чтобы процедура хуков была реализована в DLL.

Смотрите также: Snoop - программа-шпион WPF

Или мой WPF = > WF = > Win32 LL_Keyboard Hook Proxy с жестами

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top