2022-10-04 13:21:05 +08:00
|
|
|
|
//----------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Copyright © yanghy. All Rights Reserved.
|
|
|
|
|
//
|
2023-02-19 23:21:47 +08:00
|
|
|
|
// Licensed under Apache License Version 2.0, January 2004
|
|
|
|
|
//
|
|
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//
|
|
|
|
|
//----------------------------------------
|
|
|
|
|
|
|
|
|
|
//go:build windows
|
|
|
|
|
// +build windows
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// 基于 LCL 系统托盘 - windows 平台
|
|
|
|
|
// Html + CSS + JavaScript实现
|
2023-05-31 17:41:14 +08:00
|
|
|
|
|
2022-10-04 13:21:05 +08:00
|
|
|
|
package cef
|
|
|
|
|
|
|
|
|
|
import (
|
2023-05-31 18:00:34 +08:00
|
|
|
|
. "github.com/energye/energy/v2/common"
|
|
|
|
|
. "github.com/energye/energy/v2/consts"
|
|
|
|
|
"github.com/energye/energy/v2/logger"
|
|
|
|
|
"github.com/energye/energy/v2/pkgs/assetserve"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
"github.com/energye/golcl/lcl"
|
|
|
|
|
"github.com/energye/golcl/lcl/types"
|
|
|
|
|
)
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// newLCLTrayWindow 创建LCL系统托盘
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func newLCLTrayWindow(owner lcl.IComponent, width, height int32, url string) *CEFTray {
|
|
|
|
|
var trayForm *CEFTray
|
2022-10-04 13:21:05 +08:00
|
|
|
|
lcl.Application.CreateForm(&trayForm)
|
|
|
|
|
trayForm.trayIcon = lcl.NewTrayIcon(owner)
|
|
|
|
|
trayForm.trayIcon.SetVisible(true)
|
|
|
|
|
trayForm.owner = owner
|
|
|
|
|
trayForm.x = -width
|
|
|
|
|
trayForm.y = -height
|
|
|
|
|
trayForm.w = width
|
|
|
|
|
trayForm.h = height
|
|
|
|
|
trayForm.url = url
|
2023-01-07 16:12:00 +08:00
|
|
|
|
trayForm.onMouseEvent()
|
|
|
|
|
trayForm.createTrayWindow()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return trayForm
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// OnFormCreate TForm创建
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) OnFormCreate(sender lcl.IObject) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.SetShowInTaskBar(types.StNever)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// AsSysTray 尝试转换为 SysTray 组件托盘,如果创建的是其它类型托盘返回nil
|
2023-01-24 18:55:02 +08:00
|
|
|
|
func (m *CEFTray) AsSysTray() *SysTray {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// AsViewsFrameTray 尝试转换为 views framework 组件托盘, 如果创建的是其它类型托盘返回nil
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) AsViewsFrameTray() *ViewsFrameTray {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// AsCEFTray 尝试转换为 LCL+CEF 组件托盘, 如果创建的是其它类型托盘返回nil
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) AsCEFTray() *CEFTray {
|
|
|
|
|
return m
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// AsLCLTray 尝试转换为 LCL 组件托盘, 如果创建的是其它类型托盘返回nil
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) AsLCLTray() *LCLTray {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// Show 显示/启动 托盘
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) Show() {
|
2023-01-06 13:50:44 +08:00
|
|
|
|
if BrowserWindow.mainBrowserWindow.Chromium() == nil || !BrowserWindow.mainBrowserWindow.Chromium().Initialized() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
m.TForm.Show()
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// Hide 隐藏 托盘
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) Hide() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.Hide()
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) close() {
|
2022-11-02 16:18:02 +08:00
|
|
|
|
if m.isClosing {
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.Hide()
|
2023-01-07 16:12:00 +08:00
|
|
|
|
m.trayIcon.SetVisible(false)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.Close()
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetOnDblClick 设置双击事件
|
2023-01-10 19:52:57 +08:00
|
|
|
|
func (m *CEFTray) SetOnDblClick(fn TrayICONClick) {
|
|
|
|
|
m.trayIcon.SetOnDblClick(func(sender lcl.IObject) {
|
|
|
|
|
fn()
|
|
|
|
|
})
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetOnClick 设置单击事件
|
2023-01-10 19:52:57 +08:00
|
|
|
|
func (m *CEFTray) SetOnClick(fn TrayICONClick) {
|
|
|
|
|
m.trayIcon.SetOnClick(func(sender lcl.IObject) {
|
|
|
|
|
fn()
|
|
|
|
|
})
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetOnMouseUp 鼠标抬起事件
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetOnMouseUp(fn TMouseEvent) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.mouseUp = fn
|
|
|
|
|
}
|
2023-02-20 14:42:17 +08:00
|
|
|
|
|
|
|
|
|
// SetOnMouseDown 鼠标按下事件
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetOnMouseDown(fn lcl.TMouseEvent) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.trayIcon.SetOnMouseDown(fn)
|
|
|
|
|
}
|
2023-02-20 14:42:17 +08:00
|
|
|
|
|
|
|
|
|
// SetOnMouseMove 鼠标移动事件
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetOnMouseMove(fn lcl.TMouseMoveEvent) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.trayIcon.SetOnMouseMove(fn)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// Visible 显示状态
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) Visible() bool {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return m.TForm.Visible()
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetVisible 设置显示状态
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetVisible(v bool) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.trayIcon.SetVisible(v)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetHint 设置提示
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetHint(value string) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.trayIcon.SetHint(value)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetTitle 设置标题
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetTitle(title string) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.SetCaption(title)
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) onMouseEvent() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
QueueAsyncCall(func(id int) {
|
|
|
|
|
m.trayIcon.SetOnMouseUp(func(sender lcl.IObject, button types.TMouseButton, shift types.TShiftState, x, y int32) {
|
|
|
|
|
var monitor = m.TForm.Monitor()
|
|
|
|
|
var monitorWidth = monitor.Width()
|
|
|
|
|
width, height := m.TForm.Width(), m.TForm.Height()
|
|
|
|
|
var mx = x + width
|
|
|
|
|
var my = y + height
|
|
|
|
|
if mx < monitorWidth {
|
|
|
|
|
mx = x
|
|
|
|
|
} else {
|
|
|
|
|
mx = x - width
|
|
|
|
|
}
|
|
|
|
|
if my > m.h {
|
|
|
|
|
my = y
|
|
|
|
|
}
|
|
|
|
|
if my > height {
|
|
|
|
|
my = y - height
|
|
|
|
|
}
|
|
|
|
|
m.TForm.SetBounds(mx, my, width, height)
|
|
|
|
|
var ret bool
|
|
|
|
|
if m.mouseUp != nil {
|
|
|
|
|
ret = m.mouseUp(sender, button, shift, x, y)
|
|
|
|
|
}
|
|
|
|
|
if !ret {
|
|
|
|
|
if button == types.MbRight {
|
|
|
|
|
m.Show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// Notice
|
2023-02-19 23:21:47 +08:00
|
|
|
|
// 显示系统通知
|
2023-01-27 21:34:56 +08:00
|
|
|
|
//
|
2023-02-19 23:21:47 +08:00
|
|
|
|
// title 标题
|
2023-01-27 21:34:56 +08:00
|
|
|
|
//
|
2023-02-19 23:21:47 +08:00
|
|
|
|
// content 内容
|
2023-01-27 21:34:56 +08:00
|
|
|
|
//
|
2023-02-19 23:21:47 +08:00
|
|
|
|
// timeout 显示时间(毫秒)
|
2023-01-27 21:34:56 +08:00
|
|
|
|
func (m *CEFTray) Notice(title, content string, timeout int32) {
|
|
|
|
|
notification(m.trayIcon, title, content, timeout)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) createTrayWindow() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.SetBorderStyle(types.BsNone)
|
|
|
|
|
m.TForm.SetFormStyle(types.FsStayOnTop)
|
|
|
|
|
m.TForm.SetBounds(-(m.w * 2), -(m.h * 2), m.w, m.h)
|
|
|
|
|
m.TForm.SetOnActivate(func(sender lcl.IObject) {
|
|
|
|
|
m.chromium.Initialized()
|
2023-06-12 22:24:03 +08:00
|
|
|
|
m.chromium.CreateBrowser(m.windowParent, "", nil, nil)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
})
|
|
|
|
|
m.TForm.SetOnWndProc(func(msg *types.TMessage) {
|
|
|
|
|
m.TForm.InheritedWndProc(msg)
|
|
|
|
|
if msg.Msg == 6 && msg.WParam == 0 && msg.LParam == 0 {
|
|
|
|
|
QueueAsyncCall(func(id int) {
|
2023-01-04 22:47:30 +08:00
|
|
|
|
if m.isClosing {
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.Hide()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
m.TForm.SetOnDeactivate(func(sender lcl.IObject) {
|
2023-01-04 22:47:30 +08:00
|
|
|
|
if m.isClosing {
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.TForm.Hide()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
m.TForm.SetOnCloseQuery(func(sender lcl.IObject, canClose *bool) {
|
2022-12-15 23:13:27 +08:00
|
|
|
|
*canClose = true
|
|
|
|
|
logger.Debug("tray.window.onCloseQuery canClose:", *canClose)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
if m.isClosing {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
m.isClosing = true
|
|
|
|
|
m.Hide()
|
|
|
|
|
m.chromium.CloseBrowser(true)
|
2022-11-02 16:18:02 +08:00
|
|
|
|
m.trayIcon.Free()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
})
|
|
|
|
|
m.TForm.SetOnClose(func(sender lcl.IObject, action *types.TCloseAction) {
|
|
|
|
|
*action = types.CaFree
|
2022-12-15 23:13:27 +08:00
|
|
|
|
logger.Debug("tray.window.onClose action:", *action)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
})
|
|
|
|
|
m.TForm.SetOnShow(func(sender lcl.IObject) {
|
|
|
|
|
if m.windowParent != nil {
|
|
|
|
|
QueueAsyncCall(func(id int) {
|
|
|
|
|
m.windowParent.UpdateSize()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
m.windowParent = NewCEFWindow(m.TForm)
|
|
|
|
|
m.windowParent.SetParent(m.TForm)
|
|
|
|
|
m.windowParent.SetAlign(types.AlClient)
|
|
|
|
|
m.windowParent.SetAnchors(types.NewSet(types.AkTop, types.AkLeft, types.AkRight, types.AkBottom))
|
|
|
|
|
m.chromium = NewChromium(m.windowParent, nil)
|
|
|
|
|
m.chromium.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
|
|
|
|
|
model.Clear()
|
|
|
|
|
})
|
2023-05-31 17:41:14 +08:00
|
|
|
|
m.chromium.SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return false
|
|
|
|
|
})
|
2022-11-02 15:56:00 +08:00
|
|
|
|
m.chromium.SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *TCefReturnValue) {
|
|
|
|
|
if assetserve.AssetsServerHeaderKeyValue != "" {
|
|
|
|
|
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
|
|
|
|
|
}
|
|
|
|
|
})
|
2023-05-31 17:41:14 +08:00
|
|
|
|
m.chromium.SetOnClose(func(sender lcl.IObject, browser *ICefBrowser, aAction *TCefCloseBrowserAction) {
|
2022-12-15 23:13:27 +08:00
|
|
|
|
logger.Debug("tray.chromium.onClose")
|
2022-10-04 13:21:05 +08:00
|
|
|
|
if IsDarwin() {
|
|
|
|
|
m.windowParent.DestroyChildWindow()
|
|
|
|
|
}
|
2022-12-15 23:13:27 +08:00
|
|
|
|
*aAction = CbaClose
|
2022-10-04 13:21:05 +08:00
|
|
|
|
})
|
|
|
|
|
m.chromium.SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
|
2022-12-15 23:13:27 +08:00
|
|
|
|
logger.Debug("tray.chromium.onBeforeClose")
|
2022-10-04 13:21:05 +08:00
|
|
|
|
})
|
2023-02-26 21:17:28 +08:00
|
|
|
|
m.chromium.SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess CefProcessId, message *ICefProcessMessage) bool {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
m.windowParent.SetChromium(m.chromium, 0)
|
|
|
|
|
m.chromium.SetDefaultURL(m.url)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetIconFS 设置托盘图标
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetIconFS(iconResourcePath string) {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.trayIcon.Icon().LoadFromFSFile(iconResourcePath)
|
|
|
|
|
}
|
2023-01-07 16:12:00 +08:00
|
|
|
|
|
2023-02-20 14:42:17 +08:00
|
|
|
|
// SetIcon 设置托盘图标
|
2023-01-09 18:32:21 +08:00
|
|
|
|
func (m *CEFTray) SetIcon(iconResourcePath string) {
|
2023-01-07 16:12:00 +08:00
|
|
|
|
m.trayIcon.Icon().LoadFromFile(iconResourcePath)
|
|
|
|
|
}
|