U: frameless for windows LCL, Border style reflects,

This commit is contained in:
杨红岩 2024-08-09 10:56:15 +08:00
parent b67cee543b
commit 9a04bce443
15 changed files with 141 additions and 615 deletions

View File

@ -54,7 +54,6 @@ type BrowserEvent struct {
onContextMenuCommand chromiumEventOnContextMenuCommandEx //default can cover
onBeforeContextMenu chromiumEventOnBeforeContextMenuEx //default can cover
onBeforeResourceLoad chromiumEventOnBeforeResourceLoadEx //default
onRenderCompMsg chromiumEventOnCompMsg //default windows
onGetResourceHandler chromiumEventOnGetResourceHandlerEx //default
}
@ -123,10 +122,6 @@ func (m *lclBrowserWindow) OnFormCreate(sender lcl.IObject) {
//browserWindowOnEventCallback 执行完后注册CompMsgEvent
//m.registerWindowsCompMsgEvent()
//自定义窗口标题栏
m.cwcap = &customWindowCaption{
bw: &m.LCLBrowserWindow,
}
//设置 CEF Chromium IPC
ipc.SetProcessMessage(m)
// 如果开启了开发者工具,需要在这里初始化开发者工具窗口
@ -364,13 +359,6 @@ func (m *BrowserEvent) SetOnTitleChange(event chromiumEventOnTitleChangeEx) {
}
}
// SetOnRenderCompMsg windows
func (m *BrowserEvent) SetOnRenderCompMsg(event chromiumEventOnCompMsg) {
if Args.IsMain() {
m.onRenderCompMsg = event
}
}
// SetOnGetResourceHandler
//
// 获取资源处理器,通过该函数自己处理资源获取

View File

@ -59,7 +59,6 @@ type WindowProperty struct {
Url string
Icon string // 窗口图标 加载本地图标 local > /app/resources/icon.ico, VF窗口linux使用png
IconFS string // 窗口图标 加载emfs内置图标 emfs > resources/icon.ico, VF窗口linux使用png
EnableWebkitAppRegion bool //
EnableWebkitAppRegionDClk bool //
EnableHideCaption bool // 窗口 是否隐藏标题栏, VF窗口组件Linux下不能动态控制
EnableMinimize bool // 窗口 是否启用最小化 default: true
@ -198,7 +197,6 @@ func NewWindowProperty() WindowProperty {
EnableResize: true,
EnableClose: true,
EnableCenterWindow: true,
EnableWebkitAppRegion: true,
EnableWebkitAppRegionDClk: true,
EnableMainWindow: true,
X: 100,

View File

@ -11,21 +11,30 @@
package cef
const (
mouseUp = "mouseUp"
mouseDown = "mouseDown"
mouseMove = "mouseMove"
dragUp = 0
dragDown = 1
dragMove = 2
mouseUp = "mouseUp"
mouseDown = "mouseDown"
mouseMove = "mouseMove"
mouseResize = "mouseResize"
mouseDblClick = "mouseDblClick"
)
const (
dragUp = iota
dragDown
dragMove
dragResize
dragDblClick
)
// drag
// custom window drag
// The second method, Implemented using JavaScript, currently suitable for LCL windows on Windows and Mac OS
// VF window is already implemented and supported by default
//
// custom window drag
// The second method, Implemented using JavaScript, currently suitable for LCL windows on Windows and Mac OS
// VF window is already implemented and supported by default
type drag struct {
T int8 // 0:up, 1:down, 2:move
T int8 // data type
X, Y int32 // data mouse point
HT string // mouse ht
window IBrowserWindow // drag window
wx, wy int32 // window point
dx, dy int32 // down mouse point

View File

@ -96,7 +96,7 @@ func dragExtensionHandler() {
drag: {
enableDrag: false,
shouldDrag: false,
cssDragProperty: "--webkit-app-region",
cssDragProperty: "-webkit-app-region",
cssDragValue: "drag",
defaultCursor: null
},
@ -104,7 +104,7 @@ func dragExtensionHandler() {
}
(function () {
energyExtension.drag.war = function (e) {
let v = window.getComputedStyle(e.target).getPropertyValue(energyExtension.drag.cssDragProperty);
let v = window.getComputedStyle(e.target)[energyExtension.drag.cssDragProperty];
if (v) {
v = v.trim();
if (v !== energyExtension.drag.cssDragValue || e.buttons !== 1) {

View File

@ -16,16 +16,14 @@ package cef
import (
"github.com/energye/energy/v2/cef/internal/ipc"
ipcArgument "github.com/energye/energy/v2/cef/ipc/argument"
"strconv"
"github.com/energye/energy/v2/consts/messages"
"github.com/energye/golcl/lcl/types"
"github.com/energye/golcl/lcl/win"
)
// 窗口拖拽JS扩展
// 在这里执行并启用JS拖拽
func dragExtensionJS(frame *ICefFrame, drag bool) {
// Windows2种方式,自定义+webkit 只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现
var executeJS = `
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(drag) + `);
energyExtension.drag.setup();`
func dragExtensionJS(frame *ICefFrame) {
var executeJS = `energyExtension.drag.setup();`
frame.ExecuteJavaScript(executeJS, "", 0)
}
@ -36,105 +34,97 @@ energyExtension.drag.setup();`
func dragExtensionHandler() {
energyExtensionHandler := V8HandlerRef.New()
energyExtensionHandler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if name == mouseDown {
if name == mouseDown || name == mouseUp {
return true
} else if name == mouseUp {
} else if name == mouseMove {
// caption move
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragUp},
Data: &drag{T: dragMove},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseMove {
} else if name == mouseDblClick {
// caption double click
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragDblClick},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseResize {
// window border resize
htValue := arguments.Get(0)
ht := htValue.GetStringValue()
htValue.Free()
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragResize, HT: ht},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
}
return false
})
var code = `
let energyExtension;
if (!energyExtension) {
energyExtension = {
drag: {
enableDrag: false,
shouldDrag: false,
cssDragProperty: "--webkit-app-region",
cssDragValue: "drag",
defaultCursor: null
},
};
}
(function () {
energyExtension.drag.war = function (e) {
let v = window.getComputedStyle(e.target).getPropertyValue(energyExtension.drag.cssDragProperty);
if (v) {
v = v.trim();
if (v !== energyExtension.drag.cssDragValue || e.buttons !== 1) {
return false;
}
return e.detail === 1;
}
return false;
}
energyExtension.drag.mouseMove = function (e) {
if (!energyExtension.drag.enableDrag || !energyExtension.drag.shouldDrag) {
return
}
energyExtension.drag.shouldDrag = false;
native function mouseMove();
mouseMove();
}
energyExtension.drag.mouseUp = function (e) {
if (!energyExtension.drag.enableDrag) {
return
}
energyExtension.drag.shouldDrag = false;
if (energyExtension.drag.war(e)) {
e.preventDefault();
native function mouseUp();
mouseUp();
}
}
energyExtension.drag.mouseDown = function (e) {
if (!energyExtension.drag.enableDrag || ((e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight))) {
return
}
if (energyExtension.drag.war(e)) {
e.preventDefault();
energyExtension.drag.shouldDrag = true;
native function mouseDown();
mouseDown();
} else {
energyExtension.drag.shouldDrag = false;
}
}
energyExtension.drag.setEnableDrag = function (v) {
energyExtension.drag.enableDrag = v;
}
energyExtension.drag.setup = function () {
if (!energyExtension.drag.enableDrag) {
return;
}
window.addEventListener("mousemove", energyExtension.drag.mouseMove);
window.addEventListener("mousedown", energyExtension.drag.mouseDown);
window.addEventListener("mouseup", energyExtension.drag.mouseUp);
}
})();
`
RegisterExtension("energyExtension", code, energyExtensionHandler)
RegisterExtension("energyExtension", string(ipc.IPCJS), energyExtensionHandler)
}
func (m *drag) drag() {
if m.T == dragUp {
if m.window.IsLCL() {
m.window.AsLCLBrowserWindow().BrowserWindow().cwcap.canCaption = false
window := m.window.AsLCLBrowserWindow().BrowserWindow()
switch m.T {
case dragUp:
case dragDown:
case dragMove:
// 全屏时不能拖拽窗口
if window.IsFullScreen() {
return
}
// 此时是 down 事件, 拖拽窗口
if win.ReleaseCapture() {
win.PostMessage(m.window.Handle(), messages.WM_NCLBUTTONDOWN, messages.HTCAPTION, 0)
}
case dragResize:
if window.IsFullScreen() {
return
}
var borderHT uintptr
switch m.HT {
case "n-resize":
borderHT = messages.HTTOP
case "ne-resize":
borderHT = messages.HTTOPRIGHT
case "e-resize":
borderHT = messages.HTRIGHT
case "se-resize":
borderHT = messages.HTBOTTOMRIGHT
case "s-resize":
borderHT = messages.HTBOTTOM
case "sw-resize":
borderHT = messages.HTBOTTOMLEFT
case "w-resize":
borderHT = messages.HTLEFT
case "nw-resize":
borderHT = messages.HTTOPLEFT
}
if borderHT != 0 {
if win.ReleaseCapture() {
win.PostMessage(window.Handle(), messages.WM_NCLBUTTONDOWN, borderHT, 0)
}
}
case dragDblClick:
if window.WindowProperty().EnableWebkitAppRegionDClk {
if window.WindowState() == types.WsNormal {
window.SetWindowState(types.WsMaximized)
} else {
window.SetWindowState(types.WsNormal)
}
}
}
}

View File

@ -54,18 +54,17 @@ type LCLBrowserWindow struct {
onCloseQuery TCloseQueryEvent //扩展事件
onActivateAfter lcl.TNotifyEvent //扩展事件
onDestroy lcl.TNotifyEvent
onWndProc []lcl.TWndProcEvent //扩展事件 向后链试循环调用
onPaint []lcl.TNotifyEvent //扩展事件 向后链试循环调用
auxTools IAuxTools //辅助工具
tray []ITray //托盘 可以同时创建多个
cwcap *customWindowCaption //自定义窗口标题栏
drag *drag //自定义拖拽
wmPaintMessage wmPaint //
wmMoveMessage wmMove //
wmSizeMessage wmSize //
wmWindowPosChangedMessage wmWindowPosChanged //
screen IScreen //屏幕
rgn int //窗口四边圆角
onWndProc []lcl.TWndProcEvent //扩展事件 向后链试循环调用
onPaint []lcl.TNotifyEvent //扩展事件 向后链试循环调用
auxTools IAuxTools //辅助工具
tray []ITray //托盘 可以同时创建多个
drag *drag //自定义拖拽
wmPaintMessage wmPaint //
wmMoveMessage wmMove //
wmSizeMessage wmSize //
wmWindowPosChangedMessage wmWindowPosChanged //
screen IScreen //屏幕
rgn int //窗口四边圆角
oldWndPrc uintptr
}
@ -98,9 +97,6 @@ func NewLCLWindow(windowProperty WindowProperty, owner lcl.IComponent) *LCLBrows
// 窗口设置一个名字
window.TForm.SetName(fmt.Sprintf("Form_%d", time.Now().UnixNano()/1e6))
window.windowProperty = &windowProperty
window.cwcap = &customWindowCaption{
bw: window,
}
window.SetWindowType(windowProperty.WindowType)
window.SetDoubleBuffered(true)
window.FormCreate()
@ -1061,7 +1057,6 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
logger.Debug("chromium.onClose => windowParent.Free")
})
}
m.cwcap.free() //释放自定义标题栏 rgn
}
})
m.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {

View File

@ -78,89 +78,6 @@ func (m *LCLBrowserWindow) SetFocus() {
}
}
//func (m *LCLBrowserWindow) Frameless() {
// var rect = &types.TRect{}
// win.GetWindowRect(m.Handle(), rect)
// win.SetWindowPos(m.Handle(), 0, rect.Left, rect.Top, rect.Right-rect.Left, rect.Bottom-rect.Top, win.SWP_FRAMECHANGED)
//}
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
//标题栏拖拽区域 双击最大化和还原
if m.cwcap.canCaption && m.WindowProperty().EnableWebkitAppRegionDClk && m.WindowProperty().EnableMaximize && !m.IsFullScreen() {
*lResult = messages.HTCAPTION
*aHandled = true
if win.ReleaseCapture() {
if m.WindowState() == types.WsNormal {
win.PostMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_MAXIMIZE, 0)
} else {
win.PostMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_RESTORE, 0)
}
win.SendMessage(m.Handle(), messages.WM_NCLBUTTONUP, messages.HTCAPTION, 0)
}
}
case messages.WM_NCMOUSEMOVE: // 160 nc mouse move
m.cwcap.onNCMouseMove(m.Handle(), message, lResult, aHandled)
case messages.WM_NCLBUTTONDOWN: // 161 nc left down
// 标题栏和边框处理
m.cwcap.onNCLButtonDown(m.Handle(), message, lResult, aHandled)
case messages.WM_NCLBUTTONUP: // 162 nc l up
if m.cwcap.canCaption {
*lResult = messages.HTCAPTION
*aHandled = true
}
case messages.WM_SETCURSOR: // 32 设置鼠标图标样式
m.cwcap.onSetCursor(message, lResult, aHandled)
case messages.WM_NCHITTEST: // 132 NCHITTEST
if m.cwcap.borderMD { //TODO 测试windows7, 161消息之后再次处理132消息导致消息错误
m.cwcap.borderMD = false
return
}
var (
x, y int32 // 鼠标在当前窗口的坐标
caption bool // CEF HTML 自定义标题栏
)
if messageType == cmtCEF {
//鼠标坐标是否在标题区域
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{
X: x,
Y: y,
}
winapi.ScreenToClient(et.HWND(m.Handle()), p)
x, y = p.X, p.Y
}
if caption { //窗口标题栏
*lResult = messages.HTCAPTION
*aHandled = true
} else if m.WindowProperty().EnableHideCaption && m.WindowProperty().EnableResize && m.WindowState() == types.WsNormal { //1.窗口隐藏标题栏 2.启用了调整窗口大小 3.非最大化、最小化、全屏状态
//全屏时不能调整窗口大小
if m.WindowProperty().current.windowState == types.WsFullScreen {
return
}
var rect types.TRect
// 当前类型的消息取出计算的宽高
if messageType == cmtCEF {
rect = chromiumBrowser.WindowParent().BoundsRect()
} else if messageType == cmtLCL {
rect = m.BoundsRect()
}
// 判断当前鼠标是否在边框范围
// 窗口边框和CEF组件边框
handled := m.cwcap.onCanBorder(chromiumBrowser, x, y, rect)
if handled {
// 鼠标在边框位置
*lResult = types.LRESULT(m.cwcap.borderHT)
*aHandled = true
}
}
}
}
// Restore Windows平台窗口还原
func (m *LCLBrowserWindow) Restore() {
if m.TForm == nil {
@ -266,19 +183,7 @@ func (m *LCLBrowserWindow) IsFullScreen() bool {
//}
func (m *LCLBrowserWindow) doDrag() {
// Windows Drag Window
// m.drag != nil 时,这里处理的是 up 事件, 给标题栏标记为false
if m.drag != nil {
m.drag.drag()
} else {
// 全屏时不能拖拽窗口
if m.IsFullScreen() {
return
}
// 此时是 down 事件, 拖拽窗口
if win.ReleaseCapture() {
win.PostMessage(m.Handle(), messages.WM_NCLBUTTONDOWN, messages.HTCAPTION, 0)
m.cwcap.canCaption = true
}
}
}

View File

@ -11,7 +11,6 @@
package cef
import (
"github.com/energye/energy/v2/cef/winapi"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/pkgs/assetserve"
et "github.com/energye/energy/v2/types"
@ -39,10 +38,6 @@ type ICEFChromiumBrowser interface {
RegisterDefaultPopupEvent()
BroderDirectionAdjustments() et.BroderDirectionAdjustments // 返回可以调整窗口大小的边框方向, 默认所有方向
SetBroderDirectionAdjustments(val et.BroderDirectionAdjustments) // 设置可以调整窗口大小的边框方向, 默认所有方向
Rgn() *et.HRGN // Rgn 返回区域
Regions() *TCefDraggableRegions // Regions 返回区域坐标
FreeRgn() // FreeRgn 释放掉rgn
FreeRegions() // FreeRegions 释放掉regions
}
// TCEFChromiumBrowser
@ -59,7 +54,6 @@ type TCEFChromiumBrowser struct {
extraInfo *ICefDictionaryValue //
broderDirectionAdjustments et.BroderDirectionAdjustments //可以调整窗口大小的边框方向, 默认所有方向
regions *TCefDraggableRegions //窗口内html拖拽区域
rgn *et.HRGN //
}
// NewChromiumBrowser
@ -195,11 +189,7 @@ func (m *TCEFChromiumBrowser) RegisterDefaultEvent() {
}
})
m.Chromium().SetOnLoadStart(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, transitionType consts.TCefTransitionType) {
enableWebkitAppRegion := true
if m.window != nil {
enableWebkitAppRegion = m.window.WindowProperty().EnableWebkitAppRegion
}
dragExtensionJS(frame, enableWebkitAppRegion)
dragExtensionJS(frame)
if bwEvent.onLoadStart != nil {
bwEvent.onLoadStart(sender, browser, frame, transitionType, m.window)
}
@ -294,23 +284,18 @@ func (m *TCEFChromiumBrowser) RegisterDefaultEvent() {
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.regions = regions
m.setDraggableRegions()
} else {
m.window.AsViewsFrameworkBrowserWindow().BrowserWindow().regions = regions
m.window.AsViewsFrameworkBrowserWindow().WindowComponent().SetDraggableRegions(regions.Regions())
}
})
}
m.Chromium().SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if m.window.IsLCL() {
// 使用 js drag
} else if m.window.IsViewsFramework() {
m.window.AsViewsFrameworkBrowserWindow().BrowserWindow().regions = regions
m.window.AsViewsFrameworkBrowserWindow().WindowComponent().SetDraggableRegions(regions.Regions())
}
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m.window)
}
})
}
// 注册windows下CompMsg事件, CEF 组件消息事件
m.registerWindowsCompMsgEvent()
}
func (m *TCEFChromiumBrowser) RegisterDefaultPopupEvent() {
@ -351,30 +336,3 @@ func (m *TCEFChromiumBrowser) RegisterDefaultPopupEvent() {
})
}
}
// Rgn 返回区域
func (m *TCEFChromiumBrowser) Rgn() *et.HRGN {
return m.rgn
}
// Regions 返回区域坐标
func (m *TCEFChromiumBrowser) Regions() *TCefDraggableRegions {
return m.regions
}
// FreeRgn 释放掉rgn
func (m *TCEFChromiumBrowser) FreeRgn() {
if m.rgn != nil {
winapi.SetRectRgn(m.rgn, 0, 0, 0, 0)
winapi.DeleteObject(m.rgn)
m.rgn.Free()
}
}
// FreeRegions 释放掉regions
func (m *TCEFChromiumBrowser) FreeRegions() {
if m.regions != nil {
m.regions.regions = nil
m.regions = nil
}
}

View File

@ -1,22 +0,0 @@
//----------------------------------------
//
// 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
// 每一次拖拽区域改变都需要重新设置
func (m *TCEFChromiumBrowser) setDraggableRegions() {
}
// 非windows 没有 CompMsg 事件
func (m *TCEFChromiumBrowser) registerWindowsCompMsgEvent() {
}

View File

@ -1,101 +0,0 @@
//----------------------------------------
//
// 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/energy/v2/cef/winapi"
"github.com/energye/energy/v2/consts"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
// 每一次拖拽区域改变都需要重新设置
func (m *TCEFChromiumBrowser) setDraggableRegions() {
var scp float32
// Windows 10 版本 1607 [仅限桌面应用]
// Windows Server 2016 [仅限桌面应用]
// 可动态调整
dpi, err := winapi.GetDpiForWindow(et.HWND(m.window.Handle()))
if err == nil {
scp = float32(dpi) / 96.0
} else {
// 使用默认的,但不能动态调整
scp = winapi.ScalePercent()
}
//在主线程中运行
RunOnMainThread(func() {
if m.rgn == nil {
//第一次时创建RGN
m.rgn = winapi.CreateRectRgn(0, 0, 0, 0)
} else {
//每次重置RGN
winapi.SetRectRgn(m.rgn, 0, 0, 0, 0)
}
// 重新根据缩放比计算新的区域位置
for i := 0; i < m.regions.RegionsCount(); i++ {
region := m.regions.Region(i)
x := int32(float32(region.Bounds.X) * scp)
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)
if region.Draggable {
winapi.CombineRgn(m.rgn, m.rgn, creRGN, consts.RGN_OR)
} else {
winapi.CombineRgn(m.rgn, m.rgn, creRGN, consts.RGN_DIFF)
}
winapi.DeleteObject(creRGN)
}
})
}
// 注册windows下CompMsg事件
func (m *TCEFChromiumBrowser) registerWindowsCompMsgEvent() {
if m.window != nil && m.window.IsLCL() {
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.cwcap != nil {
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

@ -63,10 +63,6 @@ func chromiumOnBeforeBrowser(window IBrowserWindow, browser *ICefBrowser, frame
return
}
BrowserWindow.PutWindowInfo(browser, window)
// 只LCL窗口使用自定义的窗口拖拽
if window.IsLCL() {
dragExtensionJS(frame, window.WindowProperty().EnableWebkitAppRegion) // drag extension
}
// 方式二 本地资源加载处理器
//localLoadRes.getSchemeHandlerFactory(window, browser) // TODO
}

View File

@ -1,24 +0,0 @@
//----------------------------------------
//
// 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
// TODO no
type customWindowCaption struct {
bw *LCLBrowserWindow
regions *TCefDraggableRegions
}
func (m *customWindowCaption) free() {
//TODO no
}

View File

@ -1,169 +0,0 @@
//----------------------------------------
//
// 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/energy/v2/cef/winapi"
"github.com/energye/energy/v2/consts/messages"
et "github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl/rtl"
"github.com/energye/golcl/lcl/types"
"github.com/energye/golcl/lcl/win"
)
// customWindowCaption 自定义窗口标题栏
//
// 当隐藏窗口标题栏时, 自定义窗口标题栏通过html+css自定义窗口标题栏实现窗口拖拽等
type customWindowCaption struct {
bw IBrowserWindow //
canCaption bool //当前鼠标是否在标题栏区域
canBorder bool //当前鼠标是否在边框
borderHT, borderWMSZ int //borderHT: 鼠标所在边框位置, borderWMSZ: 窗口改变大小边框方向 borderMD:
borderMD bool //borderMD: 鼠标调整窗口大小已按下后再次接收到132消息应该忽略该消息
}
// free
func (m *customWindowCaption) free() {
if m != nil {
cb := m.bw.(*LCLBrowserWindow).chromiumBrowser
if cb != nil {
cb.FreeRgn()
cb.FreeRegions()
}
}
}
// onNCMouseMove NC 非客户区鼠标移动
func (m *customWindowCaption) onNCMouseMove(hWND types.HWND, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canCaption { // 当前在标题栏
} else if m.canBorder { // 当前在边框
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
}
}
// onSetCursor 设置鼠标图标
func (m *customWindowCaption) onSetCursor(message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canBorder { //当前在边框
switch winapi.LOWORD(uint32(message.LParam)) {
case messages.HTBOTTOMRIGHT, messages.HTTOPLEFT: //右下 左上
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
winapi.SetCursor(winapi.LoadCursor(0, messages.IDC_SIZENWSE))
case messages.HTRIGHT, messages.HTLEFT: //右 左
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
winapi.SetCursor(winapi.LoadCursor(0, messages.IDC_SIZEWE))
case messages.HTTOPRIGHT, messages.HTBOTTOMLEFT: //右上 左下
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
winapi.SetCursor(winapi.LoadCursor(0, messages.IDC_SIZENESW))
case messages.HTTOP, messages.HTBOTTOM: //上 下
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
winapi.SetCursor(winapi.LoadCursor(0, messages.IDC_SIZENS))
}
}
}
// 鼠标是否在边框,并返回当前鼠标样式
func (m *customWindowCaption) onCanBorder(chromiumBrowser ICEFChromiumBrowser, x, y int32, windowRect types.TRect) bool {
width := windowRect.Width()
height := windowRect.Height()
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 && 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 && 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 && 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 && 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 && 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 && 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 && bda.In(et.BdaRight) { // 右
m.borderWMSZ = messages.WMSZ_RIGHT
m.borderHT = messages.HTRIGHT
return true
}
return false
}
// onNCLButtonDown NC 鼠标左键按下
func (m *customWindowCaption) onNCLButtonDown(hWND types.HWND, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canCaption { // 标题栏
*lResult = messages.HTCAPTION
*aHandled = true
//全屏时不能移动窗口
if m.bw.IsFullScreen() {
return
}
x, y := m.toPoint(message)
m.borderMD = true
if win.ReleaseCapture() {
win.PostMessage(hWND, messages.WM_NCLBUTTONDOWN, messages.HTCAPTION, rtl.MakeLParam(uint16(x), uint16(y)))
}
} else if m.canBorder { // 边框
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
x, y := m.toPoint(message)
m.borderMD = true
if win.ReleaseCapture() {
win.PostMessage(hWND, messages.WM_SYSCOMMAND, uintptr(messages.SC_SIZE|m.borderWMSZ), rtl.MakeLParam(uint16(x), uint16(y)))
}
}
}
// toPoint 转换XY坐标
func (m *customWindowCaption) toPoint(message *types.TMessage) (x, y int32) {
return winapi.GET_X_LPARAM(message.LParam), winapi.GET_Y_LPARAM(message.LParam)
}
// 鼠标是否在标题栏区域
//
// 如果启用了css拖拽则校验拖拽区域,否则只返回相对于浏览器窗口的x,y坐标
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 -= chromiumBrowser.WindowParent().Left()
p.Y -= chromiumBrowser.WindowParent().Top()
if m.bw.WindowProperty().EnableWebkitAppRegion && chromiumBrowser.Rgn() != nil {
m.canCaption = winapi.PtInRegion(chromiumBrowser.Rgn(), p.X, p.Y)
} else {
m.canCaption = false
}
return p.X, p.Y, m.canCaption
}

View File

@ -15,6 +15,7 @@
package ipc
import (
_ "embed"
"github.com/energye/energy/v2/cef/internal/cef"
"github.com/energye/energy/v2/cef/ipc/callback"
"github.com/energye/energy/v2/cef/ipc/context"
@ -26,6 +27,9 @@ import (
"time"
)
//go:embed ipc.js
var IPCJS []byte
var (
isMainProcess bool
isSubProcess bool

View File

@ -186,30 +186,29 @@ func (m *ipcBrowserProcess) registerEvent() {
})
// window drag
ipc.BrowserChan().AddCallback(func(channelId int64, argument ipcArgument.IList) bool {
if argument != nil {
if argument.GetName() == internalIPCDRAG {
if wi := BrowserWindow.GetWindowInfo(argument.BrowserId()); wi != nil {
// LCL
if wi.IsLCL() {
dataJSON := argument.JSON()
if dataJSON != nil {
bw := wi.AsLCLBrowserWindow().BrowserWindow()
if bw.drag == nil {
bw.drag = &drag{}
if argument != nil && argument.GetName() == internalIPCDRAG {
if wi := BrowserWindow.GetWindowInfo(argument.BrowserId()); wi != nil {
if wi.IsLCL() {
window := wi.AsLCLBrowserWindow().BrowserWindow()
dataJSON := argument.JSON()
if dataJSON != nil {
if window.drag == nil {
window.drag = &drag{
window: wi,
}
object := dataJSON.JSONObject()
bw.drag.T = int8(object.GetIntByKey("T"))
bw.drag.X = int32(object.GetIntByKey("X"))
bw.drag.Y = int32(object.GetIntByKey("Y"))
bw.drag.window = wi
}
RunOnMainThread(func() {
wi.AsLCLBrowserWindow().BrowserWindow().doDrag()
})
object := dataJSON.JSONObject()
window.drag.T = int8(object.GetIntByKey("T"))
window.drag.X = int32(object.GetIntByKey("X"))
window.drag.Y = int32(object.GetIntByKey("Y"))
window.drag.HT = object.GetStringByKey("HT")
}
RunOnMainThread(func() {
window.doDrag()
})
}
return true
}
return true
}
return false
})