0

我想构建一个在后台工作的应用程序,并将捕获实际运行的所有打开的表单/窗口的最小化按钮上的所有点击事件。(不仅在我当前的应用程序中)

将最小化处理程序添加到所有其他窗口将是某种钩子。

如何设置这种钩子?(请在 csharp 中提供一些带有 marsheling 的代码示例)

为了更好地理解这个想法:这个程序已经存在于名为 TrayIt 的程序中,它处理 Ctrl+单击最小化按钮,并将程序发送到系统托盘。

编辑

我发现由于管理代码的限制,SetWindowsHookEx无法使用 c# 设置全局挂钩(请参阅 msdn 文档)

但可能带有 EVENT_OBJECT_STATECHANGE 的WinEventProc应该完成这项工作

4

1 回答 1

0

很好,我找到了这个钩子的解决方案,这不是我能得到的最好的解决方案,但它确实有效

我在SetWinEventHook中混合了window_state_change

和组件来跟踪Gma.UserActivityMonitor中的控制键

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Permissions;
using Gma.UserActivityMonitor;

namespace example {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        public const uint WINEVENT_OUTOFCONTEXT = 0;
        public const uint EVENT_OBJECT_STATECHANGE = 0x800A;
        [DllImport("user32.dll")]
        public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
        [DllImport("user32.dll")]
        public static extern bool UnhookWinEvent(IntPtr hWinEventHook);

        public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        public static bool ControlDown = false;
        public static IntPtr hhook;
        static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);

        private void load(object sender, System.EventArgs e) {
            hhook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE, IntPtr.Zero, procDelegate, 0, 0, winapi.WINEVENT_OUTOFCONTEXT);
            HookManager.KeyDown += HookManager_KeyDown;
            HookManager.KeyUp += HookManager_KeyUp;
        }
        private void closing(object sender, System.Windows.Forms.FormClosingEventArgs e) {
            UnhookWinEvent(hhook);

            HookManager.KeyDown -= HookManager_KeyDown;
            HookManager.KeyUp -= HookManager_KeyUp;
        }
        private void HookManager_KeyUp(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.LControlKey) { ControlDown = false; }
        }
        private void HookManager_KeyDown(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.LControlKey) { ControlDown = true; }
        }

        static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) {
            if (idObject == -2 && idChild == 2) {
                if (ControlDown) {

                    // HookWindow(hwnd);
                    .....
                }

            }
        }
    }
}

如果你喜欢,你可以使用RegisterHotKey设置一个简单的钩子

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
于 2013-10-09T13:09:00.550 回答