最近一直在研究golang下监听键盘和鼠标的操作事件功能, github上有也有非常优秀的开源库robotgo, 它地址如下, 有兴趣的同学可以去研究下:

但是目前它的键盘事件是阻塞的, 比如github上展示的一个例子

package main

import (
	"fmt"

	"github.com/go-vgo/robotgo"
)

func main() {
  ok := robotgo.AddEvents("q", "ctrl", "shift")
  if ok {
    fmt.Println("add events...")
  }

  keve := robotgo.AddEvent("k")
  if keve {
    fmt.Println("you press... ", "k")
  }

  mleft := robotgo.AddEvent("mleft")
  if mleft {
    fmt.Println("you press... ", "mouse left button")
  }
}

这段代码的功能很简单, 就是三个事件: 

a) ctrl + shift + q组合事件

b) k键点击事件

c) 鼠标左键点击事件

但在使用这段代码的过程中, 程序阻塞在了第一个监听事件, 你先按k键是监听不到的, 只能先按ctrl + shift + q组合键, 再按k键, 最后按鼠标左键, 程序退出.

而目前我使用的场景是在一个循环中轮询监听键盘的事件, 不能阻塞. 所以我根据win c/c++中的键盘和鼠标异步监听事件的代码, 改写到golang里, 同样也非常感谢无私的同学把自己的见解发到网上, 给我了启发. 下面就是项目部分: 

 

1, 代码目录结构如下:

 

2, windevice.h-头文件函数声明如下:

#ifndef WINDEVICE_H_
#define WINDEVICE_H_

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

// 键按下或者抬起
// 1-处于按下状态
// 0-处于抬起状态
int keyDownUp(int e);
// 设置屏幕坐标
bool setCursorPos(int x, int y);
// 鼠标事件
void mouseEvent(int dwFlags, int dx, int dy, int dwData, long long dwExtraInfo);

#ifdef __cplusplus
}
#endif

#endif // WINDEVICE_H_

3, windevice.c-源文件代码如下:

#include <windows.h>
#include "windevice.h"

int keyDownUp(int e)
{
        return (GetAsyncKeyState(e) & 0x8000) ? 1:0;
}

bool setCursorPos(int x, int y)
{
        return SetCursorPos(x, y);
}

void mouseEvent(int dwFlags, int dx, int dy, int dwData, long long dwExtraInfo)
{
        mouse_event(dwFlags, dx, dy, dwData, dwExtraInfo);
}

4, golang的windev包宏定义macro.go就不展示了, 里面的宏定义是支持的事件, 来自winuser.h头文件, 并增加了自己的宏定义.

5, golang的windev包代码实现windev.go如下:

package windev
/*
#cgo CFLAGS: -I./cdep
#cgo LDFLAGS: -L./lib -lwindevice
#include "windevice.h"
*/
import "C"

// KeyDownUp ..
func KeyDownUp(e int) C.int{
	return C.keyDownUp(C.int(e))
}

// SetCursorPos ..
func SetCursorPos(x, y int) C.bool{
	return C.setCursorPos(C.int(x), C.int(y))
}

// MouseEvent ..
func MouseEvent(dwFlags, dx, dy, dwData int, dwExtraInfo int64) {
	C.mouseEvent(C.int(dwFlags), C.int(dx), C.int(dy), C.int(dwData), C.longlong(dwExtraInfo))
}

我自己把windevice.h/c编译了一个静态库, 放在了lib下, 可以在windev.go里直接使用

golang测试代码如下:

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/cppdebug/windev"
)

func main() {

	for i := 0; i < 10; i++ {

		// 按Q键退出
		if windev.KeyDownUp(windev.VK_CHARQ) == 1 {
			fmt.Println("exit")
			os.Exit(-1)
		}

		// 设置鼠标的位置
		if windev.SetCursorPos(910, 300) {
			fmt.Println("set pos")
		}

		// 鼠标的滑轮事件, 页面向下滑动
		windev.MouseEvent(windev.MOUSEEVENTF_WHEEL, 0, 0, -100, 0)

		// 鼠标左键按下和松开事件
		windev.MouseEvent(windev.MOUSEEVENTF_LEFTDOWN|windev.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)

		time.Sleep(time.Second)
	}
}

最后, 我把代码上传到github, 以下是地址:

欢迎各位大牛指点