先来一个辅助类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms; namespace HZCX.Utils
{
/// <summary>
/// 鼠标全局钩子
/// </summary>
public static class MouseHook
{
private const int WM_MOUSEMOVE = 0x200;
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_RBUTTONDOWN = 0x204;
private const int WM_MBUTTONDOWN = 0x207;
private const int WM_LBUTTONUP = 0x202;
private const int WM_RBUTTONUP = 0x205;
private const int WM_MBUTTONUP = 0x208;
private const int WM_LBUTTONDBLCLK = 0x203;
private const int WM_RBUTTONDBLCLK = 0x206;
private const int WM_MBUTTONDBLCLK = 0x209; /// <summary>
/// 点
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
} /// <summary>
/// 钩子结构体
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hWnd;
public int wHitTestCode;
public int dwExtraInfo;
} public const int WH_MOUSE_LL = ; // mouse hook constant // 装置钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); // 卸下钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook); // 下一个钩挂的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam); // 全局的鼠标事件
public static event MouseEventHandler OnMouseActivity; // 钩子回调函数
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); // 声明鼠标钩子事件类型
private static HookProc _mouseHookProcedure;
private static int _hMouseHook = ; // 鼠标钩子句柄
/// <summary>
/// 启动全局钩子
/// </summary>
public static void Start()
{
// 安装鼠标钩子
if (_hMouseHook != )
{
Stop();
}
// 生成一个HookProc的实例.
_mouseHookProcedure = new HookProc(MouseHookProc); _hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, _mouseHookProcedure, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetEntryAssembly().GetModules()[]), ); //假设装置失败停止钩子
if (_hMouseHook == )
{
Stop();
throw new Exception("SetWindowsHookEx failed.");
}
} /// <summary>
/// 停止全局钩子
/// </summary>
public static void Stop()
{
bool retMouse = true; if (_hMouseHook != )
{
retMouse = UnhookWindowsHookEx(_hMouseHook);
_hMouseHook = ;
} // 假设卸下钩子失败
if (!(retMouse))
throw new Exception("UnhookWindowsHookEx failed.");
} /// <summary>
/// 鼠标钩子回调函数
/// </summary>
private static int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
// 假设正常执行而且用户要监听鼠标的消息
if ((nCode >= ) && (OnMouseActivity != null))
{
MouseButtons button = MouseButtons.None;
int clickCount = ; switch (wParam)
{
case WM_LBUTTONDOWN:
button = MouseButtons.Left;
clickCount = ;
break;
case WM_LBUTTONUP:
button = MouseButtons.Left;
clickCount = ;
break;
case WM_LBUTTONDBLCLK:
button = MouseButtons.Left;
clickCount = ;
break;
case WM_RBUTTONDOWN:
button = MouseButtons.Right;
clickCount = ;
break;
case WM_RBUTTONUP:
button = MouseButtons.Right;
clickCount = ;
break;
case WM_RBUTTONDBLCLK:
button = MouseButtons.Right;
clickCount = ;
break;
}
if (button != MouseButtons.None && clickCount>)
{
// 从回调函数中得到鼠标的信息
MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, );
OnMouseActivity(null, e);
}
} // 启动下一次钩子
int inext = CallNextHookEx(_hMouseHook, nCode, wParam, lParam);
return inext;
}
}
}

Program的main函数里面调用 MouseHook.Start();

main函数里面写 Application.ApplicationExit += Application_ApplicationExit;

static void Application_ApplicationExit(object sender, EventArgs e)
{
MouseHook.Stop();
}

窗体load里面写 HZCX.Utils.MouseHook.OnMouseActivity += hook_OnMouseActivity;

窗体closing里面写 HZCX.Utils.MouseHook.OnMouseActivity -= hook_OnMouseActivity;

 void hook_OnMouseActivity(object sender, MouseEventArgs e)
{
try
{
if (this._isLoseFocusClose && e.Clicks > )
{
if (e.Button == System.Windows.Forms.MouseButtons.Left || e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (!this.IsDisposed)
{
if (!this.ClientRectangle.Contains(this.PointToClient(e.Location)))
{
base.Close();
}
}
}
}
}
catch { }
}

就这样了

c# winform 窗体失去焦点关闭(钩子实现)的更多相关文章

  1. Winform 窗体获得焦点

    给窗体添加Shown事件 public void Form_Shown(object sender, EventArgs e) { this.Activate(); this.Focus(); //定 ...

  2. winform打开子窗体后,在子窗体中刷新父窗体,或者关闭子窗体刷新父窗体

    winform打开子窗体后,在子窗体中刷新父窗体,或者关闭子窗体刷新父窗体,搜集了几个方法,列举如下: 一 . 所有权法 父窗体,名称为“fuForm”,在父窗体中有个公共刷新方法,也就是窗体数据初始 ...

  3. Winform开发之窗体显示、关闭与资源释放

    Winform的窗体涉及到一般窗体(单文档窗体).MDI窗体.窗体之间的关系等,那么如果调用打开新窗体.如何关闭窗体.窗体资源的释放等都关系到软件运行的效率,本文一一介绍 1.窗体的显示 从一个窗体打 ...

  4. Winform 窗体的操作

    原文:http://www.cnblogs.com/Billy-rao/archive/2012/05/16/2503437.html 怎样能使winform窗体的大小固定住,不能调整其大小 窗体Fo ...

  5. WinForm窗体嵌入

    一.在winform窗体上添加两个控件 1.容器>Panel 2.添加 SideBar.dll (下载链接:http://pan.baidu.com/s/1o6qhf9w) (1)将SideBa ...

  6. C#中WinForm窗体事件的执行次序

    C#中WinForm窗体事件的执行次序如下: 当 Windows Form 应用程序启动时,会以下列顺序引发主要表单的启动事件:        System.Windows.Forms.Control ...

  7. C# winform窗体设计-通过条件查询数据

    在winform 数据库设计中,有时候需要通过条件查询对应的数据,并且将数据显示在文本框(or 富文本框)中,下面,小编将讲述通过一个条件: 首先,我们需要对数据库建立连接,并且执行数据库命令,在此之 ...

  8. Winform窗体事件发生顺序

    Form 和Control 类公开了一组与应用程序启动和关闭相关联的事件.当Windows 窗体应用程序启动时,主窗体的启动事件按以下顺序引发: System.Windows.Forms.Contro ...

  9. 小例子(二)、winform窗体间的关系

    写一个关于winform窗体间的关系 1.登陆,思路:登陆后隐藏登陆窗体,关闭Form2时结束整个应用程序. //登陆窗体 private void button2_Click(object send ...

随机推荐

  1. Java之Date类

    Date类的概述 java.util.Date类 表示特定的瞬间,精确到毫秒.毫秒:千分之一秒 1000毫秒=1秒.特定的瞬间:一个时间点,一刹那时间. 常用构造方法 public Date():分配 ...

  2. shell中字典的一个用法示例

    1. shell中字典的用法示例, 数组用法同字典 2. 以上使用sell配合字典实现的功能, 使用awk能轻松搞定, 如下: awk '{print $2}' file.txt | sort | u ...

  3. java之instanceof操作符

    a intanceof A:判断a是否是类A的的一个实例,返回值为boolean public class Person extends Object{} public class Student e ...

  4. 2019年FJNU低编赛 G题(dfs博弈)

    ###题目链接### 题目大意: 有一个 0 ~ n+1 的数轴,Alice 站在 0 点处,Bob 站在 n+1 点处.在 1 ~ n 上各有着权值. Alice 每次向右移动 1 格或两格 ,Bo ...

  5. HDU - 5952 Counting Cliques

    Counting Cliques HDU - 5952 OJ-ID: hdu-5952 author:Caution_X date of submission:20191110 tags:dfs,gr ...

  6. flutter 侧滑删除+侧滑显示删除按钮

    1.侧滑删除 1.1.Dismissible组件 2.侧滑显示删除按钮 2.1.手势监听水平滑动 ------------------------------------分割线------------ ...

  7. arcgis api 4.x for js 图层拓展篇之mapvLayer(附源码下载)

    因为在项目开发过程中,使用的arcgis js api版本是4.7,并不能支持客户端渲染热力图,想到arcgis js api 4.x的渲染是基于canvas,故琢磨着是否能借助类似于mapV.ech ...

  8. springboot进入html

    话不多说,转载 https://blog.csdn.net/sinat_33889619/article/details/78339042 这个博客写的真好

  9. goroutine并发之callback回调

    玩玩 package main import ( "fmt" "strings" "sync" ) var wait sync.WaitGr ...

  10. Fastdfs的安装流程

    一.修改ip地址 1.查看网卡一的mac地址 cat /etc/udev/rules.d/70-persistent-net.rules 2.修改ip地址文件 cd /etc/sysconfig/ne ...