A: TForm WM Message

This commit is contained in:
yanghy 2023-07-20 19:52:58 +08:00
parent d031f81689
commit 58a23467bf
8 changed files with 256 additions and 18 deletions

View File

@ -67,10 +67,8 @@ func Run(app *TCEFApplication) {
// 启动主进程
success := app.StartMainProcess()
if success {
if app.IsUIGtk3() {
//LCL -> Linux 必须在主进程启动之后初始化组件
lclwidget.CustomWidgetSetInitialization()
}
//LCL -> Linux 必须在主进程启动之后初始化组件
lclwidget.CustomWidgetSetInitialization()
// 主进程启动成功之后回调
if browserProcessStartAfterCallback != nil {
browserProcessStartAfterCallback(success)
@ -87,9 +85,7 @@ func Run(app *TCEFApplication) {
}
// LCL窗口
lcl.RunApp(&BrowserWindow.mainBrowserWindow)
if app.IsUIGtk3() {
lclwidget.CustomWidgetSetFinalization()
}
lclwidget.CustomWidgetSetFinalization()
}
}
}

View File

@ -12,20 +12,175 @@
package cef
import (
"github.com/energye/energy/v2/cef/internal/ipc"
ipcArgument "github.com/energye/energy/v2/cef/ipc/argument"
"strconv"
)
// 窗口拖拽JS扩展
// 在这里执行并启用JS拖拽
func dragExtensionJS(frame *ICefFrame) {
// MacOS只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现
// 在MacOS中LCL窗口没有有效的消息事件
var executeJS = `
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(application.EnableWebkitAppRegion()) + `);
energyExtension.drag.setup();`
frame.ExecuteJavaScript(executeJS, "", 0)
}
// 窗口拖拽JS扩展处理器
// 1. 注册JS扩展到CEF, 注册鼠标事件通过本地函数在Go里处理鼠标事件
// 2. 通过IPC将鼠标消息发送到主进程主进程监听到消息处理鼠标事件
// 3. linux 默认使用VF窗口组件, 所以不需要使用该实现
// 3. macos 使用窗口坐标实现窗口拖拽
func dragExtensionHandler() {
if !application.EnableWebkitAppRegion() {
return
}
energyExtensionHandler := V8HandlerRef.New()
energyExtensionHandler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if name == mouseUp {
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragUp},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseDown {
var dx, dy int32
if arguments.Size() > 0 {
point := arguments.Get(0)
v8ValX := point.getValueByKey("x")
v8ValY := point.getValueByKey("y")
dx = v8ValX.GetIntValue()
dy = v8ValY.GetIntValue()
v8ValX.Free()
v8ValY.Free()
point.Free()
}
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragDown, X: dx, Y: dy},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseMove {
var mx, my int32
if arguments.Size() > 0 {
point := arguments.Get(0)
v8ValX := point.getValueByKey("x")
v8ValY := point.getValueByKey("y")
mx = v8ValX.GetIntValue()
my = v8ValY.GetIntValue()
v8ValX.Free()
v8ValY.Free()
point.Free()
}
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragMove, X: mx, Y: my},
}
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
}
native function mouseMove();
mouseMove({x: e.screenX, y: e.screenY});
}
energyExtension.drag.mouseUp = function (e) {
if (!energyExtension.drag.enableDrag || !energyExtension.drag.shouldDrag) {
return
}
energyExtension.drag.shouldDrag = false;
//document.body.style.cursor = "default";
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({x: e.screenX, y: e.screenY});
} 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)
}
func (m *drag) drag() {
if m.T == dragUp {
if m.window.IsLCL() {
bw := m.window.AsLCLBrowserWindow().BrowserWindow()
bw.drag = nil
m.window = nil
}
} else if m.T == dragDown {
m.dx = m.X
m.dy = m.Y
point := m.window.Point()
m.wx = point.X
m.wy = point.Y
} else if m.T == dragMove {
m.mx = m.X
m.my = m.Y
if m.window.IsLCL() {
x := m.wx + (m.mx - m.dx)
y := m.wy + (m.my - m.dy)
m.window.SetPoint(x, y)
}
}
}

View File

@ -14,12 +14,15 @@ package cef
import (
"fmt"
"github.com/energye/energy/v2/cef/internal/def"
"github.com/energye/energy/v2/cef/internal/window"
. "github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/common/imports"
"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"
t "github.com/energye/energy/v2/types"
"github.com/energye/golcl/energy/emfs"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl"
@ -28,6 +31,7 @@ import (
"github.com/energye/golcl/lcl/types"
"runtime"
"time"
"unsafe"
)
// LCLBrowserWindow 基于CEF lcl 窗口组件
@ -1027,3 +1031,46 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
}
})
}
type messageType int32
const (
mtMove messageType = iota + 1
mtSize
mtWindowPosChanged
)
type wmMove func(message *t.TMove)
type wmSize func(message *t.TSize)
type wmWindowPosChanged func(message *t.TWindowPosChanged)
func (m *LCLBrowserWindow) SetOnWMMove(fn wmMove) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtMove), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) SetOnWMSize(fn wmSize) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtSize), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) SetOnWMWindowPosChanged(fn wmWindowPosChanged) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtWindowPosChanged), api.MakeEventDataPtr(fn))
}
func init() {
lcl.RegisterExtEventCallback(func(fn interface{}, getVal func(idx int) uintptr) bool {
getPtr := func(i int) unsafe.Pointer {
return unsafe.Pointer(getVal(i))
}
switch fn.(type) {
case wmMove:
fn.(wmMove)((*t.TMove)(getPtr(0)))
case wmSize:
fn.(wmSize)((*t.TSize)(getPtr(0)))
case wmWindowPosChanged:
fn.(wmWindowPosChanged)((*t.TWindowPosChanged)(getPtr(0)))
default:
return false
}
return true
})
}

View File

@ -23,6 +23,8 @@ package def
const (
//null nil
null_nil = iota
// TForm
Form_SetOnMessagesEvent
// CEF
LibVersion
LibBuildVersion
@ -232,9 +234,6 @@ const (
CEFApplication_QueueAsyncCall
SetCEFWindowBindCallbackFunc // no impl
SetCEFIPCCallbackFunc // no impl
// GoForm
CEF_AddGoForm // no impl
CEF_RemoveGoForm // no impl
// ICefCallback
CEFCallback_Cont
CEFCallback_Cancel

View File

@ -23,6 +23,8 @@ func init() {
var energyImportDefs = []*dllimports.ImportTable{
//null nil
dllimports.NewEnergyImport("", 0),
// TForm
dllimports.NewEnergyImport("Form_SetOnMessagesEvent", 0),
//CEF
dllimports.NewEnergyImport("LibVersion", 0),
dllimports.NewEnergyImport("LibBuildVersion", 0),
@ -232,9 +234,6 @@ func init() {
dllimports.NewEnergyImport("CEFApplication_QueueAsyncCall", 0),
dllimports.NewEnergyImport("SetCEFWindowBindCallbackFunc", 0),
dllimports.NewEnergyImport("SetCEFIPCCallbackFunc", 0),
//GoForm
dllimports.NewEnergyImport("CEF_AddGoForm", 0),
dllimports.NewEnergyImport("CEF_RemoveGoForm", 0),
//ICefCallback
dllimports.NewEnergyImport("cefCallback_Cont", 0),
dllimports.NewEnergyImport("cefCallback_Cancel", 0),

View File

@ -6,6 +6,7 @@ import (
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/energy/v2/types"
)
//go:embed resources
@ -30,5 +31,14 @@ func main() {
server.Assets = &resources
go server.StartHttpServer()
})
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) {
bw := window.AsLCLBrowserWindow().BrowserWindow()
bw.SetOnWMSize(func(message *types.TSize) {
fmt.Println("SetOnWMSize", message)
})
bw.SetOnWMMove(func(message *types.TMove) {
fmt.Println("SetOnWMMove", message)
})
})
cef.Run(app)
}

View File

@ -44,7 +44,7 @@ func main() {
// LCL macos 隐藏标题栏后,不能调整大小
cef.BrowserWindow.Config.EnableHideCaption = true
// LCL macos 隐藏标题栏后,该选项不生效
cef.BrowserWindow.Config.EnableResize = true
//cef.BrowserWindow.Config.EnableResize = true
}
cef.BrowserWindow.Config.Title = "Energy Vue + ElementUI 示例"
cef.BrowserWindow.Config.Width = 1200

View File

@ -412,3 +412,35 @@ func (m *HRGN) Free() {
func (m *HRGN) Instance() uintptr {
return uintptr(m.instance)
}
type WindowPos struct {
Hwnd HWND
HwndInsertAfter HWND
X Integer
Y Integer
Cx Integer
Cy Integer
Flags UINT
}
type TMove struct {
Msg Cardinal
MoveType PtrInt // 0 = update, 1 = force RequestAlign, 128 = Source is Interface (Widget has moved)
Dummy LPARAM // needed for64 bit alignment
Result LResult
}
type TSize struct {
Msg Cardinal
SizeType PtrInt // see LCLType.pp (e.g. Size_Restored)
Width Word
Height Word
Result LResult
}
type TWindowPosChanged struct {
Msg Cardinal
Unused WPARAM
WindowPos WindowPos
Result LPARAM
}