U: Adjusting the default implementation event to the chrrimbrowser structure

This commit is contained in:
杨红岩 2024-04-07 12:23:29 +08:00
parent ab470d8466
commit 313f66bbed
10 changed files with 502 additions and 462 deletions

View File

@ -110,7 +110,7 @@ func (m *lclBrowserWindow) OnFormCreate(sender lcl.IObject) {
m.SetProperty() //再次设置可能修改属性
}
//browserWindowOnEventCallback 执行完后注册CompMsgEvent
m.registerWindowsCompMsgEvent()
//m.registerWindowsCompMsgEvent()
//自定义窗口标题栏
m.cwcap = &customWindowCaption{

View File

@ -16,6 +16,7 @@ package cef
import (
"github.com/energye/energy/v2/cef/ipc/target"
"github.com/energye/energy/v2/consts"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
@ -134,6 +135,9 @@ type IBrowserWindow interface {
Screen() IScreen //返回屏幕信息
Target(targetType ...target.Type) target.ITarget //IPC接收目标
AsTargetWindow() target.IWindow //IPC
doBeforePopup(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo,
popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings,
resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool
}
// ILCLBrowserWindow
@ -142,20 +146,22 @@ type IBrowserWindow interface {
// 定义了LCL常用函数
type ILCLBrowserWindow interface {
IBrowserWindow
BrowserWindow() *LCLBrowserWindow //返回 LCLBrowserWindow 窗口结构
EnableDefaultCloseEvent() //启用默认关闭事件
WindowParent() ICEFWindowParent //浏览器父窗口组件
DisableTransparent() //禁用窗口透明
EnableTransparent(value uint8) //启用并设置窗口透明
DisableSystemMenu() //禁用标题栏系统菜单
DisableHelp() //禁用标题栏帮助
EnableSystemMenu() //启用标题栏系统菜单
EnableHelp() //启用标题栏帮助
NewTray() ITray //创建LCL的系统托盘
SetRoundRectRgn(rgn int) //窗口无边框时圆角设置
FramelessForLine() //无边框四边一条细线样式
Frameless() //无边框
ChromiumCreate(config *TCefChromiumConfig, defaultUrl string) //chromium实例为空时创建 chromium
BrowserWindow() *LCLBrowserWindow //返回 LCLBrowserWindow 窗口结构
EnableDefaultCloseEvent() //启用默认关闭事件
WindowParent() ICEFWindowParent //浏览器父窗口组件
DisableTransparent() //禁用窗口透明
EnableTransparent(value uint8) //启用并设置窗口透明
DisableSystemMenu() //禁用标题栏系统菜单
DisableHelp() //禁用标题栏帮助
EnableSystemMenu() //启用标题栏系统菜单
EnableHelp() //启用标题栏帮助
NewTray() ITray //创建LCL的系统托盘
SetRoundRectRgn(rgn int) //窗口无边框时圆角设置
FramelessForLine() //无边框四边一条细线样式
Frameless() //无边框
ChromiumCreate(config *TCefChromiumConfig, defaultUrl string) //chromium实例为空时创建 chromium
BroderDirectionAdjustments() et.BroderDirectionAdjustments //返回可以调整窗口大小的边框方向, 默认所有方向
SetBroderDirectionAdjustments(val et.BroderDirectionAdjustments) // 设置可以调整窗口大小的边框方向, 默认所有方向
}
// IViewsFrameworkBrowserWindow
@ -211,14 +217,14 @@ func (m *auxTools) DevTools() *devToolsWindow {
// NewBrowserWindow
//
// 创建浏览器窗口
// 根据当前主窗口类型创建
// 窗口类型
// 创建浏览器窗口
// 根据当前主窗口类型创建
// 窗口类型
// LCL: 是基于LCL组件库创建的窗口相比VF有多更的原生小部件使用更多的窗口操作
// VF : 是基于CEF ViewFramework 组件创建的窗口, 相比LCL无法使用系统原生小部件较少的窗口操作
// config: Chromium配置, 提供快捷chromium配置
// windowProperty: 窗口属性
// owner: 被创建组件拥有者
// config: Chromium配置, 提供快捷chromium配置
// windowProperty: 窗口属性
// owner: 被创建组件拥有者
func NewBrowserWindow(config *TCefChromiumConfig, windowProperty WindowProperty, owner lcl.IComponent) IBrowserWindow {
// 获取当前应用的主窗口
main := BrowserWindow.MainWindow()

View File

@ -22,7 +22,6 @@ import (
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/consts/messages"
"github.com/energye/energy/v2/logger"
"github.com/energye/energy/v2/pkgs/assetserve"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl"
@ -592,6 +591,21 @@ func (m *LCLBrowserWindow) ChromiumCreate(config *TCefChromiumConfig, defaultUrl
})
}
// BroderDirectionAdjustments 返回可以调整窗口大小的边框方向, 默认所有方向
func (m *LCLBrowserWindow) BroderDirectionAdjustments() et.BroderDirectionAdjustments {
if m.chromiumBrowser == nil {
return 0
}
return m.chromiumBrowser.BroderDirectionAdjustments()
}
// SetBroderDirectionAdjustments 设置可以调整窗口大小的边框方向, 默认所有方向
func (m *LCLBrowserWindow) SetBroderDirectionAdjustments(val et.BroderDirectionAdjustments) {
if m.chromiumBrowser != nil {
m.chromiumBrowser.SetBroderDirectionAdjustments(val)
}
}
// WindowProperty 部分提供部分窗口属性设置
func (m *LCLBrowserWindow) WindowProperty() *WindowProperty {
return m.windowProperty
@ -600,8 +614,8 @@ func (m *LCLBrowserWindow) WindowProperty() *WindowProperty {
// defaultChromiumEvent 默认的chromium事件
func (m *LCLBrowserWindow) defaultChromiumEvent() {
if m.WindowType() != consts.WT_DEV_TOOLS {
m.registerPopupEvent()
m.registerDefaultEvent()
m.chromiumBrowser.RegisterDefaultEvent()
m.chromiumBrowser.RegisterDefaultPopupEvent()
m.registerDefaultChromiumCloseEvent()
}
}
@ -635,20 +649,18 @@ func (m *LCLBrowserWindow) defaultWindowCloseEvent() {
m.TForm.SetOnCloseQuery(m.closeQuery)
}
// EnableDefaultCloseEvent 启用默认关闭事件
// EnableDefaultCloseEvent 启用默认关闭事件,仅窗口关闭事件
func (m *LCLBrowserWindow) EnableDefaultCloseEvent() {
m.defaultWindowCloseEvent()
m.registerDefaultChromiumCloseEvent()
}
// EnableAllDefaultEvent 启用所有默认事件行为
// EnableAllDefaultEvent 启用所有默认事件行为, 包含窗口关闭事件
func (m *LCLBrowserWindow) EnableAllDefaultEvent() {
// 窗口关闭事件window和chromium将以正确的行为关闭
// 窗口关闭事件window和chromium关闭流程回调
m.defaultWindowCloseEvent()
// chromium事件在回调事件中实现框架的默认行为
m.defaultChromiumEvent()
// 仅windows有的事件窗口消息事件
m.registerWindowsCompMsgEvent()
}
// SetOnResize 事件,不会覆盖默认事件返回值false继续执行默认事件, true跳过默认事件
@ -884,184 +896,41 @@ func (m *LCLBrowserWindow) activate(sender lcl.IObject) {
}
}
// registerDefaultEvent 注册默认事件 部分事件允许被覆盖
func (m *LCLBrowserWindow) registerDefaultEvent() {
// LCL 窗口的弹出事件
func (m *LCLBrowserWindow) doBeforePopup(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings, resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool {
var bwEvent = BrowserWindow.browserEvent
//默认自定义快捷键
defaultAcceleratorCustom()
m.Chromium().SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool {
if bwEvent.onProcessMessageReceived != nil {
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message, m)
}
return false
})
m.Chromium().SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *consts.TCefReturnValue) {
if assetserve.AssetsServerHeaderKeyValue != "" {
if application.IsSpecVer49() {
headerMap := request.GetHeaderMap()
headerMap.Append(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue)
request.SetHeaderMap(headerMap)
headerMap.Free()
} else {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
}
}
if bwEvent.onBeforeResourceLoad != nil {
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result, m)
}
})
//事件可以被覆盖
m.Chromium().SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
if bwEvent.onBeforeDownload != nil {
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback, m)
} else {
// 默认保存到当前执行文件所在目录
callback.Cont(consts.ExeDir+consts.Separator+suggestedName, true)
}
})
m.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model, m)
}
if !flag {
chromiumOnBeforeContextMenu(m, browser, frame, params, model)
}
})
m.Chromium().SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool {
var result bool
if bwEvent.onContextMenuCommand != nil {
result = bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, m)
// 取出预创建的下一个弹出窗口对象
if next := BrowserWindow.getNextLCLPopupWindow(); next != nil {
bw := next.AsLCLBrowserWindow().BrowserWindow()
bw.SetWindowType(consts.WT_POPUP_SUB_BROWSER)
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, bw, browser, frame, beforePopupInfo, popupFeatures, windowInfo, client, settings, resultExtraInfo, noJavascriptAccess)
}
// result = true 表示用户自行处理
if !result {
result = chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags)
// 使用energy默认弹出窗口
RunOnMainThread(func() {
bw.Chromium().SetDefaultURL(beforePopupInfo.TargetUrl)
bw.EnableAllDefaultEvent()
bw.SetProperty()
// show window, run in main thread
if bw.WindowProperty().IsShowModel {
bw.ShowModal()
return
}
bw.Show()
})
// 此时已经在energy内成功创建弹出窗口对象阻止CEF创建窗口行为
result = true
// 将 BrowserWindow 维护弹出窗口对象(popupWindow)设置为nil, 表示该窗口已被使用
// 并在 chromium.OnAfterCreate 事件中再次预创建弹出窗口对象
BrowserWindow.popupWindow = nil
}
return result
})
m.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onAfterCreated != nil {
flag = bwEvent.onAfterCreated(sender, browser, m)
}
if !flag {
chromiumOnAfterCreate(m, browser)
}
})
//事件可以被覆盖
m.Chromium().SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool) {
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, osEvent, m, result)
}
if !*result {
if m.WindowType() == consts.WT_DEV_TOOLS || m.WindowType() == consts.WT_VIEW_SOURCE {
return
}
if m.Chromium().Config().EnableDevTools() {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
}
}
if KeyAccelerator.accelerator(browser, event, result) {
return
}
}
})
m.Chromium().SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
chromiumOnBeforeBrowser(m, browser, frame, request) // default impl
if bwEvent.onBeforeBrowser != nil {
return bwEvent.onBeforeBrowser(sender, browser, frame, request, userGesture, isRedirect, m)
}
return false
})
m.Chromium().SetOnTitleChange(func(sender lcl.IObject, browser *ICefBrowser, title string) {
updateBrowserDevTools(m, browser, title)
if bwEvent.onTitleChange != nil {
bwEvent.onTitleChange(sender, browser, title, m)
}
})
m.Chromium().SetOnDragEnter(func(sender lcl.IObject, browser *ICefBrowser, dragData *ICefDragData, mask consts.TCefDragOperations, result *bool) {
*result = !m.WindowProperty().EnableDragFile
if bwEvent.onDragEnter != nil {
bwEvent.onDragEnter(sender, browser, dragData, mask, m, result)
}
})
m.Chromium().SetOnLoadEnd(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32) {
if bwEvent.onLoadEnd != nil {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode, m)
}
})
if m.WindowProperty().EnableWebkitAppRegion {
m.Chromium().SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m)
}
m.cwcap.regions = regions
m.setDraggableRegions()
})
}
if localLoadRes.enable() {
m.Chromium().SetOnGetResourceHandler(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler) {
//var flag bool
if bwEvent.onGetResourceHandler != nil {
resourceHandler, _ = bwEvent.onGetResourceHandler(sender, browser, frame, request, m)
}
//if !flag {
// resourceHandler = localLoadRes.getResourceHandler(browser, frame, request)
//}
return
})
}
}
// registerPopupEvent 注册弹出子窗口事件
func (m *LCLBrowserWindow) registerPopupEvent() {
var bwEvent = BrowserWindow.browserEvent
m.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
if !m.Chromium().Config().EnableOpenUrlTab() {
return true
}
return false
})
m.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings, resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool {
if !m.Chromium().Config().EnableWindowPopup() {
return true
}
// 取出预创建的下一个弹出窗口对象
if next := BrowserWindow.getNextLCLPopupWindow(); next != nil {
bw := next.AsLCLBrowserWindow().BrowserWindow()
bw.SetWindowType(consts.WT_POPUP_SUB_BROWSER)
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, bw, browser, frame, beforePopupInfo, popupFeatures, windowInfo, client, settings, resultExtraInfo, noJavascriptAccess)
}
// result = true 表示用户自行处理
if !result {
// 使用energy默认弹出窗口
RunOnMainThread(func() {
bw.Chromium().SetDefaultURL(beforePopupInfo.TargetUrl)
bw.EnableAllDefaultEvent()
bw.SetProperty()
// show window, run in main thread
if bw.WindowProperty().IsShowModel {
bw.ShowModal()
return
}
bw.Show()
})
// 此时已经在energy内成功创建弹出窗口对象阻止CEF创建窗口行为
result = true
// 将 BrowserWindow 维护弹出窗口对象(popupWindow)设置为nil, 表示该窗口已被使用
// 并在 chromium.OnAfterCreate 事件中再次预创建弹出窗口对象
BrowserWindow.popupWindow = nil
}
return result
}
// 未取到下一个弹出窗口对象时,默认行为不创建窗口
return true
})
// 未取到下一个弹出窗口对象时,默认行为不创建窗口
return true
}
// CloseBrowserWindow 关闭带有浏览器的窗口

View File

@ -150,6 +150,7 @@ func (m *customWindowCaption) freeRgn() {
winapi.SetRectRgn(m.rgn, 0, 0, 0, 0)
winapi.DeleteObject(m.rgn)
m.rgn.Free()
m.rgn = nil
}
}
@ -215,39 +216,40 @@ func (m *customWindowCaption) onSetCursor(message *types.TMessage, lResult *type
}
}
// onCanBorder 鼠标是否在边框
func (m *customWindowCaption) onCanBorder(x, y int32, windowRect *types.TRect) bool {
// 鼠标是否在边框,并返回当前鼠标样式
func (m *customWindowCaption) onCanBorder(chromiumBrowser ICEFChromiumBrowser, x, y int32, windowRect *types.TRect) bool {
width := windowRect.Width()
height := windowRect.Height()
if m.canBorder = x <= width && x >= width-angleRange && y <= angleRange; m.canBorder { // 右上
bda := chromiumBrowser.BroderDirectionAdjustments()
if m.canBorder = x <= width && x >= width-angleRange && y <= angleRange; m.canBorder && bda.In(et.BdaTopRight) { // 右上
m.borderWMSZ = messages.WMSZ_TOPRIGHT
m.borderHT = messages.HTTOPRIGHT
return true
} else if m.canBorder = x <= width && x >= width-angleRange && y <= height && y >= height-angleRange; m.canBorder { // 右下
} else if m.canBorder = x <= width && x >= width-angleRange && y <= height && y >= height-angleRange; m.canBorder && bda.In(et.BdaBottomRight) { // 右下
m.borderWMSZ = messages.WMSZ_BOTTOMRIGHT
m.borderHT = messages.HTBOTTOMRIGHT
return true
} else if m.canBorder = x <= angleRange && y <= angleRange; m.canBorder { //左上
} else if m.canBorder = x <= angleRange && y <= angleRange; m.canBorder && bda.In(et.BdaTopLeft) { //左上
m.borderWMSZ = messages.WMSZ_TOPLEFT
m.borderHT = messages.HTTOPLEFT
return true
} else if m.canBorder = x <= angleRange && y >= height-angleRange; m.canBorder { //左下
} else if m.canBorder = x <= angleRange && y >= height-angleRange; m.canBorder && bda.In(et.BdaBottomLeft) { //左下
m.borderWMSZ = messages.WMSZ_BOTTOMLEFT
m.borderHT = messages.HTBOTTOMLEFT
return true
} else if m.canBorder = x > angleRange && x < width-angleRange && y <= borderRange; m.canBorder { //上
} else if m.canBorder = x > angleRange && x < width-angleRange && y <= borderRange; m.canBorder && bda.In(et.BdaTop) { //上
m.borderWMSZ = messages.WMSZ_TOP
m.borderHT = messages.HTTOP
return true
} else if m.canBorder = x > angleRange && x < width-angleRange && y >= height-borderRange; m.canBorder { //下
} else if m.canBorder = x > angleRange && x < width-angleRange && y >= height-borderRange; m.canBorder && bda.In(et.BdaBottom) { //下
m.borderWMSZ = messages.WMSZ_BOTTOM
m.borderHT = messages.HTBOTTOM
return true
} else if m.canBorder = x <= borderRange && y > angleRange && y < height-angleRange; m.canBorder { //左
} else if m.canBorder = x <= borderRange && y > angleRange && y < height-angleRange; m.canBorder && bda.In(et.BdaLeft) { //左
m.borderWMSZ = messages.WMSZ_LEFT
m.borderHT = messages.HTLEFT
return true
} else if m.canBorder = x <= width && x >= width-borderRange && y > angleRange && y < height-angleRange; m.canBorder { // 右
} else if m.canBorder = x <= width && x >= width-borderRange && y > angleRange && y < height-angleRange; m.canBorder && bda.In(et.BdaRight) { // 右
m.borderWMSZ = messages.WMSZ_RIGHT
m.borderHT = messages.HTRIGHT
return true
@ -289,15 +291,15 @@ func (m *customWindowCaption) toPoint(message *types.TMessage) (x, y int32) {
// 鼠标是否在标题栏区域
//
// 如果启用了css拖拽则校验拖拽区域,否则只返回相对于浏览器窗口的x,y坐标
func (m *customWindowCaption) isCaption(hWND et.HWND, message *types.TMessage) (int32, int32, bool) {
func (m *customWindowCaption) isCaption(chromiumBrowser ICEFChromiumBrowser, hWND et.HWND, message *types.TMessage) (int32, int32, bool) {
dx, dy := m.toPoint(message)
p := &et.Point{
X: dx,
Y: dy,
}
winapi.ScreenToClient(hWND, p)
p.X -= m.bw.WindowParent().Left()
p.Y -= m.bw.WindowParent().Top()
p.X -= chromiumBrowser.WindowParent().Left()
p.Y -= chromiumBrowser.WindowParent().Top()
if m.bw.WindowProperty().EnableWebkitAppRegion && m.rgn != nil {
m.canCaption = winapi.PtInRegion(m.rgn, p.X, p.Y)
} else {
@ -306,8 +308,7 @@ func (m *customWindowCaption) isCaption(hWND et.HWND, message *types.TMessage) (
return p.X, p.Y, m.canCaption
}
// doOnRenderCompMsg
func (m *LCLBrowserWindow) doOnRenderCompMsg(messageType compMessageType, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
func (m *LCLBrowserWindow) doOnRenderCompMsg(chromiumBrowser ICEFChromiumBrowser, messageType compMessageType, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
switch message.Msg {
case messages.WM_NCLBUTTONDBLCLK: // 163 NC left dclick
//标题栏拖拽区域 双击最大化和还原
@ -346,7 +347,7 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(messageType compMessageType, messag
)
if messageType == cmtCEF {
//鼠标坐标是否在标题区域
x, y, caption = m.cwcap.isCaption(et.HWND(m.Handle()), message)
x, y, caption = m.cwcap.isCaption(chromiumBrowser, et.HWND(m.Handle()), message)
} else if messageType == cmtLCL {
x, y = m.cwcap.toPoint(message)
p := &et.Point{
@ -367,13 +368,14 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(messageType compMessageType, messag
var rect types.TRect
// 当前类型的消息取出计算的宽高
if messageType == cmtCEF {
rect = m.WindowParent().BoundsRect()
rect = chromiumBrowser.WindowParent().BoundsRect()
} else if messageType == cmtLCL {
rect = m.BoundsRect()
}
// 判断当前鼠标是否在边框范围
// 窗口边框和CEF组件边框
handled := m.cwcap.onCanBorder(x, y, &rect)
handled := m.cwcap.onCanBorder(chromiumBrowser, x, y, &rect)
if handled {
// 鼠标在边框范围
// 当是CEF组件消息判断一次组件四边距离窗口四边间距如果大于边框范围则取消操作
@ -454,10 +456,7 @@ func (m *LCLBrowserWindow) setDraggableRegions() {
y := int32(float32(region.Bounds.Y) * scp)
w := int32(float32(region.Bounds.Width) * scp)
h := int32(float32(region.Bounds.Height) * scp)
creRGN := winapi.CreateRectRgn(x,
y,
x+w,
y+h)
creRGN := winapi.CreateRectRgn(x, y, x+w, y+h)
if region.Draggable {
winapi.CombineRgn(m.cwcap.rgn, m.cwcap.rgn, creRGN, consts.RGN_OR)
} else {
@ -468,50 +467,6 @@ func (m *LCLBrowserWindow) setDraggableRegions() {
})
}
// registerWindowsCompMsgEvent
// 注册windows下CompMsg事件
func (m *LCLBrowserWindow) registerWindowsCompMsgEvent() {
var bwEvent = BrowserWindow.browserEvent
m.Chromium().SetOnRenderCompMsg(func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if bwEvent.onRenderCompMsg != nil {
bwEvent.onRenderCompMsg(sender, message, lResult, aHandled)
}
if !*aHandled {
m.doOnRenderCompMsg(cmtCEF, message, lResult, aHandled)
}
})
// TODO 暂时不使用
//m.SetOnWndProc(func(msg *types.TMessage) {
// var (
// tmpHandled bool
// lResult types.LRESULT
// )
// m.doOnRenderCompMsg(cmtLCL, msg, &lResult, &tmpHandled)
// if tmpHandled {
// msg.Result = lResult
// }
//})
if m.WindowProperty().EnableWebkitAppRegion && m.WindowProperty().EnableWebkitAppRegionDClk {
m.windowResize = func(sender lcl.IObject) bool {
if m.WindowState() == types.WsMaximized && (m.WindowProperty().EnableHideCaption || m.BorderStyle() == types.BsNone || m.BorderStyle() == types.BsSingle) {
var monitor = m.Monitor().WorkareaRect()
m.SetBounds(monitor.Left, monitor.Top, monitor.Right-monitor.Left, monitor.Bottom-monitor.Top)
m.SetWindowState(types.WsMaximized)
}
return false
}
}
//if m.WindowProperty().EnableWebkitAppRegion {
//
//} else {
// if bwEvent.onRenderCompMsg != nil {
// m.chromium.SetOnRenderCompMsg(bwEvent.onRenderCompMsg)
// }
//}
}
// Restore Windows平台窗口还原
func (m *LCLBrowserWindow) Restore() {
if m.TForm == nil {

View File

@ -19,7 +19,6 @@ import (
"github.com/energye/energy/v2/cef/process"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/logger"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/api"
@ -37,7 +36,7 @@ type ViewsFrameworkBrowserWindow struct {
isClosing bool //
windowType consts.WINDOW_TYPE //窗口类型
windowId int32 //
chromium IChromium //
chromiumBrowser ICEFChromiumBrowser //
component lcl.IComponent //
windowComponent *TCEFWindowComponent //
browserViewComponent *TCEFBrowserViewComponent //
@ -65,13 +64,17 @@ func NewViewsFrameworkBrowserWindow(config *TCefChromiumConfig, windowProperty W
config = NewChromiumConfig()
}
var component = lcl.NewComponent(owner)
chromiumBrowser := &TCEFChromiumBrowser{
chromium: NewChromium(component, config),
}
m := &ViewsFrameworkBrowserWindow{
windowProperty: &windowProperty,
component: component,
chromium: NewChromium(component, config),
chromiumBrowser: chromiumBrowser,
windowComponent: WindowComponentRef.New(component),
browserViewComponent: BrowserViewComponentRef.New(component),
}
chromiumBrowser.window = m
m.SetWindowType(windowProperty.WindowType)
m.Chromium().SetEnableMultiBrowserMode(true)
m.WindowComponent().SetOnWindowCreated(func(window *ICefWindow) {
@ -168,7 +171,7 @@ func appContextInitialized() {
// 设置到 MainBrowser, 主窗口有且仅有一个
BrowserWindow.mainBrowserWindow = vfMainWindow
if m.Config.browserWindowOnEventCallback != nil {
BrowserWindow.browserEvent.chromium = vfMainWindow.chromium
BrowserWindow.browserEvent.chromium = vfMainWindow.Chromium()
m.Config.browserWindowOnEventCallback(BrowserWindow.browserEvent, vfMainWindow)
}
// IPC
@ -224,10 +227,10 @@ func (m *ViewsFrameworkBrowserWindow) Target(targetType ...target.Type) target.I
//
// IPC消息触发当前Chromium
func (m *ViewsFrameworkBrowserWindow) ProcessMessage() target.IProcessMessage {
if m.chromium == nil {
if m.chromiumBrowser == nil {
return nil
}
return m.chromium.(*TCEFChromium)
return m.chromiumBrowser.Chromium().(*TCEFChromium)
}
func (m *ViewsFrameworkBrowserWindow) AsTargetWindow() target.IWindow {
@ -254,54 +257,26 @@ func (m *ViewsFrameworkBrowserWindow) createAfterWindowPropertyForEvent() {
}
}
// registerPopupEvent 注册弹出子窗口事件
func (m *ViewsFrameworkBrowserWindow) registerPopupEvent(isMain bool) {
// WV 窗口的弹出事件
func (m *ViewsFrameworkBrowserWindow) doBeforePopup(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings, resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool {
var bwEvent = BrowserWindow.browserEvent
if !isMain {
// 子窗口关闭流程
m.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onBeforeClose != nil {
flag = bwEvent.onBeforeClose(sender, browser, m)
}
if !flag {
chromiumOnBeforeClose(m, browser)
m.TryCloseWindowAndTerminate()
}
})
m.Chromium().SetOnClose(func(sender lcl.IObject, browser *ICefBrowser, aAction *consts.TCefCloseBrowserAction) {
if bwEvent.onClose != nil {
bwEvent.onClose(sender, browser, aAction, m)
}
})
wp := *m.windowProperty //clone
wp.Url = beforePopupInfo.TargetUrl
wp.WindowType = consts.WT_POPUP_SUB_BROWSER
var vFrameBrowserWindow = NewViewsFrameworkBrowserWindow(NewChromiumConfig(), wp, BrowserWindow.MainWindow().AsViewsFrameworkBrowserWindow().Component())
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, vFrameBrowserWindow, browser, frame, beforePopupInfo, popupFeatures, windowInfo, client, settings, resultExtraInfo, noJavascriptAccess)
}
m.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
if !m.Chromium().Config().EnableOpenUrlTab() {
return true
}
return false
})
m.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings, resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool {
if !m.Chromium().Config().EnableWindowPopup() {
return true
}
wp := *m.windowProperty //clone
wp.Url = beforePopupInfo.TargetUrl
wp.WindowType = consts.WT_POPUP_SUB_BROWSER
var vFrameBrowserWindow = NewViewsFrameworkBrowserWindow(NewChromiumConfig(), wp, BrowserWindow.MainWindow().AsViewsFrameworkBrowserWindow().Component())
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, vFrameBrowserWindow, browser, frame, beforePopupInfo, popupFeatures, windowInfo, client, settings, resultExtraInfo, noJavascriptAccess)
}
if !result {
vFrameBrowserWindow.ResetWindowPropertyForEvent()
vFrameBrowserWindow.EnableAllDefaultEvent()
vFrameBrowserWindow.CreateTopLevelWindow()
vFrameBrowserWindow.createAfterWindowPropertyForEvent()
result = true
}
return result
})
if !result {
vFrameBrowserWindow.ResetWindowPropertyForEvent()
vFrameBrowserWindow.EnableAllDefaultEvent()
vFrameBrowserWindow.CreateTopLevelWindow()
vFrameBrowserWindow.createAfterWindowPropertyForEvent()
result = true
}
return result
}
// ResetWindowPropertyForEvent 重置窗口属性-通过事件函数
@ -357,135 +332,6 @@ func (m *ViewsFrameworkBrowserWindow) ResetWindowPropertyForEvent() {
m.WindowComponent().SetBounds(NewCefRect(wp.X, wp.Y, wp.Width, wp.Height))
}
// registerDefaultEvent 注册默认事件
func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
var bwEvent = BrowserWindow.browserEvent
//默认自定义快捷键
defaultAcceleratorCustom()
m.Chromium().SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool {
if bwEvent.onProcessMessageReceived != nil {
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message, m)
}
return false
})
m.Chromium().SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *consts.TCefReturnValue) {
if assetserve.AssetsServerHeaderKeyValue != "" {
if application.IsSpecVer49() {
headerMap := request.GetHeaderMap()
headerMap.Append(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue)
request.SetHeaderMap(headerMap)
headerMap.Free()
} else {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
}
}
if bwEvent.onBeforeResourceLoad != nil {
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result, m)
}
})
m.Chromium().SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
if bwEvent.onBeforeDownload != nil {
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback, m)
} else {
// 默认保存到当前执行文件所在目录
callback.Cont(consts.ExeDir+consts.Separator+suggestedName, true)
}
})
m.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model, m)
}
if !flag {
chromiumOnBeforeContextMenu(m, browser, frame, params, model)
}
})
m.Chromium().SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool {
var result bool
if bwEvent.onContextMenuCommand != nil {
result = bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, m)
}
if !result {
result = chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags)
}
return result
})
m.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onAfterCreated != nil {
flag = bwEvent.onAfterCreated(sender, browser, m)
}
if !flag {
chromiumOnAfterCreate(m, browser)
}
})
m.Chromium().SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool) {
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, osEvent, m, result)
}
if !*result {
if m.WindowType() == consts.WT_DEV_TOOLS || m.WindowType() == consts.WT_VIEW_SOURCE {
return
}
if m.Chromium().Config().EnableDevTools() {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
}
}
if KeyAccelerator.accelerator(browser, event, result) {
return
}
}
})
m.Chromium().SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
chromiumOnBeforeBrowser(m, browser, frame, request) // default impl
if bwEvent.onBeforeBrowser != nil {
return bwEvent.onBeforeBrowser(sender, browser, frame, request, userGesture, isRedirect, m)
}
return false
})
m.Chromium().SetOnTitleChange(func(sender lcl.IObject, browser *ICefBrowser, title string) {
if bwEvent.onTitleChange != nil {
bwEvent.onTitleChange(sender, browser, title, m)
}
})
m.Chromium().SetOnDragEnter(func(sender lcl.IObject, browser *ICefBrowser, dragData *ICefDragData, mask consts.TCefDragOperations, result *bool) {
*result = !m.WindowProperty().EnableDragFile
if bwEvent.onDragEnter != nil {
bwEvent.onDragEnter(sender, browser, dragData, mask, m, result)
}
})
m.Chromium().SetOnLoadEnd(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32) {
if bwEvent.onLoadEnd != nil {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode, m)
}
})
if m.WindowProperty().EnableWebkitAppRegion {
m.Chromium().SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m)
}
m.regions = regions
m.WindowComponent().SetDraggableRegions(regions.Regions())
})
}
if localLoadRes.enable() {
m.Chromium().SetOnGetResourceHandler(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler) {
//var flag bool
if bwEvent.onGetResourceHandler != nil {
resourceHandler, _ = bwEvent.onGetResourceHandler(sender, browser, frame, request, m)
}
//if !flag {
// resourceHandler = localLoadRes.getResourceHandler(browser, frame, request)
//}
return
})
}
}
// Created 窗口是否创建完, m.CreateTopLevelWindow() 之后
func (m *ViewsFrameworkBrowserWindow) Created() bool {
return m.created
@ -493,8 +339,8 @@ func (m *ViewsFrameworkBrowserWindow) Created() bool {
// EnableAllDefaultEvent 启用所有默认事件行为
func (m *ViewsFrameworkBrowserWindow) EnableAllDefaultEvent() {
m.registerPopupEvent(m.WindowType() == consts.WT_MAIN_BROWSER)
m.registerDefaultEvent()
m.chromiumBrowser.RegisterDefaultPopupEvent()
m.chromiumBrowser.RegisterDefaultEvent()
m.canEnableDefaultEvent = true
}
@ -650,7 +496,7 @@ func (m *ViewsFrameworkBrowserWindow) Browser() *ICefBrowser {
// Chromium 返回 chromium
func (m *ViewsFrameworkBrowserWindow) Chromium() IChromium {
return m.chromium
return m.chromiumBrowser.Chromium()
}
// Id 获取窗口ID

View File

@ -11,6 +11,9 @@
package cef
import (
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/pkgs/assetserve"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
@ -24,26 +27,44 @@ type ICEFChromiumBrowser interface {
Chromium() IChromium // 返回 chromium
WindowParent() ICEFWindowParent // 返回 chromium window 组件
IsCreated() bool // 创建浏览器是否成功
SetSelfWindow(selfWindow IBrowserWindow) // 设置当前Chromium自己所属的window对象
// RegisterDefaultEvent 注册默认Chromium事件
// 如果希望所有默认实现的事件都被注册成功,在使用 NewChromiumBrowser 创建时 owner 参数非 IBrowserWindow
// 需要在创建Browser之前设置当前Chromium的所属Window, 使用 SetSelfWindow 函数
RegisterDefaultEvent()
// RegisterDefaultPopupEvent 注册弹出子窗口事件
// 如果希望所有默认实现的事件都被注册成功,在使用 NewChromiumBrowser 创建时 owner 参数非 IBrowserWindow
// 需要在创建Browser之前设置当前Chromium的所属Window, 使用 SetSelfWindow 函数
RegisterDefaultPopupEvent()
BroderDirectionAdjustments() et.BroderDirectionAdjustments // 返回可以调整窗口大小的边框方向, 默认所有方向
SetBroderDirectionAdjustments(val et.BroderDirectionAdjustments) // 设置可以调整窗口大小的边框方向, 默认所有方向
}
// TCEFChromiumBrowser
//
// CEFChromium浏览器包装结构
type TCEFChromiumBrowser struct {
chromium IChromium // chromium
windowParent ICEFWindowParent // chromium window 组件
isCreated bool // chromium browser is created
createTimer *lcl.TTimer // loop check and create chromium browser
windowName string
context *ICefRequestContext
extraInfo *ICefDictionaryValue
window IBrowserWindow // chromium 所属窗口
chromium IChromium // chromium
windowParent ICEFWindowParent // chromium window 组件
isCreated bool // chromium browser is created
createTimer *lcl.TTimer // loop check and create chromium browser
windowName string //
context *ICefRequestContext //
extraInfo *ICefDictionaryValue //
broderDirectionAdjustments et.BroderDirectionAdjustments //可以调整窗口大小的边框方向, 默认所有方向
}
// NewChromiumBrowser
//
// 初始创建一个 chromium 浏览器
// 当 owner 参数是 IBrowserWindow 类型时将此参数设置为当前chromium所属的窗口
func NewChromiumBrowser(owner lcl.IWinControl, config *TCefChromiumConfig) ICEFChromiumBrowser {
var m = new(TCEFChromiumBrowser)
// owner是窗口直接设置到selfWindow
if window, ok := owner.(IBrowserWindow); ok {
m.window = window
}
m.chromium = NewChromium(owner, config)
m.windowParent = NewCEFWindowParent(owner)
m.windowParent.SetParent(owner)
@ -55,6 +76,7 @@ func NewChromiumBrowser(owner lcl.IWinControl, config *TCefChromiumConfig) ICEFC
m.createTimer.SetInterval(200)
m.createTimer.SetEnabled(false)
m.createTimer.SetOnTimer(m.checkAndCreateBrowser)
m.broderDirectionAdjustments = et.NewSet(et.BdaTop, et.BdaTopRight, et.BdaRight, et.BdaBottomRight, et.BdaBottom, et.BdaBottomLeft, et.BdaLeft, et.BdaTopLeft)
return m
}
@ -87,6 +109,16 @@ func (m *TCEFChromiumBrowser) SetCreateBrowserExtraInfo(windowName string, conte
m.extraInfo = extraInfo
}
// BroderDirectionAdjustments 可以调整窗口大小的边框方向, 默认所有方向
func (m *TCEFChromiumBrowser) BroderDirectionAdjustments() et.BroderDirectionAdjustments {
return m.broderDirectionAdjustments
}
// SetBroderDirectionAdjustments 设置可以调整窗口大小的边框方向, 默认所有方向
func (m *TCEFChromiumBrowser) SetBroderDirectionAdjustments(val et.BroderDirectionAdjustments) {
m.broderDirectionAdjustments = val
}
// CreateBrowser
//
// 创建浏览器
@ -115,3 +147,187 @@ func (m *TCEFChromiumBrowser) WindowParent() ICEFWindowParent {
func (m *TCEFChromiumBrowser) IsCreated() bool {
return m.isCreated
}
// SetSelfWindow
//
// 设置当前Chromium自己所属的window对象
func (m *TCEFChromiumBrowser) SetSelfWindow(selfWindow IBrowserWindow) {
m.window = selfWindow
}
func (m *TCEFChromiumBrowser) RegisterDefaultEvent() {
var bwEvent = BrowserWindow.browserEvent
m.Chromium().SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool {
if bwEvent.onProcessMessageReceived != nil {
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message, m.window)
}
return false
})
m.Chromium().SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *consts.TCefReturnValue) {
if assetserve.AssetsServerHeaderKeyValue != "" {
if application.IsSpecVer49() {
headerMap := request.GetHeaderMap()
headerMap.Append(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue)
request.SetHeaderMap(headerMap)
headerMap.Free()
} else {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
}
}
if bwEvent.onBeforeResourceLoad != nil {
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result, m.window)
}
})
//事件可以被覆盖
m.Chromium().SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
if bwEvent.onBeforeDownload != nil {
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback, m.window)
} else {
// 默认保存到当前执行文件所在目录
callback.Cont(consts.ExeDir+consts.Separator+suggestedName, true)
}
})
m.Chromium().SetOnLoadEnd(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32) {
if bwEvent.onLoadEnd != nil {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode, m.window)
}
})
if localLoadRes.enable() {
m.Chromium().SetOnGetResourceHandler(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler) {
//var flag bool
if bwEvent.onGetResourceHandler != nil {
resourceHandler, _ = bwEvent.onGetResourceHandler(sender, browser, frame, request, m.window)
}
//if !flag {
// resourceHandler = localLoadRes.getResourceHandler(browser, frame, request)
//}
return
})
}
if m.window != nil {
m.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model, m.window)
}
if !flag {
chromiumOnBeforeContextMenu(m.window, browser, frame, params, model)
}
})
m.Chromium().SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool {
var result bool
if bwEvent.onContextMenuCommand != nil {
result = bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, m.window)
}
if !result {
result = chromiumOnContextMenuCommand(m.window, browser, frame, params, commandId, eventFlags)
}
return result
})
m.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onAfterCreated != nil {
flag = bwEvent.onAfterCreated(sender, browser, m.window)
}
if !flag {
chromiumOnAfterCreate(m.window, browser)
}
})
//事件可以被覆盖
m.Chromium().SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool) {
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, osEvent, m.window, result)
}
if !*result {
if m.window == nil || m.window.WindowType() == consts.WT_DEV_TOOLS || m.window.WindowType() == consts.WT_VIEW_SOURCE {
return
}
if m.Chromium().Config().EnableDevTools() {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
}
}
if KeyAccelerator.accelerator(browser, event, result) {
return
}
}
})
m.Chromium().SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
chromiumOnBeforeBrowser(m.window, browser, frame, request) // default impl
if bwEvent.onBeforeBrowser != nil {
return bwEvent.onBeforeBrowser(sender, browser, frame, request, userGesture, isRedirect, m.window)
}
return false
})
m.Chromium().SetOnTitleChange(func(sender lcl.IObject, browser *ICefBrowser, title string) {
updateBrowserDevTools(m.window, browser, title)
if bwEvent.onTitleChange != nil {
bwEvent.onTitleChange(sender, browser, title, m.window)
}
})
m.Chromium().SetOnDragEnter(func(sender lcl.IObject, browser *ICefBrowser, dragData *ICefDragData, mask consts.TCefDragOperations, result *bool) {
*result = !m.window.WindowProperty().EnableDragFile
if bwEvent.onDragEnter != nil {
bwEvent.onDragEnter(sender, browser, dragData, mask, m.window, result)
}
})
if m.window.WindowProperty().EnableWebkitAppRegion {
m.Chromium().SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m.window)
}
if m.window.IsLCL() {
m.window.AsLCLBrowserWindow().BrowserWindow().cwcap.regions = regions
m.window.AsLCLBrowserWindow().BrowserWindow().setDraggableRegions()
} else {
m.window.AsViewsFrameworkBrowserWindow().BrowserWindow().regions = regions
m.window.AsViewsFrameworkBrowserWindow().WindowComponent().SetDraggableRegions(regions.Regions())
}
})
}
}
// 注册windows下CompMsg事件, CEF 组件消息事件
m.registerWindowsCompMsgEvent()
}
func (m *TCEFChromiumBrowser) RegisterDefaultPopupEvent() {
var bwEvent = BrowserWindow.browserEvent
if m.window != nil {
if m.window.IsViewsFramework() {
isMain := m.window.WindowType() == consts.WT_MAIN_BROWSER
if !isMain {
// 子窗口关闭流程
m.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onBeforeClose != nil {
flag = bwEvent.onBeforeClose(sender, browser, m.window)
}
if !flag {
chromiumOnBeforeClose(m.window, browser)
m.window.AsViewsFrameworkBrowserWindow().BrowserWindow().TryCloseWindowAndTerminate()
}
})
m.Chromium().SetOnClose(func(sender lcl.IObject, browser *ICefBrowser, aAction *consts.TCefCloseBrowserAction) {
if bwEvent.onClose != nil {
bwEvent.onClose(sender, browser, aAction, m.window)
}
})
}
}
m.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
if !m.Chromium().Config().EnableOpenUrlTab() {
return true
}
return false
})
m.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupFeatures *TCefPopupFeatures, windowInfo *TCefWindowInfo, client *ICefClient, settings *TCefBrowserSettings, resultExtraInfo *ICefDictionaryValue, noJavascriptAccess *bool) bool {
if !m.Chromium().Config().EnableWindowPopup() {
return true
}
return m.window.doBeforePopup(sender, browser, frame, beforePopupInfo, popupFeatures, windowInfo, client, settings, resultExtraInfo, noJavascriptAccess)
})
}
}

View File

@ -0,0 +1,18 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build !windows
// +build !windows
package cef
// 非windows 没有 CompMsg 事件
func (m *TCEFChromiumBrowser) registerWindowsCompMsgEvent() {
}

View File

@ -0,0 +1,57 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build windows
// +build windows
package cef
import (
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
// 注册windows下CompMsg事件
func (m *TCEFChromiumBrowser) registerWindowsCompMsgEvent() {
if m.window != nil {
window := m.window.AsLCLBrowserWindow().BrowserWindow()
var bwEvent = BrowserWindow.browserEvent
m.Chromium().SetOnRenderCompMsg(func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if bwEvent.onRenderCompMsg != nil {
bwEvent.onRenderCompMsg(sender, message, lResult, aHandled)
}
if !*aHandled {
window.doOnRenderCompMsg(m, cmtCEF, message, lResult, aHandled)
}
})
// TODO 暂时不使用
//m.SetOnWndProc(func(msg *types.TMessage) {
// var (
// tmpHandled bool
// lResult types.LRESULT
// )
// m.doOnRenderCompMsg(cmtLCL, msg, &lResult, &tmpHandled)
// if tmpHandled {
// msg.Result = lResult
// }
//})
if window.WindowProperty().EnableWebkitAppRegion && window.WindowProperty().EnableWebkitAppRegionDClk {
window.windowResize = func(sender lcl.IObject) bool {
if window.WindowState() == types.WsMaximized && (window.WindowProperty().EnableHideCaption || window.BorderStyle() == types.BsNone || window.BorderStyle() == types.BsSingle) {
var monitor = window.Monitor().WorkareaRect()
window.SetBounds(monitor.Left, monitor.Top, monitor.Right-monitor.Left, monitor.Bottom-monitor.Top)
window.SetWindowState(types.WsMaximized)
}
return false
}
}
}
}

View File

@ -17,9 +17,12 @@ import (
"github.com/energye/energy/v2/cef/ipc"
"github.com/energye/energy/v2/cef/ipc/context"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/examples/common/tray"
"github.com/energye/energy/v2/pkgs/assetserve"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl/rtl/version"
"github.com/energye/golcl/lcl/types"
"github.com/energye/golcl/lcl/types/colors"
"github.com/energye/golcl/pkgs/libname"
)
//go:embed resources
@ -30,6 +33,7 @@ var resources embed.FS
// go build -ldflags "-s -w"
func main() {
libname.LibName = "C:\\Users\\Administrator\\golcl\\lcl_liblcl.dll"
//命令: go generate 生成内置资源
//resources := assets.AssetFile()
//全局初始化 每个应用都必须调用的
@ -48,7 +52,8 @@ func main() {
cef.BrowserWindow.Config.Title = "Energy Vue + ElementUI 示例"
cef.BrowserWindow.Config.Width = 1366
chromiumConfig := cef.BrowserWindow.Config.ChromiumConfig()
chromiumConfig.SetEnableMenu(false) //禁用右键菜单
chromiumConfig.SetEnableMenu(false) //禁用右键菜单
chromiumConfig.SetEnableWindowPopup(false) //禁用弹
//监听窗口状态事件
ipc.On("window-state", func(context context.IContext) {
@ -83,10 +88,50 @@ func main() {
//window.AsLCLBrowserWindow().FramelessForLine()
if window.IsLCL() && common.IsWindows() {
// 边框圆角, 仅LCL
window.AsLCLBrowserWindow().SetRoundRectRgn(10)
//window.AsLCLBrowserWindow().SetRoundRectRgn(10) // WindowParent 未铺满窗口会有严重的闪烁
bw := window.AsLCLBrowserWindow().BrowserWindow()
bw.SetColor(colors.ClBrown)
bw.WindowParent().RevertCustomAnchors()
var borderSpace int32 = 2
bw.WindowParent().SetTop(borderSpace + 35)
bw.WindowParent().SetLeft(borderSpace)
bw.WindowParent().SetWidth(bw.Width() - borderSpace*2)
bw.WindowParent().SetHeight(bw.Height() - borderSpace*2 - 35)
bw.WindowParent().SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight, types.AkBottom))
// 禁止窗口边框指定方向拖拽调整大小
bda := bw.BroderDirectionAdjustments()
fmt.Println("BroderDirectionAdjustments 1:", bda.In(et.BdaTopLeft))
bda = bda.Exclude(et.BdaTopLeft, et.BdaTop, et.BdaTopRight) //禁用 左上, 上, 右上
fmt.Println("BroderDirectionAdjustments 1:", bda.In(et.BdaTopLeft))
bw.SetBroderDirectionAdjustments(bda)
// 创建一个自定义chromium
chromium := cef.NewChromiumBrowser(bw, window.Chromium().Config())
bda = chromium.BroderDirectionAdjustments()
fmt.Println("BroderDirectionAdjustments 2:", bda.In(et.BdaBottomLeft))
bda = bda.Exclude(et.BdaBottomLeft, et.BdaBottom, et.BdaBottomRight) //禁用 左下, 下, 右下
fmt.Println("BroderDirectionAdjustments 2:", bda.In(et.BdaBottomLeft))
chromium.SetBroderDirectionAdjustments(bda)
// 设置在窗口显示的位置
part := chromium.WindowParent()
part.SetHeight(35)
part.SetTop(borderSpace)
part.SetLeft(borderSpace)
part.SetWidth(bw.Width() - borderSpace*2)
part.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight))
chromium.Chromium().SetDefaultURL("https://www.baidu.com/")
chromium.RegisterDefaultEvent()
//chromium.RegisterDefaultPopupEvent()
chromium.CreateBrowser()
//browserWindow := cef.NewBrowserWindow()
//browserWindow.EnableAllDefaultEvent()
}
if window.IsLCL() {
tray.LCLTray(window)
//tray.LCLTray(window)
}
})
//在主进程启动成功之后执行

View File

@ -13,6 +13,7 @@ package types
import (
"github.com/energye/golcl/lcl/api"
lcltypes "github.com/energye/golcl/lcl/types"
"unsafe"
)
@ -448,3 +449,30 @@ func (m *HRGN) Free() {
func (m *HRGN) Instance() uintptr {
return uintptr(m.instance)
}
// TSet 定义和 LCL TSet 一样,方便使用
type TSet = lcltypes.TSet
// NewSet
//
// 新建TSet初始值为0然后添加元素
func NewSet(opts ...uint8) TSet {
return lcltypes.NewSet(opts...)
}
// BroderDirectionAdjustment 边框方向调整集合
type BroderDirectionAdjustment = uint8
const (
BdaTop = iota
BdaTopRight
BdaRight
BdaBottomRight
BdaBottom
BdaBottomLeft
BdaLeft
BdaTopLeft
)
// BroderDirectionAdjustments SET
type BroderDirectionAdjustments = TSet