为什么我无法检测到发送到我的 CommonDialog 的 Windows 消息?拦截它们的正确方法是什么?

普希金

我试图检测用户何时点击 aForm和 a CommonDialog

表格相当简单。我创建了一个MessageFilter拦截消息类:

class MessageFilter : IMessageFilter
{
    private const int WM_LBUTTONDOWN = 0x0201;
    public bool PreFilterMessage(ref Message message)
    {
        if (message.Msg == WM_LBUTTONDOWN)
        {
            Console.WriteLine("activity");
        }
        return false;
    }
}

我注册了消息过滤器:

MessageFilter mf = new MessageFilter();
Application.AddMessageFilter(mf);

Form form = new Form();
form.ShowDialog();

Application.RemoveMessageFilter(mf)

当我运行我的控制台应用程序并单击 时Form,我看到“活动”记录到控制台。

当我替换FormCommonDialog

SaveFileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();

即使我可以看到 Windows 消息被发送到 CommonDialog(FWIW,我无法检测到任何消息),我也无法再检测到鼠标点击:

在此处输入图片说明

那我怎么不能拦截那些消息呢?


我想到的是,由于Application.AddMessageFilter是线程特定的,也许如果 CommonDialog 是在与调用 的线程不同的线程上创建的dialog.ShowDialog(),我将不会收到任何这些消息。

但是,我做了一个快速测试,我尝试向WM_CLOSE调用 的线程上的所有 CommonDialogs发送一条消息dialog.ShowDialog(),并且成功了:

int threadId = 0;
Thread thread = new Thread(() =>
{
    threadId = NativeMethods.GetCurrentThreadIdWrapper();
    SaveFileDialog dialog = new SaveFileDialog();
    dialog.ShowDialog();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

Thread.Sleep(2000);
NativeMethods.CloseAllWindowsDialogs(threadId);
Thread.Sleep(2000);

NativeMethods 看起来像:

static class NativeMethods
{
    public static int GetCurrentThreadIdWrapper()
    {
        return GetCurrentThreadId();
    }

    public static void CloseAllWindowsDialogs(int threadId)
    {
        EnumThreadWndProc callback = new EnumThreadWndProc(CloseWindowIfCommonDialog);
        EnumThreadWindows(threadId, callback, IntPtr.Zero);
        GC.KeepAlive(callback);
    }

    private static bool CloseWindowIfCommonDialog(IntPtr hWnd, IntPtr lp)
    {
        if (IsWindowsDialog(hWnd))
        {
            UIntPtr result;
            const int WM_CLOSE = 0x0010;
            const uint SMTO_ABORTIFHUNG = 0x0002;
            SendMessageTimeout(hWnd, WM_CLOSE, UIntPtr.Zero, IntPtr.Zero, SMTO_ABORTIFHUNG, 5000, out result);
        }

        return true;
    }

    private static bool IsWindowsDialog(IntPtr hWnd)
    {
        const int MAX_PATH_LENGTH = 260; // https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
        StringBuilder sb = new StringBuilder(MAX_PATH_LENGTH);
        GetClassName(hWnd, sb, sb.Capacity);

        return sb.ToString() == "#32770";
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern int GetCurrentThreadId();

    private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint msg, UIntPtr wp, IntPtr lp, uint fuFlags, uint timeout, out UIntPtr lpdwResult);
}

为什么我不能拦截 CommonDialog 消息?我能做些什么?

金喵

设置一个本地鼠标钩子怎么样?

在我的项目上运行良好。

public const int WM_LBUTTONDOWN = 0x0201;
// add other button messages if necessary

public const int WH_MOUSE = 7;

private IntPtr _hookHandle;

private void HookStart() {
    int threadId = GetCurrentThreadId();

    HookProc mouseClickHandler = new HookProc(MouseClickHandler);
    _hookHandle = SetWindowsHookEx(WH_MOUSE, mouseClickHandler, IntPtr.Zero, (uint) threadId);
    if (_hookHandle == IntPtr.Zero) throw new Exception("Hooking failed!");
}

private void HookStop() {        
    if (UnhookWindowsHookEx(_hookHandle) == IntPtr.Zero) throw new Exception("Unhooking failed!");
}

private IntPtr MouseClickHandler(int nCode, IntPtr wParam, IntPtr lParam) {
    if (nCode >= 0 && wParam == (IntPtr) WM_LBUTTONDOWN) {
        // user clicked
    }
    return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}

public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, uint threadId);
[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int UnhookWindowsEx(IntPtr idHook);
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId();

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么我无法将文件从Android发送到Windows 10?

来自分类Dev

为什么Ubuntu无法检测到我的SD卡?

来自分类Dev

为什么Ubuntu无法检测到我的SD卡?

来自分类Dev

为什么我的Dependency属性将null发送到我的视图模型?

来自分类Dev

为什么我的HTML表单不将数据发送到我的JS文件?

来自分类Dev

为什么我的Dependency属性将null发送到我的视图模型?

来自分类Dev

为什么我的Javascript无法检测到我的div之一?

来自分类Dev

为什么ubuntu错误地检测到我的显卡?

来自分类Dev

为什么SDL无法在Linux(PocketCHIP)上检测到我的iBuffalo游戏控制器?

来自分类Dev

为什么Android Studio无法检测到我的Nexus 6?

来自分类Dev

为什么Pyngrok无法检测到我的配置文件?

来自分类Dev

为什么stringr :: str_detect无法检测到我的字符串?

来自分类Dev

为什么Elasticsearch无法检测到我的定制分析仪?

来自分类Dev

无法为指定的ProgID创建对象实例(WIA.CommonDialog)

来自分类Dev

为什么我的Linux Mint 19无法看到我的(Windows)NVMe驱动器?

来自分类Dev

为什么我的代码会将提示发送到我的手机,而不是其他任何试图向机器人发送消息的人?

来自分类Dev

为什么我无法将邮件发送到远程邮箱?

来自分类Dev

为什么我的TUN设备无法将UDP / IP发送到192.168.2.x?

来自分类Dev

为什么将专用网络的DNS服务发现查询发送到我的ISP?

来自分类Dev

Qt为什么不将调试消息发送到Windows中的std错误流?

来自分类Dev

Qt为什么不将调试消息发送到Windows中的std错误流?

来自分类Dev

为什么Network Manager无法检测到我的ZTE USB 3G调制解调器!

来自分类Dev

为什么Network Manager无法检测到我的ZTE USB 3G调制解调器!

来自分类Dev

为什么我的C程序无法检测到特殊字符?

来自分类Dev

为什么Windows 8.x的用户无法登录到我们的域?

来自分类Dev

Windows 8.1为什么找不到我的文件?

来自分类Dev

我怎么知道从ADFS发送到我的Web应用程序的令牌的格式是什么?

来自分类Dev

我正在从邮递员和JS代码将POST发送到我的Web服务-响应不同,为什么?

来自分类Dev

为什么未检测到我的Wacom Intuos平板电脑?

Related 相关文章

  1. 1

    为什么我无法将文件从Android发送到Windows 10?

  2. 2

    为什么Ubuntu无法检测到我的SD卡?

  3. 3

    为什么Ubuntu无法检测到我的SD卡?

  4. 4

    为什么我的Dependency属性将null发送到我的视图模型?

  5. 5

    为什么我的HTML表单不将数据发送到我的JS文件?

  6. 6

    为什么我的Dependency属性将null发送到我的视图模型?

  7. 7

    为什么我的Javascript无法检测到我的div之一?

  8. 8

    为什么ubuntu错误地检测到我的显卡?

  9. 9

    为什么SDL无法在Linux(PocketCHIP)上检测到我的iBuffalo游戏控制器?

  10. 10

    为什么Android Studio无法检测到我的Nexus 6?

  11. 11

    为什么Pyngrok无法检测到我的配置文件?

  12. 12

    为什么stringr :: str_detect无法检测到我的字符串?

  13. 13

    为什么Elasticsearch无法检测到我的定制分析仪?

  14. 14

    无法为指定的ProgID创建对象实例(WIA.CommonDialog)

  15. 15

    为什么我的Linux Mint 19无法看到我的(Windows)NVMe驱动器?

  16. 16

    为什么我的代码会将提示发送到我的手机,而不是其他任何试图向机器人发送消息的人?

  17. 17

    为什么我无法将邮件发送到远程邮箱?

  18. 18

    为什么我的TUN设备无法将UDP / IP发送到192.168.2.x?

  19. 19

    为什么将专用网络的DNS服务发现查询发送到我的ISP?

  20. 20

    Qt为什么不将调试消息发送到Windows中的std错误流?

  21. 21

    Qt为什么不将调试消息发送到Windows中的std错误流?

  22. 22

    为什么Network Manager无法检测到我的ZTE USB 3G调制解调器!

  23. 23

    为什么Network Manager无法检测到我的ZTE USB 3G调制解调器!

  24. 24

    为什么我的C程序无法检测到特殊字符?

  25. 25

    为什么Windows 8.x的用户无法登录到我们的域?

  26. 26

    Windows 8.1为什么找不到我的文件?

  27. 27

    我怎么知道从ADFS发送到我的Web应用程序的令牌的格式是什么?

  28. 28

    我正在从邮递员和JS代码将POST发送到我的Web服务-响应不同,为什么?

  29. 29

    为什么未检测到我的Wacom Intuos平板电脑?

热门标签

归档