package main import ( "fmt" "io" "log" "os" "syscall" "fyne.io/systray" hook "github.com/robotn/gohook" ) var ( us32 = syscall.MustLoadDLL("user32.dll") SetForegroundWindow = us32.MustFindProc("SetForegroundWindow") GetForegroundWindow = us32.MustFindProc("GetForegroundWindow") ) var Error *log.Logger var Warning *log.Logger func init() { log.SetFlags(log.Lmicroseconds | log.Lshortfile) logFile, err := os.Create("main.log") if err != nil { log.Printf("Error creating log file: %v", err) os.Exit(1) } logger := io.MultiWriter(os.Stdout, logFile) log.SetOutput(logger) Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout), fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) Warning = log.New(io.MultiWriter(logFile, os.Stdout), fmt.Sprintf("%sWarning:%s ", "\033[0;93m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) } const ( ALT = 0xa4 TILDE = 0xc0 ) func main() { systray.Run(onReady, onExit) keyEvents := make(chan *hook.Event, 4096) hook.Register(hook.KeyDown, []string{}, func(e hook.Event) { keyEvents <- &e }) hook.Register(hook.KeyUp, []string{}, func(e hook.Event) { keyEvents <- &e }) processes := make(map[uintptr]bool) keysDown := make(map[uint16]bool) go func() { for { key, ok := <-keyEvents if !ok { Error.Printf("Error reading key events") return } log.Printf("%#v", key) if key.Kind == hook.KeyDown { keysDown[key.Rawcode] = true } else { keysDown[key.Rawcode] = false } if keysDown[ALT] && key.Rawcode == TILDE { hwnd, _, _ := GetForegroundWindow.Call() existing, ok := processes[hwnd] if !ok { processes[hwnd] = true } else { processes[hwnd] = !existing } } // if key.Kind == hook.KeyUp { // StopSpam(key.Rawcode) // } else if key.Kind == hook.KeyDown { // DoSpam(key.Rawcode) // } } }() s := hook.Start() <-hook.Process(s) } func onReady() { systray.SetIcon(icon.Data) systray.SetTitle("Awesome App") systray.SetTooltip("Pretty awesome超级棒") mQuit := systray.AddMenuItem("Quit", "Quit the whole app") // Sets the icon of a menu item. Only available on Mac and Windows. mQuit.SetIcon(icon.Data) }