当前位置: 首页 > news >正文

【Golang】Windows系统键鼠空闲监测练习

 在本文中,我们将练习如何使用Golang编写一个简单的Windows系统空闲时间监测工具。该工具能够检测系统的空闲时间,并在达到一定阈值时计数。

功能概述

监控鼠标和键盘的空闲事件,每空闲超过50s,触发次数加一。

该工具具有以下功能:

  • 监测系统空闲时间。
  • 当系统空闲时间超过设定的阈值时,触发计数。
  • 实时显示当前系统触发次数。

代码实现

下载包

go get golang.org/x/sys/windows
go get github.com/getlantern/systray

以下是实现该工具的完整代码:

package main

import (
	"fmt"
	"time"
	"unsafe"

	"github.com/getlantern/systray"
	"golang.org/x/sys/windows"
)

// 配置参数
const (
	idleThreshold = 40 * time.Second
)

var (
	user32           = windows.NewLazySystemDLL("user32.dll")
	kernel32         = windows.NewLazySystemDLL("kernel32.dll")
	getLastInputInfo = user32.NewProc("GetLastInputInfo")
	getTickCount     = kernel32.NewProc("GetTickCount")

	counter      uint
	triggerTimes []string
	lastActive   time.Time
)

type LASTINPUTINFO struct {
	CbSize uint32
	Dtime  uint32
}

func main() {
	systray.Run(onReady, onExit)
}

func onReady() {
	// 设置托盘图标和菜单
	systray.SetIcon(IconData)
	systray.SetTitle("空闲监测")
	systray.SetTooltip("空闲监测运行中...")

	mHistory := systray.AddMenuItem("查看历史", "显示触发记录")
	mReset := systray.AddMenuItem("重置计数", "重置统计信息")
	mQuit := systray.AddMenuItem("退出", "退出程序")

	// 初始化记录
	lastActive = time.Now().Add(-getSystemIdleTime())
	updateTooltip()

	// 启动监测协程
	go monitorLoop()

	// 处理菜单点击
	go func() {
		for {
			select {
			case <-mHistory.ClickedCh:
				showHistory()
			case <-mReset.ClickedCh:
				resetCounter()
			case <-mQuit.ClickedCh:
				systray.Quit()
				return
			}
		}
	}()
}

func monitorLoop() {
	for {
		idle := getSystemIdleTime()
		updateCounter(idle)
		updateTooltip()
		time.Sleep(time.Second)
	}
}

func updateCounter(idle time.Duration) {
	if idle < idleThreshold {
		actualIdle := time.Since(lastActive)
		if actualIdle >= idleThreshold {
			counter++
			triggerTimes = append(triggerTimes, time.Now().Format("2006-01-02 15:04:05"))
		}
		lastActive = time.Now().Add(-idle)
	}
}

func resetCounter() {
	counter = 0
	triggerTimes = nil
	updateTooltip()
}

func updateTooltip() {
	tooltip := fmt.Sprintf("空闲监测\n触发次数: %d\n最后触发: %s",
		counter,
		lastTriggerTime())
	systray.SetTooltip(tooltip)
}

func lastTriggerTime() string {
	if len(triggerTimes) == 0 {
		return "从未触发"
	}
	return triggerTimes[len(triggerTimes)-1]
}

func showHistory() {
	if len(triggerTimes) == 0 {
		showMessage("触发历史", "暂无触发记录")
		return
	}

	content := "触发时间记录:\n"
	for _, t := range triggerTimes {
		content += t + "\n"
	}
	showMessage("触发历史", content)
}

func showMessage(title, message string) {
	windows.MessageBox(0,
		strPtr(message),
		strPtr(title),
		windows.MB_OK|windows.MB_ICONINFORMATION)
}

func strPtr(s string) *uint16 {
	p, _ := windows.UTF16PtrFromString(s)
	return p
}

func getSystemIdleTime() time.Duration {
	info := &LASTINPUTINFO{CbSize: uint32(unsafe.Sizeof(LASTINPUTINFO{}))}
	ret, _, _ := getLastInputInfo.Call(uintptr(unsafe.Pointer(info)))
	if ret == 0 {
		return 0
	}

	tick, _, _ := getTickCount.Call()
	lastInput := uint32(tick) - info.Dtime

	return time.Duration(lastInput) * time.Millisecond
}

func onExit() {
	// 退出时的清理工作
	fmt.Print("\033[?25h") // 恢复光标显示(如果之前隐藏了)
}

// 图标数据(需用2goarray生成)
var IconData []byte = []byte{
	// 这里填入实际的图标字节数据
}

go.mod

module idle-monitor

go 1.23.0

toolchain go1.23.7

require (
	github.com/getlantern/systray v1.2.2
	golang.org/x/sys v0.31.0
)

require (
	github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
	github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
	github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect
	github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect
	github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect
	github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect
	github.com/go-stack/stack v1.8.0 // indirect
	github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
)

需要使用 2goarray 生成图标的 bytes 变量并替换掉 IconData 变量,图标使用64×64 ico格式

下载后运行

go run 2goarray.go MyArray mypackage < myimage.ico > myimage.go

代码解析

  1. 配置参数:定义了空闲触发阈值和刷新间隔。
  2. 数据结构:定义了LASTINPUTINFO结构体,用于获取系统最后输入时间。
  3. 全局变量:定义了所需的全局变量,如用户32和内核32库的引用、触发次数等。
  4. 主函数:初始化显示、记录活动时间,并在循环中更新计数器和显示状态。
  5. 辅助函数:包括更新计数器、显示状态、初始化显示、启用虚拟终端处理和获取系统空闲时间。
    通过这个简单的工具,我们可以实时监测Windows系统的空闲时间,并在达到设定阈值时进行计数。

打包为exe

go build -ldflags="-H windowsgui" -o idle-monitor.exe

运行exe,右下角会出现相应图标
在这里插入图片描述
鼠标悬浮显示空闲段触发次数
在这里插入图片描述
在这里插入图片描述

右键查看历史会显示历史空闲
在这里插入图片描述
在这里插入图片描述

相关文章:

  • 每天学一个 Linux 命令(8):ls
  • 使用 KT-Connect 0.3.7在本地访问 Kubernetes
  • 如何实现口型0误差?
  • RTL8304问题
  • 《电容:时空交错的能量银行》
  • 愚人杯-web-被遗忘的反序列化
  • [数学]关于组合数
  • 蓝桥杯比赛python程序设计——班级活动
  • 【前端】一文掌握 Vue 3 指令用法(vue3 备忘清单)
  • 字符串复习
  • scss报错Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0
  • 如何加强 SSH 安全:内网和专用网络环境下的防护策略
  • Linux中的文件寻址
  • 脚手架 + 指令
  • 山东大学软件学院项目创新实训开发日志(4)之中医知识问答数据存储、功能结构、用户界面初步设计
  • 语义分析(编译原理)
  • Springcache+xxljob实现定时刷新缓存
  • Linux文件描述符的分配机制与重定向实现:揭开“一切皆文件”的面纱
  • 使用卷积神经网络识别MNIST数据集
  • AI与.NET技术实操系列(三):在 .NET 中使用大语言模型(LLMs)
  • 奇艺广州网站建设熊掌号/网上培训机构
  • 想学做网站学什么教程/查询网138网站域名
  • 网站域名到期了怎么办/内容营销案例
  • 公司网站开发怎么入账/网络推广代理
  • 论坛网站怎么做/视频剪辑培训机构
  • 自己做网站的流程/手机百度网盘下载慢怎么解决