195 lines
6.1 KiB
Go
195 lines
6.1 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"fmt"
|
||
"io"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
|
||
"github.com/getlantern/systray"
|
||
)
|
||
|
||
var (
|
||
sendPipe *os.File
|
||
receivePipe *os.File
|
||
logFile *os.File
|
||
)
|
||
|
||
func initLog() {
|
||
var err error
|
||
logFile, err = os.OpenFile("systray_debug.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||
if err != nil {
|
||
// failsafe
|
||
return
|
||
}
|
||
}
|
||
|
||
func logMsg(format string, args ...interface{}) {
|
||
if logFile != nil {
|
||
fmt.Fprintf(logFile, format+"\n", args...)
|
||
}
|
||
}
|
||
|
||
func main() {
|
||
initLog()
|
||
logMsg("Systray process started")
|
||
|
||
// 使用 Stdin 和 Stdout 与主进程通信
|
||
// 主进程将 cmd.Stdin 连接到 pipes,将 cmd.Stdout 连接到 pipes
|
||
// 所以这里我们直接使用 os.Stdin 读取,os.Stdout 发送
|
||
|
||
sendPipe = os.Stdout
|
||
receivePipe = os.Stdin
|
||
|
||
// 启动系统托盘
|
||
logMsg("Calling systray.Run")
|
||
systray.Run(onReady, onExit)
|
||
}
|
||
|
||
func onReady() {
|
||
logMsg("systray onReady called")
|
||
// 设置托盘图标 - 使用简单的图标
|
||
systray.SetIcon(getIcon())
|
||
systray.SetTitle("Bidding Looker")
|
||
systray.SetTooltip("Bidding Looker - 招标信息查看器")
|
||
|
||
// 显示窗口菜单项
|
||
mShow := systray.AddMenuItem("显示窗口", "显示主窗口")
|
||
mQuit := systray.AddMenuItem("退出", "退出程序")
|
||
|
||
// 监听来自主进程的消息
|
||
go monitorPipe()
|
||
|
||
// 处理菜单点击
|
||
go func() {
|
||
for {
|
||
select {
|
||
case <-mShow.ClickedCh:
|
||
logMsg("Show menu clicked")
|
||
// 发送显示窗口消息到主进程
|
||
sendMessage("SHOW")
|
||
case <-mQuit.ClickedCh:
|
||
logMsg("Quit menu clicked")
|
||
// 发送退出消息到主进程
|
||
sendMessage("QUIT")
|
||
systray.Quit()
|
||
}
|
||
}
|
||
}()
|
||
|
||
// 监听系统信号
|
||
sigCh := make(chan os.Signal, 1)
|
||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||
go func() {
|
||
<-sigCh
|
||
logMsg("Received signal, quitting")
|
||
systray.Quit()
|
||
}()
|
||
}
|
||
|
||
func onExit() {
|
||
logMsg("systray onExit called")
|
||
// 清理资源
|
||
}
|
||
|
||
func monitorPipe() {
|
||
logMsg("Starting monitorPipe")
|
||
reader := bufio.NewReader(receivePipe)
|
||
for {
|
||
line, err := reader.ReadString('\n')
|
||
if err != nil {
|
||
if err == io.EOF {
|
||
logMsg("Pipe EOF, quitting")
|
||
// 主进程关闭了管道(可能退出了),我们也退出
|
||
systray.Quit()
|
||
return
|
||
}
|
||
logMsg("Pipe read error: %v", err)
|
||
fmt.Fprintf(os.Stderr, "Pipe read error: %v\n", err)
|
||
return
|
||
}
|
||
// 处理来自主进程的消息 (日志输出到 Stderr,避免污染 Stdout)
|
||
logMsg("Received from main: %s", line)
|
||
fmt.Fprintf(os.Stderr, "Received from main: %s", line)
|
||
}
|
||
}
|
||
|
||
func sendMessage(message string) {
|
||
logMsg("Sending message: %s", message)
|
||
_, err := sendPipe.WriteString(message + "\n")
|
||
if err != nil {
|
||
logMsg("Failed to send message: %v", err)
|
||
fmt.Fprintf(os.Stderr, "Failed to send message: %v\n", err)
|
||
}
|
||
}
|
||
|
||
// 简单的图标数据(16x16 像素的简单图标)
|
||
// 使用 PNG 格式,这是 systray 库在 Windows 上的推荐格式
|
||
func getIcon() []byte {
|
||
// PNG 文件签名
|
||
// IHDR chunk (图像头): 16x16, 8-bit RGBA
|
||
// IDAT chunk (图像数据): 简单的蓝色方块图标
|
||
// IEND chunk (文件结束)
|
||
return []byte{
|
||
// PNG 签名 (8 bytes)
|
||
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
|
||
|
||
// IHDR chunk
|
||
0x00, 0x00, 0x00, 0x0D, // Length: 13 bytes
|
||
0x49, 0x48, 0x44, 0x52, // Type: IHDR
|
||
0x00, 0x00, 0x00, 0x10, // Width: 16
|
||
0x00, 0x00, 0x00, 0x10, // Height: 16
|
||
0x08, // Bit depth: 8
|
||
0x06, // Color type: RGBA
|
||
0x00, 0x00, 0x00, // Compression, Filter, Interlace
|
||
0x5D, 0x8A, 0x7F, 0xD4, // CRC
|
||
|
||
// IDAT chunk (使用最简单的 PNG 编码)
|
||
0x00, 0x00, 0x01, 0x6D, // Length: 365 bytes
|
||
0x49, 0x44, 0x41, 0x54, // Type: IDAT
|
||
// 压缩数据 (zlib 格式)
|
||
0x78, 0x9C, // zlib header (default compression)
|
||
// Deflate 压缩块
|
||
0x63, 0x18, 0x19, 0x60, 0x28, 0x55, 0xF6, 0x7F, 0x00, 0x00, 0x00,
|
||
0x00, 0x05, 0x00, 0x01, 0x0A, 0x8C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00,
|
||
0x52, 0x4B, 0x8C, 0x36, // CRC
|
||
|
||
// IEND chunk
|
||
0x00, 0x00, 0x00, 0x00, // Length: 0 bytes
|
||
0x49, 0x45, 0x4E, 0x44, // Type: IEND
|
||
0xAE, 0x42, 0x60, 0x82, // CRC
|
||
}
|
||
}
|