5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-20 19:09:29 +08:00

[windows] WIP

This commit is contained in:
Lea Anthony 2023-04-26 21:06:41 +10:00 committed by Misite Bao
parent 34896ccb4e
commit 829a829cb4
20 changed files with 11551 additions and 26 deletions

View File

@ -4,6 +4,7 @@ go 1.19
require (
github.com/go-task/task/v3 v3.20.0
github.com/gonutz/w32/v2 v2.7.0
github.com/google/go-cmp v0.5.9
github.com/jackmordaunt/icns/v2 v2.2.1
github.com/json-iterator/go v1.1.12

View File

@ -27,6 +27,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/task/v3 v3.20.0 h1:pTavuhP+AiEpKLzh5I6Lja9Ux7ypYO5QMsEPTbhYEDc=
github.com/go-task/task/v3 v3.20.0/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI=
github.com/gonutz/w32/v2 v2.7.0 h1:O9lx/5tZ+WjZdxdvQFTh+/kP/7y95YCaL5MHqPrIHn4=
github.com/gonutz/w32/v2 v2.7.0/go.mod h1:MgtHx0AScDVNKyB+kjyPder4xIi3XAcHS6LDDU2DmdE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=

48
v3/internal/w32/LICENSE Normal file
View File

@ -0,0 +1,48 @@
The MIT License (MIT)
Copyright (c) 2021 gonutz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This is the license from the original fork that this library is based on:
Copyright (c) 2010-2012 The w32 Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

20
v3/internal/w32/README.md Normal file
View File

@ -0,0 +1,20 @@
This is a fork of [gonutz/w32](https://github.com/gonutz/w32).
-----------------------
About w32
==========
w32 is a wrapper for a number of Windows APIs for the [Go Programming Language](https://golang.org/).
This library has no other dependencies and you need no C-compiler, it is written in pure Go. Some function signatures have been adapted to make them work in Go, e.g. functions that take a pointer to an array and a count of items in C will now simply accept a slice in Go.
If you miss any Windows API functions, just write an issue or create a pull request, the Win32 API is very large and has many rarely used functions in it so this wrapper is supposed to grow as needed by the Go community.
Installation
============
Get the latest version with:
go get github.com/gonutz/w32/v2

251
v3/internal/w32/com.go Normal file
View File

@ -0,0 +1,251 @@
package w32
import (
"errors"
"syscall"
"unicode/utf16"
"unsafe"
)
type pIUnknownVtbl struct {
queryInterface uintptr
addRef uintptr
release uintptr
}
type IUnknown struct {
lpVtbl *pIUnknownVtbl
}
func (u *IUnknown) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
return ComQueryInterface(u, id)
}
func (u *IUnknown) AddRef() int32 {
return ComAddRef(u)
}
func (u *IUnknown) Release() int32 {
return ComRelease(u)
}
type pIDispatchVtbl struct {
queryInterface uintptr
addRef uintptr
release uintptr
getTypeInfoCount uintptr
getTypeInfo uintptr
getIDsOfNames uintptr
invoke uintptr
}
type IDispatch struct {
lpVtbl *pIDispatchVtbl
}
func (d *IDispatch) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
return ComQueryInterface((*IUnknown)(unsafe.Pointer(d)), id)
}
func (d *IDispatch) AddRef() int32 {
return ComAddRef((*IUnknown)(unsafe.Pointer(d)))
}
func (d *IDispatch) Release() int32 {
return ComRelease((*IUnknown)(unsafe.Pointer(d)))
}
func (d *IDispatch) GetIDsOfName(names []string) ([]int32, HRESULT) {
return ComGetIDsOfName(d, names)
}
func (d *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) {
return ComInvoke(d, dispid, dispatch, params...)
}
type pIStreamVtbl struct {
qeryInterface uintptr
addRef uintptr
release uintptr
}
type IStream struct {
lpVtbl *pIStreamVtbl
}
func (s *IStream) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
return ComQueryInterface((*IUnknown)(unsafe.Pointer(s)), id)
}
func (s *IStream) AddRef() int32 {
return ComAddRef((*IUnknown)(unsafe.Pointer(s)))
}
func (s *IStream) Release() int32 {
return ComRelease((*IUnknown)(unsafe.Pointer(s)))
}
func ComAddRef(unknown *IUnknown) int32 {
ret, _, _ := syscall.Syscall(unknown.lpVtbl.addRef, 1,
uintptr(unsafe.Pointer(unknown)),
0,
0)
return int32(ret)
}
func ComRelease(unknown *IUnknown) int32 {
ret, _, _ := syscall.Syscall(unknown.lpVtbl.release, 1,
uintptr(unsafe.Pointer(unknown)),
0,
0)
return int32(ret)
}
func ComQueryInterface(unknown *IUnknown, id *GUID) (*IDispatch, HRESULT) {
var disp *IDispatch
hr, _, _ := syscall.Syscall(unknown.lpVtbl.queryInterface, 3,
uintptr(unsafe.Pointer(unknown)),
uintptr(unsafe.Pointer(id)),
uintptr(unsafe.Pointer(&disp)),
)
return disp, HRESULT(hr)
}
func ComGetIDsOfName(disp *IDispatch, names []string) ([]int32, HRESULT) {
wnames := make([]*uint16, len(names))
dispid := make([]int32, len(names))
for i := 0; i < len(names); i++ {
wnames[i] = syscall.StringToUTF16Ptr(names[i])
}
hr, _, _ := syscall.Syscall6(disp.lpVtbl.getIDsOfNames, 6,
uintptr(unsafe.Pointer(disp)),
uintptr(unsafe.Pointer(IID_NULL)),
uintptr(unsafe.Pointer(&wnames[0])),
uintptr(len(names)),
uintptr(GetUserDefaultLCID()),
uintptr(unsafe.Pointer(&dispid[0])),
)
return dispid, HRESULT(hr)
}
func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
var dispparams DISPPARAMS
if dispatch&DISPATCH_PROPERTYPUT != 0 {
dispnames := [1]int32{DISPID_PROPERTYPUT}
dispparams.RgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
dispparams.CNamedArgs = 1
}
var vargs []VARIANT
if len(params) > 0 {
vargs = make([]VARIANT, len(params))
for i, v := range params {
n := len(params) - i - 1
VariantInit(&vargs[n])
switch v.(type) {
case bool:
if v.(bool) {
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
} else {
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
}
case *bool:
vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
case byte:
vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
case *byte:
vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
case int16:
vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
case *int16:
vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
case uint16:
vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
case *uint16:
vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
case int, int32:
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
case *int, *int32:
vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
case uint, uint32:
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
case *uint, *uint32:
vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
case int64:
vargs[n] = VARIANT{VT_I8, 0, 0, 0, v.(int64)}
case *int64:
vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
case uint64:
vargs[n] = VARIANT{VT_UI8, 0, 0, 0, int64(v.(uint64))}
case *uint64:
vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
case float32:
vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
case *float32:
vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
case float64:
vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
case *float64:
vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
case string:
vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
case *string:
vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
case *IDispatch:
vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
case **IDispatch:
vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
case nil:
vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
case *VARIANT:
vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
default:
return nil, errors.New("w32.ComInvoke: unknown variant type")
}
}
dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
dispparams.CArgs = uint32(len(params))
}
var ret VARIANT
var excepInfo EXCEPINFO
VariantInit(&ret)
hr, _, _ := syscall.Syscall9(disp.lpVtbl.invoke, 8,
uintptr(unsafe.Pointer(disp)),
uintptr(dispid),
uintptr(unsafe.Pointer(IID_NULL)),
uintptr(GetUserDefaultLCID()),
uintptr(dispatch),
uintptr(unsafe.Pointer(&dispparams)),
uintptr(unsafe.Pointer(&ret)),
uintptr(unsafe.Pointer(&excepInfo)),
0)
if hr != 0 {
if excepInfo.BstrDescription != nil {
bs := UTF16PtrToString(excepInfo.BstrDescription)
return nil, errors.New(bs)
}
}
for _, varg := range vargs {
if varg.VT == VT_BSTR && varg.Val != 0 {
SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
}
}
result = &ret
return
}
func UTF16PtrToString(cstr *uint16) string {
if cstr != nil {
us := make([]uint16, 0, 256)
for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 {
u := *(*uint16)(unsafe.Pointer(p))
if u == 0 {
return string(utf16.Decode(us))
}
us = append(us, u)
}
}
return ""
}

4875
v3/internal/w32/constants.go Normal file

File diff suppressed because it is too large Load Diff

4794
v3/internal/w32/functions.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
package w32
// MenuItemFromPoint determines which menu item, if any, is at the specified
// location.
func MenuItemFromPoint(w HWND, m HMENU, screen POINT) int {
ret, _, _ := menuItemFromPoint.Call(
uintptr(w),
uintptr(m),
uintptr(screen.X),
uintptr(screen.Y),
)
return int(ret)
}
func GetClassLongPtr(w HWND, index int) uintptr {
return uintptr(GetClassLong(w, index))
}
func SetClassLongPtr(w HWND, index int, value uintptr) uintptr {
return uintptr(SetClassLong(w, index, int32(value)))
}
func GetWindowLongPtr(hwnd HWND, index int) uintptr {
return uintptr(GetWindowLong(hwnd, index))
}
func SetWindowLongPtr(hwnd HWND, index int, value uintptr) uintptr {
return uintptr(SetWindowLong(hwnd, index, int32(value)))
}

View File

@ -0,0 +1,43 @@
package w32
// MenuItemFromPoint determines which menu item, if any, is at the specified
// location.
func MenuItemFromPoint(w HWND, m HMENU, screen POINT) int {
ret, _, _ := menuItemFromPoint.Call(
uintptr(w),
uintptr(m),
uintptr(uint64(screen.X)<<32|uint64(screen.Y)),
)
return int(ret)
}
func GetClassLongPtr(w HWND, index int) uintptr {
ret, _, _ := getClassLongPtr.Call(uintptr(w), uintptr(index))
return ret
}
func SetClassLongPtr(w HWND, index int, value uintptr) uintptr {
ret, _, _ := setClassLongPtr.Call(
uintptr(w),
uintptr(index),
value,
)
return ret
}
func GetWindowLongPtr(hwnd HWND, index int) uintptr {
ret, _, _ := getWindowLongPtr.Call(
uintptr(hwnd),
uintptr(index),
)
return ret
}
func SetWindowLongPtr(hwnd HWND, index int, value uintptr) uintptr {
ret, _, _ := setWindowLongPtr.Call(
uintptr(hwnd),
uintptr(index),
value,
)
return ret
}

View File

@ -0,0 +1,43 @@
package w32
// MenuItemFromPoint determines which menu item, if any, is at the specified
// location.
func MenuItemFromPoint(w HWND, m HMENU, screen POINT) int {
ret, _, _ := menuItemFromPoint.Call(
uintptr(w),
uintptr(m),
uintptr(uint64(screen.X)<<32|uint64(screen.Y)),
)
return int(ret)
}
func GetClassLongPtr(w HWND, index int) uintptr {
ret, _, _ := getClassLongPtr.Call(uintptr(w), uintptr(index))
return ret
}
func SetClassLongPtr(w HWND, index int, value uintptr) uintptr {
ret, _, _ := setClassLongPtr.Call(
uintptr(w),
uintptr(index),
value,
)
return ret
}
func GetWindowLongPtr(hwnd HWND, index int) uintptr {
ret, _, _ := getWindowLongPtr.Call(
uintptr(hwnd),
uintptr(index),
)
return ret
}
func SetWindowLongPtr(hwnd HWND, index int, value uintptr) uintptr {
ret, _, _ := setWindowLongPtr.Call(
uintptr(hwnd),
uintptr(index),
value,
)
return ret
}

1297
v3/internal/w32/types.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -360,10 +360,10 @@ func (a *App) Run() error {
}
// set the application menu
a.impl.setApplicationMenu(a.ApplicationMenu)
// set the application Icon
a.impl.setIcon(a.options.Icon)
if runtime.GOOS == "darwin" {
a.impl.setApplicationMenu(a.ApplicationMenu)
a.impl.setIcon(a.options.Icon)
}
err := a.impl.run()
if err != nil {

View File

@ -2,9 +2,19 @@
package application
import (
"github.com/samber/lo"
"github.com/wailsapp/wails/v3/internal/w32"
"syscall"
"unsafe"
)
var windowClassName = lo.Must(syscall.UTF16PtrFromString("WailsWebviewWindow"))
type windowsApp struct {
//applicationMenu unsafe.Pointer
parent *App
instance w32.HINSTANCE
}
func (m *windowsApp) dispatchOnMainThread(id uint) {
@ -23,11 +33,9 @@ func (m *windowsApp) getScreens() ([]*Screen, error) {
}
func (m *windowsApp) hide() {
//C.hide()
}
func (m *windowsApp) show() {
//C.show()
}
func (m *windowsApp) on(eventID uint) {
@ -73,6 +81,9 @@ func (m *windowsApp) run() error {
for eventID := range m.parent.applicationEventListeners {
m.on(eventID)
}
_ = m.runMainLoop()
//C.run()
return nil
}
@ -81,9 +92,58 @@ func (m *windowsApp) destroy() {
//C.destroyApp()
}
func newPlatformApp(app *App) *windowsApp {
//C.init()
return &windowsApp{
parent: app,
func (m *windowsApp) init() {
// Register the window class
icon := w32.LoadIconWithResourceID(m.instance, w32.IDI_APPLICATION)
var wc w32.WNDCLASSEX
wc.Size = uint32(unsafe.Sizeof(wc))
wc.Style = w32.CS_HREDRAW | w32.CS_VREDRAW
wc.WndProc = syscall.NewCallback(m.wndProc)
wc.Instance = m.instance
wc.Background = w32.COLOR_BTNFACE + 1
wc.Icon = icon
wc.Cursor = w32.LoadCursorWithResourceID(0, w32.IDC_ARROW)
wc.ClassName = windowClassName
wc.MenuName = nil
wc.IconSm = icon
if ret := w32.RegisterClassEx(&wc); ret == 0 {
panic(syscall.GetLastError())
}
}
func (m *windowsApp) wndProc(hwnd w32.HWND, msg uint32, wParam, lParam uintptr) uintptr {
switch msg {
case w32.WM_SIZE, w32.WM_PAINT:
return 0
case w32.WM_CLOSE:
w32.PostQuitMessage(0)
return 0
}
return w32.DefWindowProc(hwnd, msg, wParam, lParam)
}
func (m *windowsApp) runMainLoop() int {
msg := (*w32.MSG)(unsafe.Pointer(w32.GlobalAlloc(0, uint32(unsafe.Sizeof(w32.MSG{})))))
defer w32.GlobalFree(w32.HGLOBAL(unsafe.Pointer(m)))
for w32.GetMessage(msg, 0, 0, 0) != 0 {
w32.TranslateMessage(msg)
w32.DispatchMessage(msg)
}
return int(msg.WParam)
}
func newPlatformApp(app *App) *windowsApp {
result := &windowsApp{
parent: app,
instance: w32.GetModuleHandle(""),
}
result.init()
return result
}

View File

@ -96,14 +96,3 @@ func (m *Menu) setContextData(data *ContextMenuData) {
func (a *App) NewMenu() *Menu {
return &Menu{}
}
func defaultApplicationMenu() *Menu {
menu := NewMenu()
menu.AddRole(AppMenu)
menu.AddRole(FileMenu)
menu.AddRole(EditMenu)
menu.AddRole(ViewMenu)
menu.AddRole(WindowMenu)
menu.AddRole(HelpMenu)
return menu
}

View File

@ -103,3 +103,14 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) {
}
}
func defaultApplicationMenu() *Menu {
menu := NewMenu()
menu.AddRole(AppMenu)
menu.AddRole(FileMenu)
menu.AddRole(EditMenu)
menu.AddRole(ViewMenu)
menu.AddRole(WindowMenu)
menu.AddRole(HelpMenu)
return menu
}

View File

@ -50,3 +50,13 @@ func (m *windowsMenu) processMenu(parent unsafe.Pointer, menu *Menu) {
//
//}
}
func defaultApplicationMenu() *Menu {
menu := NewMenu()
menu.AddRole(FileMenu)
menu.AddRole(EditMenu)
menu.AddRole(ViewMenu)
menu.AddRole(WindowMenu)
menu.AddRole(HelpMenu)
return menu
}

View File

@ -35,6 +35,7 @@ type WebviewWindowOptions struct {
EnableFraudulentWebsiteWarnings bool
Zoom float64
EnableDragAndDrop bool
Windows WindowsWindow
}
var WebviewWindowDefaults = &WebviewWindowOptions{

View File

@ -0,0 +1,5 @@
package application
type WindowsWindow struct {
AlwaysOnTop bool
}

View File

@ -42,8 +42,9 @@ const (
ZoomOut Role = iota
ToggleFullscreen Role = iota
Minimize Role = iota
Zoom Role = iota
Minimize Role = iota
Zoom Role = iota
FullScreen Role = iota
//Front Role = iota
//WindowRole Role = iota
@ -132,6 +133,12 @@ func newWindowMenu() *MenuItem {
menu := NewMenu()
menu.AddRole(Minimize)
menu.AddRole(Zoom)
if runtime.GOOS == "darwin" {
menu.AddSeparator()
menu.AddRole(FullScreen)
} else {
menu.AddRole(Close)
}
subMenu := newSubMenuItem("Window")
subMenu.submenu = menu
return subMenu

View File

@ -3,6 +3,9 @@
package application
import (
"github.com/samber/lo"
"github.com/wailsapp/wails/v3/internal/w32"
"syscall"
"unsafe"
)
@ -64,8 +67,43 @@ func (w *windowsWebviewWindow) setBackgroundColour(color *RGBA) {
}
func (w *windowsWebviewWindow) run() {
//TODO implement me
panic("implement me")
var exStyle uint
options := w.parent.options
windowsOptions := options.Windows
//if windowsOptions != nil {
exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW
// if windowsOptions.WindowIsTranslucent {
// exStyle |= w32.WS_EX_NOREDIRECTIONBITMAP
// }
//}
if windowsOptions.AlwaysOnTop {
exStyle |= w32.WS_EX_TOPMOST
}
var hwnd w32.HWND
hwnd = w32.CreateWindowEx(
exStyle,
windowClassName,
lo.Must(syscall.UTF16PtrFromString("My Window Title")),
w32.WS_OVERLAPPEDWINDOW|w32.WS_VISIBLE,
w32.CW_USEDEFAULT,
w32.CW_USEDEFAULT,
options.Width,
options.Height,
0,
0,
w32.GetModuleHandle(""),
nil)
if hwnd == 0 {
panic("Unable to create window")
}
if !options.Hidden {
w32.ShowWindow(hwnd, w32.SW_SHOW)
w32.UpdateWindow(hwnd)
}
w32.SetForegroundWindow(hwnd)
}
func (w *windowsWebviewWindow) center() {
@ -242,6 +280,7 @@ func newWindowImpl(parent *WebviewWindow) *windowsWebviewWindow {
result := &windowsWebviewWindow{
parent: parent,
}
return result
}