mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-20 19:09:29 +08:00
[windows] WIP
This commit is contained in:
parent
34896ccb4e
commit
829a829cb4
@ -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
|
||||
|
@ -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
48
v3/internal/w32/LICENSE
Normal 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
20
v3/internal/w32/README.md
Normal 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
251
v3/internal/w32/com.go
Normal 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
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
4794
v3/internal/w32/functions.go
Normal file
File diff suppressed because it is too large
Load Diff
29
v3/internal/w32/functions_386.go
Normal file
29
v3/internal/w32/functions_386.go
Normal 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)))
|
||||
}
|
43
v3/internal/w32/functions_amd64.go
Normal file
43
v3/internal/w32/functions_amd64.go
Normal 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
|
||||
}
|
43
v3/internal/w32/functions_arm64.go
Normal file
43
v3/internal/w32/functions_arm64.go
Normal 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
1297
v3/internal/w32/types.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ type WebviewWindowOptions struct {
|
||||
EnableFraudulentWebsiteWarnings bool
|
||||
Zoom float64
|
||||
EnableDragAndDrop bool
|
||||
Windows WindowsWindow
|
||||
}
|
||||
|
||||
var WebviewWindowDefaults = &WebviewWindowOptions{
|
||||
|
5
v3/pkg/application/options_windows.go
Normal file
5
v3/pkg/application/options_windows.go
Normal file
@ -0,0 +1,5 @@
|
||||
package application
|
||||
|
||||
type WindowsWindow struct {
|
||||
AlwaysOnTop bool
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user