Pergunta

Estou tentando ligar um aplicativo 3o partido para que eu possa tirar a sua tela. Desenho para a tela é fácil, e eu não preciso de ajuda com isso, mas eu parecem estar a ter problemas com o uso SetWindowsHookEx para WH_GETMESSAGE alça. Eu não consigo descobrir o que passar para os dois últimos parâmetros.

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;
    }
}
Foi útil?

Solução

SetWindowsHookEx especificas nos últimos dois parâmetros Thusly :

  • hMod

[no] Identificador para a DLL que contém o procedimento gancho apontado pelo lpfn parâmetro. O parâmetro hMod deve ser Definir como NULL se o dwThreadId parâmetro especifica um segmento criado pelo processo atual e se o gancho procedimento está dentro do código associado ao processo atual.

  • dwThreadId

[no] Especifica o identificador do fio com o qual o procedimento de gancho está a ser associada. Se este parâmetro é igual a zero, o procedimento de rotina é associado com os tópicos existentes correndo na mesma área de trabalho como o chamando fio.

Eu não tenho certeza que você pode usar um .NET dll na forma exigida, mas certamente você pode tentar.

Grab hMod via Marshal.GetHINSTANCE (typeof (Formulário1) .module) e dwThreadId através Process.Threads . Alternativamente, conjunto dwThreadId a 0 se você quer um gancho global (ou seja. Um gancho para todas as chamadas GetMessage() na área de trabalho atual), mas cuidado com as penalidades de desempenho.

Outras dicas

A seguir sugere que este não vai funcionar:

"ganchos globais não são suportadas no .NET Framework. Exceto para o gancho WH_KEYBOARD_LL de baixo nível eo gancho WH_MOUSE_LL de baixo nível, você não pode implementar ganchos globais no Microsoft .NET Framework."

A partir "Como definir um gancho do Windows no Visual C # .NET"

Eu acredito que você precisa para P / Invoke GetModuleHandle e usar a alça ele retorna para o terceiro parâmetro de SetWindowsHookEx. Eu também acredito 0 é correto para o quarto parâmetro, como você não quer ligar qualquer fio de um específico no aplicativo de terceiros.

Se isso não funcionar para você, SetWindowsHookEx no MSDN pode apontar na direção certa.

Eu não sei, mas se você estiver usando os valores dos parâmetros que especificam que você deseja, como a API ajuda diz, "injetar uma DLL em outro processo", então por tudo que eu sei que pode funcionar apenas se você escrever uma DLL não gerenciada a partir do qual a chamá-lo.

Eu sei que esta é uma questão de idade, mas eu estou esperando que ainda há alguém que vai encontrar este útil. Eu acho que você está misturando-se int e IntPtr

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

Este trabalho para mim usar 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
  }

ganchos globais não são suportadas no .NET Framework

exceto para o gancho WH_KEYBOARD_LL de baixo nível eo gancho WH_MOUSE_LL de baixo nível, você não pode implementar ganchos globais no Microsoft .NET Framework.

Para instalar um gancho global, um gancho deve ter uma exportação DLL nativa para injetar-se em outro processo que requer uma função válida e consistente para pôr em. Este comportamento requer uma exportação DLL.

O .NET Framework não suporta exportações DLL. O código gerenciado não tem o conceito de um valor consistente para um ponteiro de função, pois esses ponteiros de função são proxies que são construídos de forma dinâmica.

procedimentos gancho de baixo nível são chamados no thread que instalou o gancho. ganchos de baixo nível não requerem que o procedimento de gancho ser implementado em uma DLL.

Veja também: Snoop - O WPF Spy Utility

Ou o meu WPF => WF => Win32 LL_Keyboard gancho Proxy w / Gestos

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top