mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-08 22:33:26 +08:00
[windows] Support AlwaysOnTop, EnableResize at runtime. Added Solid/Transparent/Translucent options.
This commit is contained in:
parent
ef184ec8bf
commit
7f3f51e36b
@ -180,3 +180,25 @@ const MyEnum = {
|
||||
|
||||
- Why use `float64`? Can't we use `int`?
|
||||
- Because JavaScript doesn't have a concept of `int`. Everything is a `number`, which translates to `float64` in Go. There are also restrictions on casting types in Go's reflection package, which means using `int` doesn't work.
|
||||
|
||||
### BackgroundColour
|
||||
|
||||
In v2, this was a pointer to an `RGBA` struct. In v3, this is an `RGBA` struct value.
|
||||
|
||||
### WindowIsTranslucent
|
||||
|
||||
This flag has been removed. Now there is a `BackgroundType` flag that can be used to set the type of background the window should have.
|
||||
This flag can be set to any of the following values:
|
||||
- `BackgroundTypeSolid` - The window will have a solid background
|
||||
- `BackgroundTypeTransparent` - The window will have a transparent background
|
||||
- `BackgroundTypeTranslucent` - The window will have a translucent background
|
||||
|
||||
On Windows, if the `BackgroundType` is set to `BackgroundTypeTranslucent`, the type of translucency can be set using the
|
||||
`BackdropType` flag in the `WindowsWindow` options. This can be set to any of the following values:
|
||||
- `Auto` - The window will use an effect determined by the system
|
||||
- `None` - The window will have no background
|
||||
- `Mica` - The window will use the Mica effect
|
||||
- `Acrylic` - The window will use the acrylic effect
|
||||
- `Tabbed` - The window will use the tabbed effect
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@ 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
|
||||
@ -18,6 +17,7 @@ require (
|
||||
github.com/samber/lo v1.37.0
|
||||
github.com/tc-hib/winres v0.1.6
|
||||
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6
|
||||
golang.org/x/sys v0.7.0
|
||||
modernc.org/sqlite v1.21.0
|
||||
)
|
||||
|
||||
@ -54,7 +54,6 @@ require (
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
|
@ -27,8 +27,6 @@ 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=
|
||||
@ -184,8 +182,8 @@ golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -1,48 +0,0 @@
|
||||
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.
|
@ -1,20 +0,0 @@
|
||||
|
||||
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
|
143
v3/internal/w32/clipboard.go
Normal file
143
v3/internal/w32/clipboard.go
Normal file
@ -0,0 +1,143 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Based on code originally from https://github.com/atotto/clipboard. Copyright (c) 2013 Ato Araki. All rights reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
cfUnicodetext = 13
|
||||
gmemMoveable = 0x0002
|
||||
)
|
||||
|
||||
// waitOpenClipboard opens the clipboard, waiting for up to a second to do so.
|
||||
func waitOpenClipboard() error {
|
||||
started := time.Now()
|
||||
limit := started.Add(time.Second)
|
||||
var r uintptr
|
||||
var err error
|
||||
for time.Now().Before(limit) {
|
||||
r, _, err = procOpenClipboard.Call(0)
|
||||
if r != 0 {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func GetClipboardText() (string, error) {
|
||||
// LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution).
|
||||
// Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock.
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
if formatAvailable, _, err := procIsClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 {
|
||||
return "", err
|
||||
}
|
||||
err := waitOpenClipboard()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
h, _, err := procGetClipboardData.Call(cfUnicodetext)
|
||||
if h == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return "", err
|
||||
}
|
||||
|
||||
l, _, err := kernelGlobalLock.Call(h)
|
||||
if l == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return "", err
|
||||
}
|
||||
|
||||
text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:])
|
||||
|
||||
r, _, err := kernelGlobalUnlock.Call(h)
|
||||
if r == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return "", err
|
||||
}
|
||||
|
||||
closed, _, err := procCloseClipboard.Call()
|
||||
if closed == 0 {
|
||||
return "", err
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
|
||||
func SetClipboardText(text string) error {
|
||||
// LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution).
|
||||
// Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock.
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
err := waitOpenClipboard()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err := procEmptyClipboard.Call(0)
|
||||
if r == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := syscall.UTF16FromString(text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// "If the hMem parameter identifies a memory object, the object must have
|
||||
// been allocated using the function with the GMEM_MOVEABLE flag."
|
||||
h, _, err := kernelGlobalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0]))))
|
||||
if h == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if h != 0 {
|
||||
kernelGlobalFree.Call(h)
|
||||
}
|
||||
}()
|
||||
|
||||
l, _, err := kernelGlobalLock.Call(h)
|
||||
if l == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err = kernelLstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0])))
|
||||
if r == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err = kernelGlobalUnlock.Call(h)
|
||||
if r == 0 {
|
||||
if err.(syscall.Errno) != 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
r, _, err = procSetClipboardData.Call(cfUnicodetext, h)
|
||||
if r == 0 {
|
||||
_, _, _ = procCloseClipboard.Call()
|
||||
return err
|
||||
}
|
||||
h = 0 // suppress deferred cleanup
|
||||
closed, _, err := procCloseClipboard.Call()
|
||||
if closed == 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
112
v3/internal/w32/comctl32.go
Normal file
112
v3/internal/w32/comctl32.go
Normal file
@ -0,0 +1,112 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modcomctl32 = syscall.NewLazyDLL("comctl32.dll")
|
||||
|
||||
procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx")
|
||||
procImageList_Create = modcomctl32.NewProc("ImageList_Create")
|
||||
procImageList_Destroy = modcomctl32.NewProc("ImageList_Destroy")
|
||||
procImageList_GetImageCount = modcomctl32.NewProc("ImageList_GetImageCount")
|
||||
procImageList_SetImageCount = modcomctl32.NewProc("ImageList_SetImageCount")
|
||||
procImageList_Add = modcomctl32.NewProc("ImageList_Add")
|
||||
procImageList_ReplaceIcon = modcomctl32.NewProc("ImageList_ReplaceIcon")
|
||||
procImageList_Remove = modcomctl32.NewProc("ImageList_Remove")
|
||||
procTrackMouseEvent = modcomctl32.NewProc("_TrackMouseEvent")
|
||||
)
|
||||
|
||||
func InitCommonControlsEx(lpInitCtrls *INITCOMMONCONTROLSEX) bool {
|
||||
ret, _, _ := procInitCommonControlsEx.Call(
|
||||
uintptr(unsafe.Pointer(lpInitCtrls)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func ImageList_Create(cx, cy int, flags uint, cInitial, cGrow int) HIMAGELIST {
|
||||
ret, _, _ := procImageList_Create.Call(
|
||||
uintptr(cx),
|
||||
uintptr(cy),
|
||||
uintptr(flags),
|
||||
uintptr(cInitial),
|
||||
uintptr(cGrow))
|
||||
|
||||
if ret == 0 {
|
||||
panic("Create image list failed")
|
||||
}
|
||||
|
||||
return HIMAGELIST(ret)
|
||||
}
|
||||
|
||||
func ImageList_Destroy(himl HIMAGELIST) bool {
|
||||
ret, _, _ := procImageList_Destroy.Call(
|
||||
uintptr(himl))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func ImageList_GetImageCount(himl HIMAGELIST) int {
|
||||
ret, _, _ := procImageList_GetImageCount.Call(
|
||||
uintptr(himl))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func ImageList_SetImageCount(himl HIMAGELIST, uNewCount uint) bool {
|
||||
ret, _, _ := procImageList_SetImageCount.Call(
|
||||
uintptr(himl),
|
||||
uintptr(uNewCount))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func ImageList_Add(himl HIMAGELIST, hbmImage, hbmMask HBITMAP) int {
|
||||
ret, _, _ := procImageList_Add.Call(
|
||||
uintptr(himl),
|
||||
uintptr(hbmImage),
|
||||
uintptr(hbmMask))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func ImageList_ReplaceIcon(himl HIMAGELIST, i int, hicon HICON) int {
|
||||
ret, _, _ := procImageList_ReplaceIcon.Call(
|
||||
uintptr(himl),
|
||||
uintptr(i),
|
||||
uintptr(hicon))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func ImageList_AddIcon(himl HIMAGELIST, hicon HICON) int {
|
||||
return ImageList_ReplaceIcon(himl, -1, hicon)
|
||||
}
|
||||
|
||||
func ImageList_Remove(himl HIMAGELIST, i int) bool {
|
||||
ret, _, _ := procImageList_Remove.Call(
|
||||
uintptr(himl),
|
||||
uintptr(i))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func ImageList_RemoveAll(himl HIMAGELIST) bool {
|
||||
return ImageList_Remove(himl, -1)
|
||||
}
|
||||
|
||||
func TrackMouseEvent(tme *TRACKMOUSEEVENT) bool {
|
||||
ret, _, _ := procTrackMouseEvent.Call(
|
||||
uintptr(unsafe.Pointer(tme)))
|
||||
|
||||
return ret != 0
|
||||
}
|
40
v3/internal/w32/comdlg32.go
Normal file
40
v3/internal/w32/comdlg32.go
Normal file
@ -0,0 +1,40 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modcomdlg32 = syscall.NewLazyDLL("comdlg32.dll")
|
||||
|
||||
procGetSaveFileName = modcomdlg32.NewProc("GetSaveFileNameW")
|
||||
procGetOpenFileName = modcomdlg32.NewProc("GetOpenFileNameW")
|
||||
procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError")
|
||||
)
|
||||
|
||||
func GetOpenFileName(ofn *OPENFILENAME) bool {
|
||||
ret, _, _ := procGetOpenFileName.Call(
|
||||
uintptr(unsafe.Pointer(ofn)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetSaveFileName(ofn *OPENFILENAME) bool {
|
||||
ret, _, _ := procGetSaveFileName.Call(
|
||||
uintptr(unsafe.Pointer(ofn)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func CommDlgExtendedError() uint {
|
||||
ret, _, _ := procCommDlgExtendedError.Call()
|
||||
|
||||
return uint(ret)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
83
v3/internal/w32/consts.go
Normal file
83
v3/internal/w32/consts.go
Normal file
@ -0,0 +1,83 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows/registry"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
modwingdi = syscall.NewLazyDLL("gdi32.dll")
|
||||
procCreateSolidBrush = modwingdi.NewProc("CreateSolidBrush")
|
||||
)
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
||||
kernelGlobalAlloc = kernel32.NewProc("GlobalAlloc")
|
||||
kernelGlobalFree = kernel32.NewProc("GlobalFree")
|
||||
kernelGlobalLock = kernel32.NewProc("GlobalLock")
|
||||
kernelGlobalUnlock = kernel32.NewProc("GlobalUnlock")
|
||||
kernelLstrcpy = kernel32.NewProc("lstrcpyW")
|
||||
)
|
||||
|
||||
var windowsVersion, _ = getWindowsVersionInfo()
|
||||
|
||||
func IsWindowsVersionAtLeast(major, minor, buildNumber int) bool {
|
||||
return windowsVersion.Major >= major &&
|
||||
windowsVersion.Minor >= minor &&
|
||||
windowsVersion.Build >= buildNumber
|
||||
}
|
||||
|
||||
type WindowsVersionInfo struct {
|
||||
Major int
|
||||
Minor int
|
||||
Build int
|
||||
DisplayVersion string
|
||||
}
|
||||
|
||||
func (w *WindowsVersionInfo) IsWindowsVersionAtLeast(major, minor, buildNumber int) bool {
|
||||
return w.Major >= major && w.Minor >= minor && w.Build >= buildNumber
|
||||
}
|
||||
|
||||
func getWindowsVersionInfo() (*WindowsVersionInfo, error) {
|
||||
key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WindowsVersionInfo{
|
||||
Major: regDWORDKeyAsInt(key, "CurrentMajorVersionNumber"),
|
||||
Minor: regDWORDKeyAsInt(key, "CurrentMinorVersionNumber"),
|
||||
Build: regStringKeyAsInt(key, "CurrentBuildNumber"),
|
||||
DisplayVersion: regKeyAsString(key, "DisplayVersion"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func regDWORDKeyAsInt(key registry.Key, name string) int {
|
||||
result, _, err := key.GetIntegerValue(name)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return int(result)
|
||||
}
|
||||
|
||||
func regStringKeyAsInt(key registry.Key, name string) int {
|
||||
resultStr, _, err := key.GetStringValue(name)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
result, err := strconv.Atoi(resultStr)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func regKeyAsString(key registry.Key, name string) string {
|
||||
resultStr, _, err := key.GetStringValue(name)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return resultStr
|
||||
}
|
36
v3/internal/w32/dwmapi.go
Normal file
36
v3/internal/w32/dwmapi.go
Normal file
@ -0,0 +1,36 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
moddwmapi = syscall.NewLazyDLL("dwmapi.dll")
|
||||
|
||||
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
|
||||
procDwmExtendFrameIntoClientArea = moddwmapi.NewProc("DwmExtendFrameIntoClientArea")
|
||||
)
|
||||
|
||||
func DwmSetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute LPCVOID, cbAttribute uint32) HRESULT {
|
||||
ret, _, _ := procDwmSetWindowAttribute.Call(
|
||||
hwnd,
|
||||
uintptr(dwAttribute),
|
||||
uintptr(pvAttribute),
|
||||
uintptr(cbAttribute))
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error {
|
||||
ret, _, _ := procDwmExtendFrameIntoClientArea.Call(
|
||||
hwnd,
|
||||
uintptr(unsafe.Pointer(margins)))
|
||||
|
||||
if ret != 0 {
|
||||
return syscall.GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +0,0 @@
|
||||
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)))
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
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
|
||||
}
|
526
v3/internal/w32/gdi32.go
Normal file
526
v3/internal/w32/gdi32.go
Normal file
@ -0,0 +1,526 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modgdi32 = syscall.NewLazyDLL("gdi32.dll")
|
||||
|
||||
procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps")
|
||||
procDeleteObject = modgdi32.NewProc("DeleteObject")
|
||||
procCreateFontIndirect = modgdi32.NewProc("CreateFontIndirectW")
|
||||
procAbortDoc = modgdi32.NewProc("AbortDoc")
|
||||
procBitBlt = modgdi32.NewProc("BitBlt")
|
||||
procPatBlt = modgdi32.NewProc("PatBlt")
|
||||
procCloseEnhMetaFile = modgdi32.NewProc("CloseEnhMetaFile")
|
||||
procCopyEnhMetaFile = modgdi32.NewProc("CopyEnhMetaFileW")
|
||||
procCreateBrushIndirect = modgdi32.NewProc("CreateBrushIndirect")
|
||||
procCreateCompatibleDC = modgdi32.NewProc("CreateCompatibleDC")
|
||||
procCreateDC = modgdi32.NewProc("CreateDCW")
|
||||
procCreateDIBSection = modgdi32.NewProc("CreateDIBSection")
|
||||
procCreateEnhMetaFile = modgdi32.NewProc("CreateEnhMetaFileW")
|
||||
procCreateIC = modgdi32.NewProc("CreateICW")
|
||||
procDeleteDC = modgdi32.NewProc("DeleteDC")
|
||||
procDeleteEnhMetaFile = modgdi32.NewProc("DeleteEnhMetaFile")
|
||||
procEllipse = modgdi32.NewProc("Ellipse")
|
||||
procEndDoc = modgdi32.NewProc("EndDoc")
|
||||
procEndPage = modgdi32.NewProc("EndPage")
|
||||
procExtCreatePen = modgdi32.NewProc("ExtCreatePen")
|
||||
procGetEnhMetaFile = modgdi32.NewProc("GetEnhMetaFileW")
|
||||
procGetEnhMetaFileHeader = modgdi32.NewProc("GetEnhMetaFileHeader")
|
||||
procGetObject = modgdi32.NewProc("GetObjectW")
|
||||
procGetStockObject = modgdi32.NewProc("GetStockObject")
|
||||
procGetTextExtentExPoint = modgdi32.NewProc("GetTextExtentExPointW")
|
||||
procGetTextExtentPoint32 = modgdi32.NewProc("GetTextExtentPoint32W")
|
||||
procGetTextMetrics = modgdi32.NewProc("GetTextMetricsW")
|
||||
procLineTo = modgdi32.NewProc("LineTo")
|
||||
procMoveToEx = modgdi32.NewProc("MoveToEx")
|
||||
procPlayEnhMetaFile = modgdi32.NewProc("PlayEnhMetaFile")
|
||||
procRectangle = modgdi32.NewProc("Rectangle")
|
||||
procResetDC = modgdi32.NewProc("ResetDCW")
|
||||
procSelectObject = modgdi32.NewProc("SelectObject")
|
||||
procSetBkMode = modgdi32.NewProc("SetBkMode")
|
||||
procSetBrushOrgEx = modgdi32.NewProc("SetBrushOrgEx")
|
||||
procSetStretchBltMode = modgdi32.NewProc("SetStretchBltMode")
|
||||
procSetTextColor = modgdi32.NewProc("SetTextColor")
|
||||
procSetBkColor = modgdi32.NewProc("SetBkColor")
|
||||
procStartDoc = modgdi32.NewProc("StartDocW")
|
||||
procStartPage = modgdi32.NewProc("StartPage")
|
||||
procStretchBlt = modgdi32.NewProc("StretchBlt")
|
||||
procSetDIBitsToDevice = modgdi32.NewProc("SetDIBitsToDevice")
|
||||
procChoosePixelFormat = modgdi32.NewProc("ChoosePixelFormat")
|
||||
procDescribePixelFormat = modgdi32.NewProc("DescribePixelFormat")
|
||||
procGetEnhMetaFilePixelFormat = modgdi32.NewProc("GetEnhMetaFilePixelFormat")
|
||||
procGetPixelFormat = modgdi32.NewProc("GetPixelFormat")
|
||||
procSetPixelFormat = modgdi32.NewProc("SetPixelFormat")
|
||||
procSwapBuffers = modgdi32.NewProc("SwapBuffers")
|
||||
)
|
||||
|
||||
func GetDeviceCaps(hdc HDC, index int) int {
|
||||
ret, _, _ := procGetDeviceCaps.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(index))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func DeleteObject(hObject HGDIOBJ) bool {
|
||||
ret, _, _ := procDeleteObject.Call(
|
||||
uintptr(hObject))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func CreateFontIndirect(logFont *LOGFONT) HFONT {
|
||||
ret, _, _ := procCreateFontIndirect.Call(
|
||||
uintptr(unsafe.Pointer(logFont)))
|
||||
|
||||
return HFONT(ret)
|
||||
}
|
||||
|
||||
func AbortDoc(hdc HDC) int {
|
||||
ret, _, _ := procAbortDoc.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func BitBlt(hdcDest HDC, nXDest, nYDest, nWidth, nHeight int, hdcSrc HDC, nXSrc, nYSrc int, dwRop uint) {
|
||||
ret, _, _ := procBitBlt.Call(
|
||||
uintptr(hdcDest),
|
||||
uintptr(nXDest),
|
||||
uintptr(nYDest),
|
||||
uintptr(nWidth),
|
||||
uintptr(nHeight),
|
||||
uintptr(hdcSrc),
|
||||
uintptr(nXSrc),
|
||||
uintptr(nYSrc),
|
||||
uintptr(dwRop))
|
||||
|
||||
if ret == 0 {
|
||||
panic("BitBlt failed")
|
||||
}
|
||||
}
|
||||
|
||||
func PatBlt(hdc HDC, nXLeft, nYLeft, nWidth, nHeight int, dwRop uint) {
|
||||
ret, _, _ := procPatBlt.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(nXLeft),
|
||||
uintptr(nYLeft),
|
||||
uintptr(nWidth),
|
||||
uintptr(nHeight),
|
||||
uintptr(dwRop))
|
||||
|
||||
if ret == 0 {
|
||||
panic("PatBlt failed")
|
||||
}
|
||||
}
|
||||
|
||||
func CloseEnhMetaFile(hdc HDC) HENHMETAFILE {
|
||||
ret, _, _ := procCloseEnhMetaFile.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return HENHMETAFILE(ret)
|
||||
}
|
||||
|
||||
func CopyEnhMetaFile(hemfSrc HENHMETAFILE, lpszFile *uint16) HENHMETAFILE {
|
||||
ret, _, _ := procCopyEnhMetaFile.Call(
|
||||
uintptr(hemfSrc),
|
||||
uintptr(unsafe.Pointer(lpszFile)))
|
||||
|
||||
return HENHMETAFILE(ret)
|
||||
}
|
||||
|
||||
func CreateBrushIndirect(lplb *LOGBRUSH) HBRUSH {
|
||||
ret, _, _ := procCreateBrushIndirect.Call(
|
||||
uintptr(unsafe.Pointer(lplb)))
|
||||
|
||||
return HBRUSH(ret)
|
||||
}
|
||||
|
||||
func CreateCompatibleDC(hdc HDC) HDC {
|
||||
ret, _, _ := procCreateCompatibleDC.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
if ret == 0 {
|
||||
panic("Create compatible DC failed")
|
||||
}
|
||||
|
||||
return HDC(ret)
|
||||
}
|
||||
|
||||
func CreateDC(lpszDriver, lpszDevice, lpszOutput *uint16, lpInitData *DEVMODE) HDC {
|
||||
ret, _, _ := procCreateDC.Call(
|
||||
uintptr(unsafe.Pointer(lpszDriver)),
|
||||
uintptr(unsafe.Pointer(lpszDevice)),
|
||||
uintptr(unsafe.Pointer(lpszOutput)),
|
||||
uintptr(unsafe.Pointer(lpInitData)))
|
||||
|
||||
return HDC(ret)
|
||||
}
|
||||
|
||||
func CreateDIBSection(hdc HDC, pbmi *BITMAPINFO, iUsage uint, ppvBits *unsafe.Pointer, hSection HANDLE, dwOffset uint) HBITMAP {
|
||||
ret, _, _ := procCreateDIBSection.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(pbmi)),
|
||||
uintptr(iUsage),
|
||||
uintptr(unsafe.Pointer(ppvBits)),
|
||||
uintptr(hSection),
|
||||
uintptr(dwOffset))
|
||||
|
||||
return HBITMAP(ret)
|
||||
}
|
||||
|
||||
func CreateEnhMetaFile(hdcRef HDC, lpFilename *uint16, lpRect *RECT, lpDescription *uint16) HDC {
|
||||
ret, _, _ := procCreateEnhMetaFile.Call(
|
||||
uintptr(hdcRef),
|
||||
uintptr(unsafe.Pointer(lpFilename)),
|
||||
uintptr(unsafe.Pointer(lpRect)),
|
||||
uintptr(unsafe.Pointer(lpDescription)))
|
||||
|
||||
return HDC(ret)
|
||||
}
|
||||
|
||||
func CreateIC(lpszDriver, lpszDevice, lpszOutput *uint16, lpdvmInit *DEVMODE) HDC {
|
||||
ret, _, _ := procCreateIC.Call(
|
||||
uintptr(unsafe.Pointer(lpszDriver)),
|
||||
uintptr(unsafe.Pointer(lpszDevice)),
|
||||
uintptr(unsafe.Pointer(lpszOutput)),
|
||||
uintptr(unsafe.Pointer(lpdvmInit)))
|
||||
|
||||
return HDC(ret)
|
||||
}
|
||||
|
||||
func DeleteDC(hdc HDC) bool {
|
||||
ret, _, _ := procDeleteDC.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func DeleteEnhMetaFile(hemf HENHMETAFILE) bool {
|
||||
ret, _, _ := procDeleteEnhMetaFile.Call(
|
||||
uintptr(hemf))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func Ellipse(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int32) bool {
|
||||
ret, _, _ := procEllipse.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(nLeftRect),
|
||||
uintptr(nTopRect),
|
||||
uintptr(nRightRect),
|
||||
uintptr(nBottomRect))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func EndDoc(hdc HDC) int {
|
||||
ret, _, _ := procEndDoc.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func EndPage(hdc HDC) int {
|
||||
ret, _, _ := procEndPage.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func ExtCreatePen(dwPenStyle, dwWidth uint, lplb *LOGBRUSH, dwStyleCount uint, lpStyle *uint) HPEN {
|
||||
ret, _, _ := procExtCreatePen.Call(
|
||||
uintptr(dwPenStyle),
|
||||
uintptr(dwWidth),
|
||||
uintptr(unsafe.Pointer(lplb)),
|
||||
uintptr(dwStyleCount),
|
||||
uintptr(unsafe.Pointer(lpStyle)))
|
||||
|
||||
return HPEN(ret)
|
||||
}
|
||||
|
||||
func GetEnhMetaFile(lpszMetaFile *uint16) HENHMETAFILE {
|
||||
ret, _, _ := procGetEnhMetaFile.Call(
|
||||
uintptr(unsafe.Pointer(lpszMetaFile)))
|
||||
|
||||
return HENHMETAFILE(ret)
|
||||
}
|
||||
|
||||
func GetEnhMetaFileHeader(hemf HENHMETAFILE, cbBuffer uint, lpemh *ENHMETAHEADER) uint {
|
||||
ret, _, _ := procGetEnhMetaFileHeader.Call(
|
||||
uintptr(hemf),
|
||||
uintptr(cbBuffer),
|
||||
uintptr(unsafe.Pointer(lpemh)))
|
||||
|
||||
return uint(ret)
|
||||
}
|
||||
|
||||
func GetObject(hgdiobj HGDIOBJ, cbBuffer uintptr, lpvObject unsafe.Pointer) int {
|
||||
ret, _, _ := procGetObject.Call(
|
||||
uintptr(hgdiobj),
|
||||
uintptr(cbBuffer),
|
||||
uintptr(lpvObject))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func GetStockObject(fnObject int) HGDIOBJ {
|
||||
ret, _, _ := procGetDeviceCaps.Call(
|
||||
uintptr(fnObject))
|
||||
|
||||
return HGDIOBJ(ret)
|
||||
}
|
||||
|
||||
func GetTextExtentExPoint(hdc HDC, lpszStr *uint16, cchString, nMaxExtent int, lpnFit, alpDx *int, lpSize *SIZE) bool {
|
||||
ret, _, _ := procGetTextExtentExPoint.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(lpszStr)),
|
||||
uintptr(cchString),
|
||||
uintptr(nMaxExtent),
|
||||
uintptr(unsafe.Pointer(lpnFit)),
|
||||
uintptr(unsafe.Pointer(alpDx)),
|
||||
uintptr(unsafe.Pointer(lpSize)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetTextExtentPoint32(hdc HDC, lpString *uint16, c int, lpSize *SIZE) bool {
|
||||
ret, _, _ := procGetTextExtentPoint32.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(lpString)),
|
||||
uintptr(c),
|
||||
uintptr(unsafe.Pointer(lpSize)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetTextMetrics(hdc HDC, lptm *TEXTMETRIC) bool {
|
||||
ret, _, _ := procGetTextMetrics.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(lptm)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func LineTo(hdc HDC, nXEnd, nYEnd int32) bool {
|
||||
ret, _, _ := procLineTo.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(nXEnd),
|
||||
uintptr(nYEnd))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func MoveToEx(hdc HDC, x, y int, lpPoint *POINT) bool {
|
||||
ret, _, _ := procMoveToEx.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(x),
|
||||
uintptr(y),
|
||||
uintptr(unsafe.Pointer(lpPoint)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func PlayEnhMetaFile(hdc HDC, hemf HENHMETAFILE, lpRect *RECT) bool {
|
||||
ret, _, _ := procPlayEnhMetaFile.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(hemf),
|
||||
uintptr(unsafe.Pointer(lpRect)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func Rectangle(hdc HDC, nLeftRect, nTopRect, nRightRect, nBottomRect int32) bool {
|
||||
ret, _, _ := procRectangle.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(nLeftRect),
|
||||
uintptr(nTopRect),
|
||||
uintptr(nRightRect),
|
||||
uintptr(nBottomRect))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func ResetDC(hdc HDC, lpInitData *DEVMODE) HDC {
|
||||
ret, _, _ := procResetDC.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(lpInitData)))
|
||||
|
||||
return HDC(ret)
|
||||
}
|
||||
|
||||
func SelectObject(hdc HDC, hgdiobj HGDIOBJ) HGDIOBJ {
|
||||
ret, _, _ := procSelectObject.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(hgdiobj))
|
||||
|
||||
if ret == 0 {
|
||||
panic("SelectObject failed")
|
||||
}
|
||||
|
||||
return HGDIOBJ(ret)
|
||||
}
|
||||
|
||||
func SetBkMode(hdc HDC, iBkMode int) int {
|
||||
ret, _, _ := procSetBkMode.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(iBkMode))
|
||||
|
||||
if ret == 0 {
|
||||
panic("SetBkMode failed")
|
||||
}
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func SetBrushOrgEx(hdc HDC, nXOrg, nYOrg int, lppt *POINT) bool {
|
||||
ret, _, _ := procSetBrushOrgEx.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(nXOrg),
|
||||
uintptr(nYOrg),
|
||||
uintptr(unsafe.Pointer(lppt)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func SetStretchBltMode(hdc HDC, iStretchMode int) int {
|
||||
ret, _, _ := procSetStretchBltMode.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(iStretchMode))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func SetTextColor(hdc HDC, crColor COLORREF) COLORREF {
|
||||
ret, _, _ := procSetTextColor.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(crColor))
|
||||
|
||||
if ret == CLR_INVALID {
|
||||
panic("SetTextColor failed")
|
||||
}
|
||||
|
||||
return COLORREF(ret)
|
||||
}
|
||||
|
||||
func SetBkColor(hdc HDC, crColor COLORREF) COLORREF {
|
||||
ret, _, _ := procSetBkColor.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(crColor))
|
||||
|
||||
if ret == CLR_INVALID {
|
||||
panic("SetBkColor failed")
|
||||
}
|
||||
|
||||
return COLORREF(ret)
|
||||
}
|
||||
|
||||
func StartDoc(hdc HDC, lpdi *DOCINFO) int {
|
||||
ret, _, _ := procStartDoc.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(lpdi)))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func StartPage(hdc HDC) int {
|
||||
ret, _, _ := procStartPage.Call(
|
||||
uintptr(hdc))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func StretchBlt(hdcDest HDC, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest int, hdcSrc HDC, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc int, dwRop uint) {
|
||||
ret, _, _ := procStretchBlt.Call(
|
||||
uintptr(hdcDest),
|
||||
uintptr(nXOriginDest),
|
||||
uintptr(nYOriginDest),
|
||||
uintptr(nWidthDest),
|
||||
uintptr(nHeightDest),
|
||||
uintptr(hdcSrc),
|
||||
uintptr(nXOriginSrc),
|
||||
uintptr(nYOriginSrc),
|
||||
uintptr(nWidthSrc),
|
||||
uintptr(nHeightSrc),
|
||||
uintptr(dwRop))
|
||||
|
||||
if ret == 0 {
|
||||
panic("StretchBlt failed")
|
||||
}
|
||||
}
|
||||
|
||||
func SetDIBitsToDevice(hdc HDC, xDest, yDest, dwWidth, dwHeight, xSrc, ySrc int, uStartScan, cScanLines uint, lpvBits []byte, lpbmi *BITMAPINFO, fuColorUse uint) int {
|
||||
ret, _, _ := procSetDIBitsToDevice.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(xDest),
|
||||
uintptr(yDest),
|
||||
uintptr(dwWidth),
|
||||
uintptr(dwHeight),
|
||||
uintptr(xSrc),
|
||||
uintptr(ySrc),
|
||||
uintptr(uStartScan),
|
||||
uintptr(cScanLines),
|
||||
uintptr(unsafe.Pointer(&lpvBits[0])),
|
||||
uintptr(unsafe.Pointer(lpbmi)),
|
||||
uintptr(fuColorUse))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func ChoosePixelFormat(hdc HDC, pfd *PIXELFORMATDESCRIPTOR) int {
|
||||
ret, _, _ := procChoosePixelFormat.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(unsafe.Pointer(pfd)),
|
||||
)
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func DescribePixelFormat(hdc HDC, iPixelFormat int, nBytes uint, pfd *PIXELFORMATDESCRIPTOR) int {
|
||||
ret, _, _ := procDescribePixelFormat.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(iPixelFormat),
|
||||
uintptr(nBytes),
|
||||
uintptr(unsafe.Pointer(pfd)),
|
||||
)
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func GetEnhMetaFilePixelFormat(hemf HENHMETAFILE, cbBuffer uint32, pfd *PIXELFORMATDESCRIPTOR) uint {
|
||||
ret, _, _ := procGetEnhMetaFilePixelFormat.Call(
|
||||
uintptr(hemf),
|
||||
uintptr(cbBuffer),
|
||||
uintptr(unsafe.Pointer(pfd)),
|
||||
)
|
||||
return uint(ret)
|
||||
}
|
||||
|
||||
func GetPixelFormat(hdc HDC) int {
|
||||
ret, _, _ := procGetPixelFormat.Call(
|
||||
uintptr(hdc),
|
||||
)
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func SetPixelFormat(hdc HDC, iPixelFormat int, pfd *PIXELFORMATDESCRIPTOR) bool {
|
||||
ret, _, _ := procSetPixelFormat.Call(
|
||||
uintptr(hdc),
|
||||
uintptr(iPixelFormat),
|
||||
uintptr(unsafe.Pointer(pfd)),
|
||||
)
|
||||
return ret == TRUE
|
||||
}
|
||||
|
||||
func SwapBuffers(hdc HDC) bool {
|
||||
ret, _, _ := procSwapBuffers.Call(uintptr(hdc))
|
||||
return ret == TRUE
|
||||
}
|
177
v3/internal/w32/gdiplus.go
Normal file
177
v3/internal/w32/gdiplus.go
Normal file
@ -0,0 +1,177 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
Ok = 0
|
||||
GenericError = 1
|
||||
InvalidParameter = 2
|
||||
OutOfMemory = 3
|
||||
ObjectBusy = 4
|
||||
InsufficientBuffer = 5
|
||||
NotImplemented = 6
|
||||
Win32Error = 7
|
||||
WrongState = 8
|
||||
Aborted = 9
|
||||
FileNotFound = 10
|
||||
ValueOverflow = 11
|
||||
AccessDenied = 12
|
||||
UnknownImageFormat = 13
|
||||
FontFamilyNotFound = 14
|
||||
FontStyleNotFound = 15
|
||||
NotTrueTypeFont = 16
|
||||
UnsupportedGdiplusVersion = 17
|
||||
GdiplusNotInitialized = 18
|
||||
PropertyNotFound = 19
|
||||
PropertyNotSupported = 20
|
||||
ProfileNotFound = 21
|
||||
)
|
||||
|
||||
func GetGpStatus(s int32) string {
|
||||
switch s {
|
||||
case Ok:
|
||||
return "Ok"
|
||||
case GenericError:
|
||||
return "GenericError"
|
||||
case InvalidParameter:
|
||||
return "InvalidParameter"
|
||||
case OutOfMemory:
|
||||
return "OutOfMemory"
|
||||
case ObjectBusy:
|
||||
return "ObjectBusy"
|
||||
case InsufficientBuffer:
|
||||
return "InsufficientBuffer"
|
||||
case NotImplemented:
|
||||
return "NotImplemented"
|
||||
case Win32Error:
|
||||
return "Win32Error"
|
||||
case WrongState:
|
||||
return "WrongState"
|
||||
case Aborted:
|
||||
return "Aborted"
|
||||
case FileNotFound:
|
||||
return "FileNotFound"
|
||||
case ValueOverflow:
|
||||
return "ValueOverflow"
|
||||
case AccessDenied:
|
||||
return "AccessDenied"
|
||||
case UnknownImageFormat:
|
||||
return "UnknownImageFormat"
|
||||
case FontFamilyNotFound:
|
||||
return "FontFamilyNotFound"
|
||||
case FontStyleNotFound:
|
||||
return "FontStyleNotFound"
|
||||
case NotTrueTypeFont:
|
||||
return "NotTrueTypeFont"
|
||||
case UnsupportedGdiplusVersion:
|
||||
return "UnsupportedGdiplusVersion"
|
||||
case GdiplusNotInitialized:
|
||||
return "GdiplusNotInitialized"
|
||||
case PropertyNotFound:
|
||||
return "PropertyNotFound"
|
||||
case PropertyNotSupported:
|
||||
return "PropertyNotSupported"
|
||||
case ProfileNotFound:
|
||||
return "ProfileNotFound"
|
||||
}
|
||||
return "Unknown Status Value"
|
||||
}
|
||||
|
||||
var (
|
||||
token uintptr
|
||||
|
||||
modgdiplus = syscall.NewLazyDLL("gdiplus.dll")
|
||||
|
||||
procGdipCreateBitmapFromFile = modgdiplus.NewProc("GdipCreateBitmapFromFile")
|
||||
procGdipCreateBitmapFromHBITMAP = modgdiplus.NewProc("GdipCreateBitmapFromHBITMAP")
|
||||
procGdipCreateHBITMAPFromBitmap = modgdiplus.NewProc("GdipCreateHBITMAPFromBitmap")
|
||||
procGdipCreateBitmapFromResource = modgdiplus.NewProc("GdipCreateBitmapFromResource")
|
||||
procGdipCreateBitmapFromStream = modgdiplus.NewProc("GdipCreateBitmapFromStream")
|
||||
procGdipDisposeImage = modgdiplus.NewProc("GdipDisposeImage")
|
||||
procGdiplusShutdown = modgdiplus.NewProc("GdiplusShutdown")
|
||||
procGdiplusStartup = modgdiplus.NewProc("GdiplusStartup")
|
||||
)
|
||||
|
||||
func GdipCreateBitmapFromFile(filename string) (*uintptr, error) {
|
||||
var bitmap *uintptr
|
||||
ret, _, _ := procGdipCreateBitmapFromFile.Call(
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
|
||||
uintptr(unsafe.Pointer(&bitmap)))
|
||||
|
||||
if ret != Ok {
|
||||
return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromFile failed with status '%s' for file '%s'", GetGpStatus(int32(ret)), filename))
|
||||
}
|
||||
|
||||
return bitmap, nil
|
||||
}
|
||||
|
||||
func GdipCreateBitmapFromResource(instance HINSTANCE, resId *uint16) (*uintptr, error) {
|
||||
var bitmap *uintptr
|
||||
ret, _, _ := procGdipCreateBitmapFromResource.Call(
|
||||
uintptr(instance),
|
||||
uintptr(unsafe.Pointer(resId)),
|
||||
uintptr(unsafe.Pointer(&bitmap)))
|
||||
|
||||
if ret != Ok {
|
||||
return nil, errors.New(fmt.Sprintf("GdiCreateBitmapFromResource failed with status '%s'", GetGpStatus(int32(ret))))
|
||||
}
|
||||
|
||||
return bitmap, nil
|
||||
}
|
||||
|
||||
func GdipCreateBitmapFromStream(stream *IStream) (*uintptr, error) {
|
||||
var bitmap *uintptr
|
||||
ret, _, _ := procGdipCreateBitmapFromStream.Call(
|
||||
uintptr(unsafe.Pointer(stream)),
|
||||
uintptr(unsafe.Pointer(&bitmap)))
|
||||
|
||||
if ret != Ok {
|
||||
return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromStream failed with status '%s'", GetGpStatus(int32(ret))))
|
||||
}
|
||||
|
||||
return bitmap, nil
|
||||
}
|
||||
|
||||
func GdipCreateHBITMAPFromBitmap(bitmap *uintptr, background uint32) (HBITMAP, error) {
|
||||
var hbitmap HBITMAP
|
||||
ret, _, _ := procGdipCreateHBITMAPFromBitmap.Call(
|
||||
uintptr(unsafe.Pointer(bitmap)),
|
||||
uintptr(unsafe.Pointer(&hbitmap)),
|
||||
uintptr(background))
|
||||
|
||||
if ret != Ok {
|
||||
return 0, errors.New(fmt.Sprintf("GdipCreateHBITMAPFromBitmap failed with status '%s'", GetGpStatus(int32(ret))))
|
||||
}
|
||||
|
||||
return hbitmap, nil
|
||||
}
|
||||
|
||||
func GdipDisposeImage(image *uintptr) {
|
||||
procGdipDisposeImage.Call(uintptr(unsafe.Pointer(image)))
|
||||
}
|
||||
|
||||
func GdiplusShutdown() {
|
||||
procGdiplusShutdown.Call(token)
|
||||
}
|
||||
|
||||
func GdiplusStartup(input *GdiplusStartupInput, output *GdiplusStartupOutput) {
|
||||
ret, _, _ := procGdiplusStartup.Call(
|
||||
uintptr(unsafe.Pointer(&token)),
|
||||
uintptr(unsafe.Pointer(input)),
|
||||
uintptr(unsafe.Pointer(output)))
|
||||
|
||||
if ret != Ok {
|
||||
panic("GdiplusStartup failed with status " + GetGpStatus(int32(ret)))
|
||||
}
|
||||
}
|
45
v3/internal/w32/idispatch.go
Normal file
45
v3/internal/w32/idispatch.go
Normal file
@ -0,0 +1,45 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type pIDispatchVtbl struct {
|
||||
pQueryInterface uintptr
|
||||
pAddRef uintptr
|
||||
pRelease uintptr
|
||||
pGetTypeInfoCount uintptr
|
||||
pGetTypeInfo uintptr
|
||||
pGetIDsOfNames uintptr
|
||||
pInvoke uintptr
|
||||
}
|
||||
|
||||
type IDispatch struct {
|
||||
lpVtbl *pIDispatchVtbl
|
||||
}
|
||||
|
||||
func (this *IDispatch) QueryInterface(id *GUID) *IDispatch {
|
||||
return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id)
|
||||
}
|
||||
|
||||
func (this *IDispatch) AddRef() int32 {
|
||||
return ComAddRef((*IUnknown)(unsafe.Pointer(this)))
|
||||
}
|
||||
|
||||
func (this *IDispatch) Release() int32 {
|
||||
return ComRelease((*IUnknown)(unsafe.Pointer(this)))
|
||||
}
|
||||
|
||||
func (this *IDispatch) GetIDsOfName(names []string) []int32 {
|
||||
return ComGetIDsOfName(this, names)
|
||||
}
|
||||
|
||||
func (this *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) *VARIANT {
|
||||
return ComInvoke(this, dispid, dispatch, params...)
|
||||
}
|
33
v3/internal/w32/istream.go
Normal file
33
v3/internal/w32/istream.go
Normal file
@ -0,0 +1,33 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type pIStreamVtbl struct {
|
||||
pQueryInterface uintptr
|
||||
pAddRef uintptr
|
||||
pRelease uintptr
|
||||
}
|
||||
|
||||
type IStream struct {
|
||||
lpVtbl *pIStreamVtbl
|
||||
}
|
||||
|
||||
func (this *IStream) QueryInterface(id *GUID) *IDispatch {
|
||||
return ComQueryInterface((*IUnknown)(unsafe.Pointer(this)), id)
|
||||
}
|
||||
|
||||
func (this *IStream) AddRef() int32 {
|
||||
return ComAddRef((*IUnknown)(unsafe.Pointer(this)))
|
||||
}
|
||||
|
||||
func (this *IStream) Release() int32 {
|
||||
return ComRelease((*IUnknown)(unsafe.Pointer(this)))
|
||||
}
|
29
v3/internal/w32/iunknown.go
Normal file
29
v3/internal/w32/iunknown.go
Normal file
@ -0,0 +1,29 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
type pIUnknownVtbl struct {
|
||||
pQueryInterface uintptr
|
||||
pAddRef uintptr
|
||||
pRelease uintptr
|
||||
}
|
||||
|
||||
type IUnknown struct {
|
||||
lpVtbl *pIUnknownVtbl
|
||||
}
|
||||
|
||||
func (this *IUnknown) QueryInterface(id *GUID) *IDispatch {
|
||||
return ComQueryInterface(this, id)
|
||||
}
|
||||
|
||||
func (this *IUnknown) AddRef() int32 {
|
||||
return ComAddRef(this)
|
||||
}
|
||||
|
||||
func (this *IUnknown) Release() int32 {
|
||||
return ComRelease(this)
|
||||
}
|
332
v3/internal/w32/kernel32.go
Normal file
332
v3/internal/w32/kernel32.go
Normal file
@ -0,0 +1,332 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
procGetModuleHandle = modkernel32.NewProc("GetModuleHandleW")
|
||||
procMulDiv = modkernel32.NewProc("MulDiv")
|
||||
procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId")
|
||||
procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives")
|
||||
procGetLogicalDriveStrings = modkernel32.NewProc("GetLogicalDriveStringsW")
|
||||
procGetUserDefaultLCID = modkernel32.NewProc("GetUserDefaultLCID")
|
||||
procLstrlen = modkernel32.NewProc("lstrlenW")
|
||||
procLstrcpy = modkernel32.NewProc("lstrcpyW")
|
||||
procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
|
||||
procGlobalFree = modkernel32.NewProc("GlobalFree")
|
||||
procGlobalLock = modkernel32.NewProc("GlobalLock")
|
||||
procGlobalUnlock = modkernel32.NewProc("GlobalUnlock")
|
||||
procMoveMemory = modkernel32.NewProc("RtlMoveMemory")
|
||||
procFindResource = modkernel32.NewProc("FindResourceW")
|
||||
procSizeofResource = modkernel32.NewProc("SizeofResource")
|
||||
procLockResource = modkernel32.NewProc("LockResource")
|
||||
procLoadResource = modkernel32.NewProc("LoadResource")
|
||||
procGetLastError = modkernel32.NewProc("GetLastError")
|
||||
procOpenProcess = modkernel32.NewProc("OpenProcess")
|
||||
procTerminateProcess = modkernel32.NewProc("TerminateProcess")
|
||||
procCloseHandle = modkernel32.NewProc("CloseHandle")
|
||||
procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
|
||||
procModule32First = modkernel32.NewProc("Module32FirstW")
|
||||
procModule32Next = modkernel32.NewProc("Module32NextW")
|
||||
procGetSystemTimes = modkernel32.NewProc("GetSystemTimes")
|
||||
procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
procSetConsoleTextAttribute = modkernel32.NewProc("SetConsoleTextAttribute")
|
||||
procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||
procGetProcessTimes = modkernel32.NewProc("GetProcessTimes")
|
||||
procSetSystemTime = modkernel32.NewProc("SetSystemTime")
|
||||
procGetSystemTime = modkernel32.NewProc("GetSystemTime")
|
||||
)
|
||||
|
||||
func GetModuleHandle(modulename string) HINSTANCE {
|
||||
var mn uintptr
|
||||
if modulename == "" {
|
||||
mn = 0
|
||||
} else {
|
||||
mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
|
||||
}
|
||||
ret, _, _ := procGetModuleHandle.Call(mn)
|
||||
return HINSTANCE(ret)
|
||||
}
|
||||
|
||||
func MulDiv(number, numerator, denominator int) int {
|
||||
ret, _, _ := procMulDiv.Call(
|
||||
uintptr(number),
|
||||
uintptr(numerator),
|
||||
uintptr(denominator))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func GetConsoleWindow() HWND {
|
||||
ret, _, _ := procGetConsoleWindow.Call()
|
||||
|
||||
return HWND(ret)
|
||||
}
|
||||
|
||||
func GetCurrentThread() HANDLE {
|
||||
ret, _, _ := procGetCurrentThread.Call()
|
||||
|
||||
return HANDLE(ret)
|
||||
}
|
||||
|
||||
func GetCurrentThreadId() HANDLE {
|
||||
ret, _, _ := procGetCurrentThreadId.Call()
|
||||
|
||||
return HANDLE(ret)
|
||||
}
|
||||
|
||||
func GetLogicalDrives() uint32 {
|
||||
ret, _, _ := procGetLogicalDrives.Call()
|
||||
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
func GetUserDefaultLCID() uint32 {
|
||||
ret, _, _ := procGetUserDefaultLCID.Call()
|
||||
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
func Lstrlen(lpString *uint16) int {
|
||||
ret, _, _ := procLstrlen.Call(uintptr(unsafe.Pointer(lpString)))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func Lstrcpy(buf []uint16, lpString *uint16) {
|
||||
procLstrcpy.Call(
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(lpString)))
|
||||
}
|
||||
|
||||
func GlobalAlloc(uFlags uint, dwBytes uint32) HGLOBAL {
|
||||
ret, _, _ := procGlobalAlloc.Call(
|
||||
uintptr(uFlags),
|
||||
uintptr(dwBytes))
|
||||
|
||||
if ret == 0 {
|
||||
panic("GlobalAlloc failed")
|
||||
}
|
||||
|
||||
return HGLOBAL(ret)
|
||||
}
|
||||
|
||||
func GlobalFree(hMem HGLOBAL) {
|
||||
ret, _, _ := procGlobalFree.Call(uintptr(hMem))
|
||||
|
||||
if ret != 0 {
|
||||
panic("GlobalFree failed")
|
||||
}
|
||||
}
|
||||
|
||||
func GlobalLock(hMem HGLOBAL) unsafe.Pointer {
|
||||
ret, _, _ := procGlobalLock.Call(uintptr(hMem))
|
||||
|
||||
if ret == 0 {
|
||||
panic("GlobalLock failed")
|
||||
}
|
||||
|
||||
return unsafe.Pointer(ret)
|
||||
}
|
||||
|
||||
func GlobalUnlock(hMem HGLOBAL) bool {
|
||||
ret, _, _ := procGlobalUnlock.Call(uintptr(hMem))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func MoveMemory(destination, source unsafe.Pointer, length uint32) {
|
||||
procMoveMemory.Call(
|
||||
uintptr(unsafe.Pointer(destination)),
|
||||
uintptr(source),
|
||||
uintptr(length))
|
||||
}
|
||||
|
||||
func FindResource(hModule HMODULE, lpName, lpType *uint16) (HRSRC, error) {
|
||||
ret, _, _ := procFindResource.Call(
|
||||
uintptr(hModule),
|
||||
uintptr(unsafe.Pointer(lpName)),
|
||||
uintptr(unsafe.Pointer(lpType)))
|
||||
|
||||
if ret == 0 {
|
||||
return 0, syscall.GetLastError()
|
||||
}
|
||||
|
||||
return HRSRC(ret), nil
|
||||
}
|
||||
|
||||
func SizeofResource(hModule HMODULE, hResInfo HRSRC) uint32 {
|
||||
ret, _, _ := procSizeofResource.Call(
|
||||
uintptr(hModule),
|
||||
uintptr(hResInfo))
|
||||
|
||||
if ret == 0 {
|
||||
panic("SizeofResource failed")
|
||||
}
|
||||
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
func LockResource(hResData HGLOBAL) unsafe.Pointer {
|
||||
ret, _, _ := procLockResource.Call(uintptr(hResData))
|
||||
|
||||
if ret == 0 {
|
||||
panic("LockResource failed")
|
||||
}
|
||||
|
||||
return unsafe.Pointer(ret)
|
||||
}
|
||||
|
||||
func LoadResource(hModule HMODULE, hResInfo HRSRC) HGLOBAL {
|
||||
ret, _, _ := procLoadResource.Call(
|
||||
uintptr(hModule),
|
||||
uintptr(hResInfo))
|
||||
|
||||
if ret == 0 {
|
||||
panic("LoadResource failed")
|
||||
}
|
||||
|
||||
return HGLOBAL(ret)
|
||||
}
|
||||
|
||||
func GetLastError() uint32 {
|
||||
ret, _, _ := procGetLastError.Call()
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) HANDLE {
|
||||
inherit := 0
|
||||
if inheritHandle {
|
||||
inherit = 1
|
||||
}
|
||||
|
||||
ret, _, _ := procOpenProcess.Call(
|
||||
uintptr(desiredAccess),
|
||||
uintptr(inherit),
|
||||
uintptr(processId))
|
||||
return HANDLE(ret)
|
||||
}
|
||||
|
||||
func TerminateProcess(hProcess HANDLE, uExitCode uint) bool {
|
||||
ret, _, _ := procTerminateProcess.Call(
|
||||
uintptr(hProcess),
|
||||
uintptr(uExitCode))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func CloseHandle(object HANDLE) bool {
|
||||
ret, _, _ := procCloseHandle.Call(
|
||||
uintptr(object))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func CreateToolhelp32Snapshot(flags, processId uint32) HANDLE {
|
||||
ret, _, _ := procCreateToolhelp32Snapshot.Call(
|
||||
uintptr(flags),
|
||||
uintptr(processId))
|
||||
|
||||
if ret <= 0 {
|
||||
return HANDLE(0)
|
||||
}
|
||||
|
||||
return HANDLE(ret)
|
||||
}
|
||||
|
||||
func Module32First(snapshot HANDLE, me *MODULEENTRY32) bool {
|
||||
ret, _, _ := procModule32First.Call(
|
||||
uintptr(snapshot),
|
||||
uintptr(unsafe.Pointer(me)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func Module32Next(snapshot HANDLE, me *MODULEENTRY32) bool {
|
||||
ret, _, _ := procModule32Next.Call(
|
||||
uintptr(snapshot),
|
||||
uintptr(unsafe.Pointer(me)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetSystemTimes(lpIdleTime, lpKernelTime, lpUserTime *FILETIME) bool {
|
||||
ret, _, _ := procGetSystemTimes.Call(
|
||||
uintptr(unsafe.Pointer(lpIdleTime)),
|
||||
uintptr(unsafe.Pointer(lpKernelTime)),
|
||||
uintptr(unsafe.Pointer(lpUserTime)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetProcessTimes(hProcess HANDLE, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime *FILETIME) bool {
|
||||
ret, _, _ := procGetProcessTimes.Call(
|
||||
uintptr(hProcess),
|
||||
uintptr(unsafe.Pointer(lpCreationTime)),
|
||||
uintptr(unsafe.Pointer(lpExitTime)),
|
||||
uintptr(unsafe.Pointer(lpKernelTime)),
|
||||
uintptr(unsafe.Pointer(lpUserTime)))
|
||||
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetConsoleScreenBufferInfo(hConsoleOutput HANDLE) *CONSOLE_SCREEN_BUFFER_INFO {
|
||||
var csbi CONSOLE_SCREEN_BUFFER_INFO
|
||||
ret, _, _ := procGetConsoleScreenBufferInfo.Call(
|
||||
uintptr(hConsoleOutput),
|
||||
uintptr(unsafe.Pointer(&csbi)))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
}
|
||||
return &csbi
|
||||
}
|
||||
|
||||
func SetConsoleTextAttribute(hConsoleOutput HANDLE, wAttributes uint16) bool {
|
||||
ret, _, _ := procSetConsoleTextAttribute.Call(
|
||||
uintptr(hConsoleOutput),
|
||||
uintptr(wAttributes))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetDiskFreeSpaceEx(dirName string) (r bool,
|
||||
freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64) {
|
||||
ret, _, _ := procGetDiskFreeSpaceEx.Call(
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(dirName))),
|
||||
uintptr(unsafe.Pointer(&freeBytesAvailable)),
|
||||
uintptr(unsafe.Pointer(&totalNumberOfBytes)),
|
||||
uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)))
|
||||
return ret != 0,
|
||||
freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes
|
||||
}
|
||||
|
||||
func GetSystemTime() *SYSTEMTIME {
|
||||
var time SYSTEMTIME
|
||||
procGetSystemTime.Call(
|
||||
uintptr(unsafe.Pointer(&time)))
|
||||
return &time
|
||||
}
|
||||
|
||||
func SetSystemTime(time *SYSTEMTIME) bool {
|
||||
ret, _, _ := procSetSystemTime.Call(
|
||||
uintptr(unsafe.Pointer(time)))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func GetLogicalDriveStrings(nBufferLength uint32, lpBuffer *uint16) uint32 {
|
||||
ret, _, _ := procGetLogicalDriveStrings.Call(
|
||||
uintptr(nBufferLength),
|
||||
uintptr(unsafe.Pointer(lpBuffer)),
|
||||
0)
|
||||
|
||||
return uint32(ret)
|
||||
}
|
65
v3/internal/w32/ole32.go
Normal file
65
v3/internal/w32/ole32.go
Normal file
@ -0,0 +1,65 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modole32 = syscall.NewLazyDLL("ole32.dll")
|
||||
|
||||
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
|
||||
procCoInitialize = modole32.NewProc("CoInitialize")
|
||||
procCoUninitialize = modole32.NewProc("CoUninitialize")
|
||||
procCreateStreamOnHGlobal = modole32.NewProc("CreateStreamOnHGlobal")
|
||||
)
|
||||
|
||||
func CoInitializeEx(coInit uintptr) HRESULT {
|
||||
ret, _, _ := procCoInitializeEx.Call(
|
||||
0,
|
||||
coInit)
|
||||
|
||||
switch uint32(ret) {
|
||||
case E_INVALIDARG:
|
||||
panic("CoInitializeEx failed with E_INVALIDARG")
|
||||
case E_OUTOFMEMORY:
|
||||
panic("CoInitializeEx failed with E_OUTOFMEMORY")
|
||||
case E_UNEXPECTED:
|
||||
panic("CoInitializeEx failed with E_UNEXPECTED")
|
||||
}
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func CoInitialize() {
|
||||
procCoInitialize.Call(0)
|
||||
}
|
||||
|
||||
func CoUninitialize() {
|
||||
procCoUninitialize.Call()
|
||||
}
|
||||
|
||||
func CreateStreamOnHGlobal(hGlobal HGLOBAL, fDeleteOnRelease bool) *IStream {
|
||||
stream := new(IStream)
|
||||
ret, _, _ := procCreateStreamOnHGlobal.Call(
|
||||
uintptr(hGlobal),
|
||||
uintptr(BoolToBOOL(fDeleteOnRelease)),
|
||||
uintptr(unsafe.Pointer(&stream)))
|
||||
|
||||
switch uint32(ret) {
|
||||
case E_INVALIDARG:
|
||||
panic("CreateStreamOnHGlobal failed with E_INVALIDARG")
|
||||
case E_OUTOFMEMORY:
|
||||
panic("CreateStreamOnHGlobal failed with E_OUTOFMEMORY")
|
||||
case E_UNEXPECTED:
|
||||
panic("CreateStreamOnHGlobal failed with E_UNEXPECTED")
|
||||
}
|
||||
|
||||
return stream
|
||||
}
|
50
v3/internal/w32/oleaut32.go
Normal file
50
v3/internal/w32/oleaut32.go
Normal file
@ -0,0 +1,50 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modoleaut32 = syscall.NewLazyDLL("oleaut32")
|
||||
|
||||
procVariantInit = modoleaut32.NewProc("VariantInit")
|
||||
procSysAllocString = modoleaut32.NewProc("SysAllocString")
|
||||
procSysFreeString = modoleaut32.NewProc("SysFreeString")
|
||||
procSysStringLen = modoleaut32.NewProc("SysStringLen")
|
||||
procCreateDispTypeInfo = modoleaut32.NewProc("CreateDispTypeInfo")
|
||||
procCreateStdDispatch = modoleaut32.NewProc("CreateStdDispatch")
|
||||
)
|
||||
|
||||
func VariantInit(v *VARIANT) {
|
||||
hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
|
||||
if hr != 0 {
|
||||
panic("Invoke VariantInit error.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SysAllocString(v string) (ss *int16) {
|
||||
pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
|
||||
ss = (*int16)(unsafe.Pointer(pss))
|
||||
return
|
||||
}
|
||||
|
||||
func SysFreeString(v *int16) {
|
||||
hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))
|
||||
if hr != 0 {
|
||||
panic("Invoke SysFreeString error.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SysStringLen(v *int16) uint {
|
||||
l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v)))
|
||||
return uint(l)
|
||||
}
|
29
v3/internal/w32/shcore.go
Normal file
29
v3/internal/w32/shcore.go
Normal file
@ -0,0 +1,29 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modshcore = syscall.NewLazyDLL("shcore.dll")
|
||||
|
||||
procGetDpiForMonitor = modshcore.NewProc("GetDpiForMonitor")
|
||||
)
|
||||
|
||||
func HasGetDPIForMonitorFunc() bool {
|
||||
err := procGetDpiForMonitor.Find()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func GetDPIForMonitor(hmonitor HMONITOR, dpiType MONITOR_DPI_TYPE, dpiX *UINT, dpiY *UINT) uintptr {
|
||||
ret, _, _ := procGetDpiForMonitor.Call(
|
||||
hmonitor,
|
||||
uintptr(dpiType),
|
||||
uintptr(unsafe.Pointer(dpiX)),
|
||||
uintptr(unsafe.Pointer(dpiY)))
|
||||
|
||||
return ret
|
||||
}
|
235
v3/internal/w32/shell32.go
Normal file
235
v3/internal/w32/shell32.go
Normal file
@ -0,0 +1,235 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
package w32
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type CSIDL uint32
|
||||
|
||||
const (
|
||||
CSIDL_DESKTOP = 0x00
|
||||
CSIDL_INTERNET = 0x01
|
||||
CSIDL_PROGRAMS = 0x02
|
||||
CSIDL_CONTROLS = 0x03
|
||||
CSIDL_PRINTERS = 0x04
|
||||
CSIDL_PERSONAL = 0x05
|
||||
CSIDL_FAVORITES = 0x06
|
||||
CSIDL_STARTUP = 0x07
|
||||
CSIDL_RECENT = 0x08
|
||||
CSIDL_SENDTO = 0x09
|
||||
CSIDL_BITBUCKET = 0x0A
|
||||
CSIDL_STARTMENU = 0x0B
|
||||
CSIDL_MYDOCUMENTS = 0x0C
|
||||
CSIDL_MYMUSIC = 0x0D
|
||||
CSIDL_MYVIDEO = 0x0E
|
||||
CSIDL_DESKTOPDIRECTORY = 0x10
|
||||
CSIDL_DRIVES = 0x11
|
||||
CSIDL_NETWORK = 0x12
|
||||
CSIDL_NETHOOD = 0x13
|
||||
CSIDL_FONTS = 0x14
|
||||
CSIDL_TEMPLATES = 0x15
|
||||
CSIDL_COMMON_STARTMENU = 0x16
|
||||
CSIDL_COMMON_PROGRAMS = 0x17
|
||||
CSIDL_COMMON_STARTUP = 0x18
|
||||
CSIDL_COMMON_DESKTOPDIRECTORY = 0x19
|
||||
CSIDL_APPDATA = 0x1A
|
||||
CSIDL_PRINTHOOD = 0x1B
|
||||
CSIDL_LOCAL_APPDATA = 0x1C
|
||||
CSIDL_ALTSTARTUP = 0x1D
|
||||
CSIDL_COMMON_ALTSTARTUP = 0x1E
|
||||
CSIDL_COMMON_FAVORITES = 0x1F
|
||||
CSIDL_INTERNET_CACHE = 0x20
|
||||
CSIDL_COOKIES = 0x21
|
||||
CSIDL_HISTORY = 0x22
|
||||
CSIDL_COMMON_APPDATA = 0x23
|
||||
CSIDL_WINDOWS = 0x24
|
||||
CSIDL_SYSTEM = 0x25
|
||||
CSIDL_PROGRAM_FILES = 0x26
|
||||
CSIDL_MYPICTURES = 0x27
|
||||
CSIDL_PROFILE = 0x28
|
||||
CSIDL_SYSTEMX86 = 0x29
|
||||
CSIDL_PROGRAM_FILESX86 = 0x2A
|
||||
CSIDL_PROGRAM_FILES_COMMON = 0x2B
|
||||
CSIDL_PROGRAM_FILES_COMMONX86 = 0x2C
|
||||
CSIDL_COMMON_TEMPLATES = 0x2D
|
||||
CSIDL_COMMON_DOCUMENTS = 0x2E
|
||||
CSIDL_COMMON_ADMINTOOLS = 0x2F
|
||||
CSIDL_ADMINTOOLS = 0x30
|
||||
CSIDL_CONNECTIONS = 0x31
|
||||
CSIDL_COMMON_MUSIC = 0x35
|
||||
CSIDL_COMMON_PICTURES = 0x36
|
||||
CSIDL_COMMON_VIDEO = 0x37
|
||||
CSIDL_RESOURCES = 0x38
|
||||
CSIDL_RESOURCES_LOCALIZED = 0x39
|
||||
CSIDL_COMMON_OEM_LINKS = 0x3A
|
||||
CSIDL_CDBURN_AREA = 0x3B
|
||||
CSIDL_COMPUTERSNEARME = 0x3D
|
||||
CSIDL_FLAG_CREATE = 0x8000
|
||||
CSIDL_FLAG_DONT_VERIFY = 0x4000
|
||||
CSIDL_FLAG_NO_ALIAS = 0x1000
|
||||
CSIDL_FLAG_PER_USER_INIT = 0x8000
|
||||
CSIDL_FLAG_MASK = 0xFF00
|
||||
)
|
||||
|
||||
var (
|
||||
modshell32 = syscall.NewLazyDLL("shell32.dll")
|
||||
|
||||
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolderW")
|
||||
procSHGetPathFromIDList = modshell32.NewProc("SHGetPathFromIDListW")
|
||||
procDragAcceptFiles = modshell32.NewProc("DragAcceptFiles")
|
||||
procDragQueryFile = modshell32.NewProc("DragQueryFileW")
|
||||
procDragQueryPoint = modshell32.NewProc("DragQueryPoint")
|
||||
procDragFinish = modshell32.NewProc("DragFinish")
|
||||
procShellExecute = modshell32.NewProc("ShellExecuteW")
|
||||
procExtractIcon = modshell32.NewProc("ExtractIconW")
|
||||
procGetSpecialFolderPath = modshell32.NewProc("SHGetSpecialFolderPathW")
|
||||
)
|
||||
|
||||
func SHBrowseForFolder(bi *BROWSEINFO) uintptr {
|
||||
ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi)))
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func SHGetPathFromIDList(idl uintptr) string {
|
||||
buf := make([]uint16, 1024)
|
||||
procSHGetPathFromIDList.Call(
|
||||
idl,
|
||||
uintptr(unsafe.Pointer(&buf[0])))
|
||||
|
||||
return syscall.UTF16ToString(buf)
|
||||
}
|
||||
|
||||
func DragAcceptFiles(hwnd HWND, accept bool) {
|
||||
procDragAcceptFiles.Call(
|
||||
uintptr(hwnd),
|
||||
uintptr(BoolToBOOL(accept)))
|
||||
}
|
||||
|
||||
func DragQueryFile(hDrop HDROP, iFile uint) (fileName string, fileCount uint) {
|
||||
ret, _, _ := procDragQueryFile.Call(
|
||||
uintptr(hDrop),
|
||||
uintptr(iFile),
|
||||
0,
|
||||
0)
|
||||
|
||||
fileCount = uint(ret)
|
||||
|
||||
if iFile != 0xFFFFFFFF {
|
||||
buf := make([]uint16, fileCount+1)
|
||||
|
||||
ret, _, _ := procDragQueryFile.Call(
|
||||
uintptr(hDrop),
|
||||
uintptr(iFile),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(fileCount+1))
|
||||
|
||||
if ret == 0 {
|
||||
panic("Invoke DragQueryFile error.")
|
||||
}
|
||||
|
||||
fileName = syscall.UTF16ToString(buf)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func DragQueryPoint(hDrop HDROP) (x, y int, isClientArea bool) {
|
||||
var pt POINT
|
||||
ret, _, _ := procDragQueryPoint.Call(
|
||||
uintptr(hDrop),
|
||||
uintptr(unsafe.Pointer(&pt)))
|
||||
|
||||
return int(pt.X), int(pt.Y), (ret == 1)
|
||||
}
|
||||
|
||||
func DragFinish(hDrop HDROP) {
|
||||
procDragFinish.Call(uintptr(hDrop))
|
||||
}
|
||||
|
||||
func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
|
||||
var op, param, directory uintptr
|
||||
if len(lpOperation) != 0 {
|
||||
op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
|
||||
}
|
||||
if len(lpParameters) != 0 {
|
||||
param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
|
||||
}
|
||||
if len(lpDirectory) != 0 {
|
||||
directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
|
||||
}
|
||||
|
||||
ret, _, _ := procShellExecute.Call(
|
||||
uintptr(hwnd),
|
||||
op,
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
|
||||
param,
|
||||
directory,
|
||||
uintptr(nShowCmd))
|
||||
|
||||
errorMsg := ""
|
||||
if ret != 0 && ret <= 32 {
|
||||
switch int(ret) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
errorMsg = "The specified file was not found."
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
errorMsg = "The specified path was not found."
|
||||
case ERROR_BAD_FORMAT:
|
||||
errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
|
||||
case SE_ERR_ACCESSDENIED:
|
||||
errorMsg = "The operating system denied access to the specified file."
|
||||
case SE_ERR_ASSOCINCOMPLETE:
|
||||
errorMsg = "The file name association is incomplete or invalid."
|
||||
case SE_ERR_DDEBUSY:
|
||||
errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
|
||||
case SE_ERR_DDEFAIL:
|
||||
errorMsg = "The DDE transaction failed."
|
||||
case SE_ERR_DDETIMEOUT:
|
||||
errorMsg = "The DDE transaction could not be completed because the request timed out."
|
||||
case SE_ERR_DLLNOTFOUND:
|
||||
errorMsg = "The specified DLL was not found."
|
||||
case SE_ERR_NOASSOC:
|
||||
errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable."
|
||||
case SE_ERR_OOM:
|
||||
errorMsg = "There was not enough memory to complete the operation."
|
||||
case SE_ERR_SHARE:
|
||||
errorMsg = "A sharing violation occurred."
|
||||
default:
|
||||
errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New(errorMsg)
|
||||
}
|
||||
|
||||
func ExtractIcon(lpszExeFileName string, nIconIndex int) HICON {
|
||||
ret, _, _ := procExtractIcon.Call(
|
||||
0,
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszExeFileName))),
|
||||
uintptr(nIconIndex))
|
||||
|
||||
return HICON(ret)
|
||||
}
|
||||
|
||||
func SHGetSpecialFolderPath(hwndOwner HWND, lpszPath *uint16, csidl CSIDL, fCreate bool) bool {
|
||||
ret, _, _ := procGetSpecialFolderPath.Call(
|
||||
uintptr(hwndOwner),
|
||||
uintptr(unsafe.Pointer(lpszPath)),
|
||||
uintptr(csidl),
|
||||
uintptr(BoolToBOOL(fCreate)),
|
||||
0,
|
||||
0)
|
||||
|
||||
return ret != 0
|
||||
}
|
26
v3/internal/w32/shlwapi.go
Normal file
26
v3/internal/w32/shlwapi.go
Normal file
@ -0,0 +1,26 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modshlwapi = syscall.NewLazyDLL("shlwapi.dll")
|
||||
|
||||
procSHCreateMemStream = modshlwapi.NewProc("SHCreateMemStream")
|
||||
)
|
||||
|
||||
func SHCreateMemStream(data []byte) (uintptr, error) {
|
||||
ret, _, err := procSHCreateMemStream.Call(
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
uintptr(len(data)),
|
||||
)
|
||||
if ret == 0 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
119
v3/internal/w32/theme.go
Normal file
119
v3/internal/w32/theme.go
Normal file
@ -0,0 +1,119 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
type DWMWINDOWATTRIBUTE int32
|
||||
|
||||
const DwmwaUseImmersiveDarkModeBefore20h1 DWMWINDOWATTRIBUTE = 19
|
||||
const DwmwaUseImmersiveDarkMode DWMWINDOWATTRIBUTE = 20
|
||||
const DwmwaBorderColor DWMWINDOWATTRIBUTE = 34
|
||||
const DwmwaCaptionColor DWMWINDOWATTRIBUTE = 35
|
||||
const DwmwaTextColor DWMWINDOWATTRIBUTE = 36
|
||||
const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38
|
||||
|
||||
const SPI_GETHIGHCONTRAST = 0x0042
|
||||
const HCF_HIGHCONTRASTON = 0x00000001
|
||||
|
||||
// BackdropType defines the type of translucency we wish to use
|
||||
type BackdropType int32
|
||||
|
||||
func dwmSetWindowAttribute(hwnd uintptr, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
|
||||
ret, _, err := procDwmSetWindowAttribute.Call(
|
||||
hwnd,
|
||||
uintptr(dwAttribute),
|
||||
uintptr(pvAttribute),
|
||||
cbAttribute)
|
||||
if ret != 0 {
|
||||
_ = err
|
||||
// println(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func SupportsThemes() bool {
|
||||
// We can't support Windows versions before 17763
|
||||
return IsWindowsVersionAtLeast(10, 0, 17763)
|
||||
}
|
||||
|
||||
func SupportsCustomThemes() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 17763)
|
||||
}
|
||||
|
||||
func SupportsBackdropTypes() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 22621)
|
||||
}
|
||||
|
||||
func SupportsImmersiveDarkMode() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 18985)
|
||||
}
|
||||
|
||||
func SetTheme(hwnd uintptr, useDarkMode bool) {
|
||||
if SupportsThemes() {
|
||||
attr := DwmwaUseImmersiveDarkModeBefore20h1
|
||||
if SupportsImmersiveDarkMode() {
|
||||
attr = DwmwaUseImmersiveDarkMode
|
||||
}
|
||||
var winDark int32
|
||||
if useDarkMode {
|
||||
winDark = 1
|
||||
}
|
||||
dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
|
||||
}
|
||||
}
|
||||
|
||||
func EnableTranslucency(hwnd uintptr, backdrop BackdropType) {
|
||||
if SupportsBackdropTypes() {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaSystemBackdropType, unsafe.Pointer(&backdrop), unsafe.Sizeof(backdrop))
|
||||
} else {
|
||||
println("Warning: Translucency type unavailable on Windows < 22621")
|
||||
}
|
||||
}
|
||||
|
||||
func SetTitleBarColour(hwnd uintptr, titleBarColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaCaptionColor, unsafe.Pointer(&titleBarColour), unsafe.Sizeof(titleBarColour))
|
||||
}
|
||||
|
||||
func SetTitleTextColour(hwnd uintptr, titleTextColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaTextColor, unsafe.Pointer(&titleTextColour), unsafe.Sizeof(titleTextColour))
|
||||
}
|
||||
|
||||
func SetBorderColour(hwnd uintptr, titleBorderColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaBorderColor, unsafe.Pointer(&titleBorderColour), unsafe.Sizeof(titleBorderColour))
|
||||
}
|
||||
|
||||
func IsCurrentlyDarkMode() bool {
|
||||
key, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer key.Close()
|
||||
|
||||
AppsUseLightTheme, _, err := key.GetIntegerValue("AppsUseLightTheme")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return AppsUseLightTheme == 0
|
||||
}
|
||||
|
||||
type highContrast struct {
|
||||
CbSize uint32
|
||||
DwFlags uint32
|
||||
LpszDefaultScheme *int16
|
||||
}
|
||||
|
||||
func IsCurrentlyHighContrastMode() bool {
|
||||
var result highContrast
|
||||
result.CbSize = uint32(unsafe.Sizeof(result))
|
||||
res, _, err := procSystemParametersInfo.Call(SPI_GETHIGHCONTRAST, uintptr(result.CbSize), uintptr(unsafe.Pointer(&result)), 0)
|
||||
if res == 0 {
|
||||
_ = err
|
||||
return false
|
||||
}
|
||||
r := result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON
|
||||
return r
|
||||
}
|
216
v3/internal/w32/toolbar.go
Normal file
216
v3/internal/w32/toolbar.go
Normal file
@ -0,0 +1,216 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
// ToolBar messages
|
||||
const (
|
||||
TB_ENABLEBUTTON = WM_USER + 1
|
||||
TB_CHECKBUTTON = WM_USER + 2
|
||||
TB_PRESSBUTTON = WM_USER + 3
|
||||
TB_HIDEBUTTON = WM_USER + 4
|
||||
TB_INDETERMINATE = WM_USER + 5
|
||||
TB_MARKBUTTON = WM_USER + 6
|
||||
TB_ISBUTTONENABLED = WM_USER + 9
|
||||
TB_ISBUTTONCHECKED = WM_USER + 10
|
||||
TB_ISBUTTONPRESSED = WM_USER + 11
|
||||
TB_ISBUTTONHIDDEN = WM_USER + 12
|
||||
TB_ISBUTTONINDETERMINATE = WM_USER + 13
|
||||
TB_ISBUTTONHIGHLIGHTED = WM_USER + 14
|
||||
TB_SETSTATE = WM_USER + 17
|
||||
TB_GETSTATE = WM_USER + 18
|
||||
TB_ADDBITMAP = WM_USER + 19
|
||||
TB_DELETEBUTTON = WM_USER + 22
|
||||
TB_GETBUTTON = WM_USER + 23
|
||||
TB_BUTTONCOUNT = WM_USER + 24
|
||||
TB_COMMANDTOINDEX = WM_USER + 25
|
||||
TB_SAVERESTORE = WM_USER + 76
|
||||
TB_CUSTOMIZE = WM_USER + 27
|
||||
TB_ADDSTRING = WM_USER + 77
|
||||
TB_GETITEMRECT = WM_USER + 29
|
||||
TB_BUTTONSTRUCTSIZE = WM_USER + 30
|
||||
TB_SETBUTTONSIZE = WM_USER + 31
|
||||
TB_SETBITMAPSIZE = WM_USER + 32
|
||||
TB_AUTOSIZE = WM_USER + 33
|
||||
TB_GETTOOLTIPS = WM_USER + 35
|
||||
TB_SETTOOLTIPS = WM_USER + 36
|
||||
TB_SETPARENT = WM_USER + 37
|
||||
TB_SETROWS = WM_USER + 39
|
||||
TB_GETROWS = WM_USER + 40
|
||||
TB_GETBITMAPFLAGS = WM_USER + 41
|
||||
TB_SETCMDID = WM_USER + 42
|
||||
TB_CHANGEBITMAP = WM_USER + 43
|
||||
TB_GETBITMAP = WM_USER + 44
|
||||
TB_GETBUTTONTEXT = WM_USER + 75
|
||||
TB_REPLACEBITMAP = WM_USER + 46
|
||||
TB_GETBUTTONSIZE = WM_USER + 58
|
||||
TB_SETBUTTONWIDTH = WM_USER + 59
|
||||
TB_SETINDENT = WM_USER + 47
|
||||
TB_SETIMAGELIST = WM_USER + 48
|
||||
TB_GETIMAGELIST = WM_USER + 49
|
||||
TB_LOADIMAGES = WM_USER + 50
|
||||
TB_GETRECT = WM_USER + 51
|
||||
TB_SETHOTIMAGELIST = WM_USER + 52
|
||||
TB_GETHOTIMAGELIST = WM_USER + 53
|
||||
TB_SETDISABLEDIMAGELIST = WM_USER + 54
|
||||
TB_GETDISABLEDIMAGELIST = WM_USER + 55
|
||||
TB_SETSTYLE = WM_USER + 56
|
||||
TB_GETSTYLE = WM_USER + 57
|
||||
TB_SETMAXTEXTROWS = WM_USER + 60
|
||||
TB_GETTEXTROWS = WM_USER + 61
|
||||
TB_GETOBJECT = WM_USER + 62
|
||||
TB_GETBUTTONINFO = WM_USER + 63
|
||||
TB_SETBUTTONINFO = WM_USER + 64
|
||||
TB_INSERTBUTTON = WM_USER + 67
|
||||
TB_ADDBUTTONS = WM_USER + 68
|
||||
TB_HITTEST = WM_USER + 69
|
||||
TB_SETDRAWTEXTFLAGS = WM_USER + 70
|
||||
TB_GETHOTITEM = WM_USER + 71
|
||||
TB_SETHOTITEM = WM_USER + 72
|
||||
TB_SETANCHORHIGHLIGHT = WM_USER + 73
|
||||
TB_GETANCHORHIGHLIGHT = WM_USER + 74
|
||||
TB_GETINSERTMARK = WM_USER + 79
|
||||
TB_SETINSERTMARK = WM_USER + 80
|
||||
TB_INSERTMARKHITTEST = WM_USER + 81
|
||||
TB_MOVEBUTTON = WM_USER + 82
|
||||
TB_GETMAXSIZE = WM_USER + 83
|
||||
TB_SETEXTENDEDSTYLE = WM_USER + 84
|
||||
TB_GETEXTENDEDSTYLE = WM_USER + 85
|
||||
TB_GETPADDING = WM_USER + 86
|
||||
TB_SETPADDING = WM_USER + 87
|
||||
TB_SETINSERTMARKCOLOR = WM_USER + 88
|
||||
TB_GETINSERTMARKCOLOR = WM_USER + 89
|
||||
TB_MAPACCELERATOR = WM_USER + 90
|
||||
TB_GETSTRING = WM_USER + 91
|
||||
TB_SETCOLORSCHEME = CCM_SETCOLORSCHEME
|
||||
TB_GETCOLORSCHEME = CCM_GETCOLORSCHEME
|
||||
TB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT
|
||||
TB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT
|
||||
)
|
||||
|
||||
// ToolBar notifications
|
||||
const (
|
||||
TBN_FIRST = -700
|
||||
TBN_DROPDOWN = TBN_FIRST - 10
|
||||
)
|
||||
|
||||
// TBN_DROPDOWN return codes
|
||||
const (
|
||||
TBDDRET_DEFAULT = 0
|
||||
TBDDRET_NODEFAULT = 1
|
||||
TBDDRET_TREATPRESSED = 2
|
||||
)
|
||||
|
||||
// ToolBar state constants
|
||||
const (
|
||||
TBSTATE_CHECKED = 1
|
||||
TBSTATE_PRESSED = 2
|
||||
TBSTATE_ENABLED = 4
|
||||
TBSTATE_HIDDEN = 8
|
||||
TBSTATE_INDETERMINATE = 16
|
||||
TBSTATE_WRAP = 32
|
||||
TBSTATE_ELLIPSES = 0x40
|
||||
TBSTATE_MARKED = 0x0080
|
||||
)
|
||||
|
||||
// ToolBar style constants
|
||||
const (
|
||||
TBSTYLE_BUTTON = 0
|
||||
TBSTYLE_SEP = 1
|
||||
TBSTYLE_CHECK = 2
|
||||
TBSTYLE_GROUP = 4
|
||||
TBSTYLE_CHECKGROUP = TBSTYLE_GROUP | TBSTYLE_CHECK
|
||||
TBSTYLE_DROPDOWN = 8
|
||||
TBSTYLE_AUTOSIZE = 16
|
||||
TBSTYLE_NOPREFIX = 32
|
||||
TBSTYLE_TOOLTIPS = 256
|
||||
TBSTYLE_WRAPABLE = 512
|
||||
TBSTYLE_ALTDRAG = 1024
|
||||
TBSTYLE_FLAT = 2048
|
||||
TBSTYLE_LIST = 4096
|
||||
TBSTYLE_CUSTOMERASE = 8192
|
||||
TBSTYLE_REGISTERDROP = 0x4000
|
||||
TBSTYLE_TRANSPARENT = 0x8000
|
||||
)
|
||||
|
||||
// ToolBar extended style constants
|
||||
const (
|
||||
TBSTYLE_EX_DRAWDDARROWS = 0x00000001
|
||||
TBSTYLE_EX_MIXEDBUTTONS = 8
|
||||
TBSTYLE_EX_HIDECLIPPEDBUTTONS = 16
|
||||
TBSTYLE_EX_DOUBLEBUFFER = 0x80
|
||||
)
|
||||
|
||||
// ToolBar button style constants
|
||||
const (
|
||||
BTNS_BUTTON = TBSTYLE_BUTTON
|
||||
BTNS_SEP = TBSTYLE_SEP
|
||||
BTNS_CHECK = TBSTYLE_CHECK
|
||||
BTNS_GROUP = TBSTYLE_GROUP
|
||||
BTNS_CHECKGROUP = TBSTYLE_CHECKGROUP
|
||||
BTNS_DROPDOWN = TBSTYLE_DROPDOWN
|
||||
BTNS_AUTOSIZE = TBSTYLE_AUTOSIZE
|
||||
BTNS_NOPREFIX = TBSTYLE_NOPREFIX
|
||||
BTNS_WHOLEDROPDOWN = 0x0080
|
||||
BTNS_SHOWTEXT = 0x0040
|
||||
)
|
||||
|
||||
// TBBUTTONINFO mask flags
|
||||
const (
|
||||
TBIF_IMAGE = 0x00000001
|
||||
TBIF_TEXT = 0x00000002
|
||||
TBIF_STATE = 0x00000004
|
||||
TBIF_STYLE = 0x00000008
|
||||
TBIF_LPARAM = 0x00000010
|
||||
TBIF_COMMAND = 0x00000020
|
||||
TBIF_SIZE = 0x00000040
|
||||
TBIF_BYINDEX = 0x80000000
|
||||
)
|
||||
|
||||
type NMMOUSE struct {
|
||||
Hdr NMHDR
|
||||
DwItemSpec uintptr
|
||||
DwItemData uintptr
|
||||
Pt POINT
|
||||
DwHitInfo uintptr
|
||||
}
|
||||
|
||||
type NMTOOLBAR struct {
|
||||
Hdr NMHDR
|
||||
IItem int32
|
||||
TbButton TBBUTTON
|
||||
CchText int32
|
||||
PszText *uint16
|
||||
RcButton RECT
|
||||
}
|
||||
|
||||
type TBBUTTON struct {
|
||||
IBitmap int32
|
||||
IdCommand int32
|
||||
FsState byte
|
||||
FsStyle byte
|
||||
//#ifdef _WIN64
|
||||
// BYTE bReserved[6] // padding for alignment
|
||||
//#elif defined(_WIN32)
|
||||
BReserved [2]byte // padding for alignment
|
||||
//#endif
|
||||
DwData uintptr
|
||||
IString uintptr
|
||||
}
|
||||
|
||||
type TBBUTTONINFO struct {
|
||||
CbSize uint32
|
||||
DwMask uint32
|
||||
IdCommand int32
|
||||
IImage int32
|
||||
FsState byte
|
||||
FsStyle byte
|
||||
Cx uint16
|
||||
LParam uintptr
|
||||
PszText uintptr
|
||||
CchText int32
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1281
v3/internal/w32/user32.go
Normal file
1281
v3/internal/w32/user32.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,92 +1,81 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type pIUnknownVtbl struct {
|
||||
queryInterface uintptr
|
||||
addRef uintptr
|
||||
release uintptr
|
||||
func MustLoadLibrary(name string) uintptr {
|
||||
lib, err := syscall.LoadLibrary(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return uintptr(lib)
|
||||
}
|
||||
|
||||
type IUnknown struct {
|
||||
lpVtbl *pIUnknownVtbl
|
||||
func MustGetProcAddress(lib uintptr, name string) uintptr {
|
||||
addr, err := syscall.GetProcAddress(syscall.Handle(lib), name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return uintptr(addr)
|
||||
}
|
||||
|
||||
func (u *IUnknown) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
|
||||
return ComQueryInterface(u, id)
|
||||
func SUCCEEDED(hr HRESULT) bool {
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
func (u *IUnknown) AddRef() int32 {
|
||||
return ComAddRef(u)
|
||||
func FAILED(hr HRESULT) bool {
|
||||
return hr < 0
|
||||
}
|
||||
|
||||
func (u *IUnknown) Release() int32 {
|
||||
return ComRelease(u)
|
||||
func LOWORD(dw uint32) uint16 {
|
||||
return uint16(dw)
|
||||
}
|
||||
|
||||
type pIDispatchVtbl struct {
|
||||
queryInterface uintptr
|
||||
addRef uintptr
|
||||
release uintptr
|
||||
getTypeInfoCount uintptr
|
||||
getTypeInfo uintptr
|
||||
getIDsOfNames uintptr
|
||||
invoke uintptr
|
||||
func HIWORD(dw uint32) uint16 {
|
||||
return uint16(dw >> 16 & 0xffff)
|
||||
}
|
||||
|
||||
type IDispatch struct {
|
||||
lpVtbl *pIDispatchVtbl
|
||||
func MAKELONG(lo, hi uint16) uint32 {
|
||||
return uint32(uint32(lo) | ((uint32(hi)) << 16))
|
||||
}
|
||||
|
||||
func (d *IDispatch) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
|
||||
return ComQueryInterface((*IUnknown)(unsafe.Pointer(d)), id)
|
||||
func BoolToBOOL(value bool) BOOL {
|
||||
if value {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (d *IDispatch) AddRef() int32 {
|
||||
return ComAddRef((*IUnknown)(unsafe.Pointer(d)))
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
return ""
|
||||
}
|
||||
|
||||
func ComAddRef(unknown *IUnknown) int32 {
|
||||
ret, _, _ := syscall.Syscall(unknown.lpVtbl.addRef, 1,
|
||||
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1,
|
||||
uintptr(unsafe.Pointer(unknown)),
|
||||
0,
|
||||
0)
|
||||
@ -94,41 +83,45 @@ func ComAddRef(unknown *IUnknown) int32 {
|
||||
}
|
||||
|
||||
func ComRelease(unknown *IUnknown) int32 {
|
||||
ret, _, _ := syscall.Syscall(unknown.lpVtbl.release, 1,
|
||||
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1,
|
||||
uintptr(unsafe.Pointer(unknown)),
|
||||
0,
|
||||
0)
|
||||
return int32(ret)
|
||||
}
|
||||
|
||||
func ComQueryInterface(unknown *IUnknown, id *GUID) (*IDispatch, HRESULT) {
|
||||
func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
|
||||
var disp *IDispatch
|
||||
hr, _, _ := syscall.Syscall(unknown.lpVtbl.queryInterface, 3,
|
||||
hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3,
|
||||
uintptr(unsafe.Pointer(unknown)),
|
||||
uintptr(unsafe.Pointer(id)),
|
||||
uintptr(unsafe.Pointer(&disp)),
|
||||
)
|
||||
return disp, HRESULT(hr)
|
||||
uintptr(unsafe.Pointer(&disp)))
|
||||
if hr != 0 {
|
||||
panic("Invoke QieryInterface error.")
|
||||
}
|
||||
return disp
|
||||
}
|
||||
|
||||
func ComGetIDsOfName(disp *IDispatch, names []string) ([]int32, HRESULT) {
|
||||
func ComGetIDsOfName(disp *IDispatch, names []string) []int32 {
|
||||
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,
|
||||
hr, _, _ := syscall.Syscall6(disp.lpVtbl.pGetIDsOfNames, 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)
|
||||
uintptr(unsafe.Pointer(&dispid[0])))
|
||||
if hr != 0 {
|
||||
panic("Invoke GetIDsOfName error.")
|
||||
}
|
||||
return dispid
|
||||
}
|
||||
|
||||
func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
|
||||
func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT) {
|
||||
var dispparams DISPPARAMS
|
||||
|
||||
if dispatch&DISPATCH_PROPERTYPUT != 0 {
|
||||
@ -140,6 +133,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
if len(params) > 0 {
|
||||
vargs = make([]VARIANT, len(params))
|
||||
for i, v := range params {
|
||||
//n := len(params)-i-1
|
||||
n := len(params) - i - 1
|
||||
VariantInit(&vargs[n])
|
||||
switch v.(type) {
|
||||
@ -200,7 +194,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
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")
|
||||
panic("unknown type")
|
||||
}
|
||||
}
|
||||
dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
|
||||
@ -210,7 +204,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
var ret VARIANT
|
||||
var excepInfo EXCEPINFO
|
||||
VariantInit(&ret)
|
||||
hr, _, _ := syscall.Syscall9(disp.lpVtbl.invoke, 8,
|
||||
hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8,
|
||||
uintptr(unsafe.Pointer(disp)),
|
||||
uintptr(dispid),
|
||||
uintptr(unsafe.Pointer(IID_NULL)),
|
||||
@ -223,7 +217,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
if hr != 0 {
|
||||
if excepInfo.BstrDescription != nil {
|
||||
bs := UTF16PtrToString(excepInfo.BstrDescription)
|
||||
return nil, errors.New(bs)
|
||||
panic(bs)
|
||||
}
|
||||
}
|
||||
for _, varg := range vargs {
|
||||
@ -234,18 +228,3 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
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 ""
|
||||
}
|
152
v3/internal/w32/uxtheme.go
Normal file
152
v3/internal/w32/uxtheme.go
Normal file
@ -0,0 +1,152 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// LISTVIEW parts
|
||||
const (
|
||||
LVP_LISTITEM = 1
|
||||
LVP_LISTGROUP = 2
|
||||
LVP_LISTDETAIL = 3
|
||||
LVP_LISTSORTEDDETAIL = 4
|
||||
LVP_EMPTYTEXT = 5
|
||||
LVP_GROUPHEADER = 6
|
||||
LVP_GROUPHEADERLINE = 7
|
||||
LVP_EXPANDBUTTON = 8
|
||||
LVP_COLLAPSEBUTTON = 9
|
||||
LVP_COLUMNDETAIL = 10
|
||||
)
|
||||
|
||||
// LVP_LISTITEM states
|
||||
const (
|
||||
LISS_NORMAL = 1
|
||||
LISS_HOT = 2
|
||||
LISS_SELECTED = 3
|
||||
LISS_DISABLED = 4
|
||||
LISS_SELECTEDNOTFOCUS = 5
|
||||
LISS_HOTSELECTED = 6
|
||||
)
|
||||
|
||||
// TREEVIEW parts
|
||||
const (
|
||||
TVP_TREEITEM = 1
|
||||
TVP_GLYPH = 2
|
||||
TVP_BRANCH = 3
|
||||
TVP_HOTGLYPH = 4
|
||||
)
|
||||
|
||||
// TVP_TREEITEM states
|
||||
const (
|
||||
TREIS_NORMAL = 1
|
||||
TREIS_HOT = 2
|
||||
TREIS_SELECTED = 3
|
||||
TREIS_DISABLED = 4
|
||||
TREIS_SELECTEDNOTFOCUS = 5
|
||||
TREIS_HOTSELECTED = 6
|
||||
)
|
||||
|
||||
type HTHEME HANDLE
|
||||
|
||||
var (
|
||||
// Library
|
||||
libuxtheme uintptr
|
||||
|
||||
// Functions
|
||||
closeThemeData uintptr
|
||||
drawThemeBackground uintptr
|
||||
drawThemeText uintptr
|
||||
getThemeTextExtent uintptr
|
||||
openThemeData uintptr
|
||||
setWindowTheme uintptr
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Library
|
||||
libuxtheme = MustLoadLibrary("uxtheme.dll")
|
||||
|
||||
// Functions
|
||||
closeThemeData = MustGetProcAddress(libuxtheme, "CloseThemeData")
|
||||
drawThemeBackground = MustGetProcAddress(libuxtheme, "DrawThemeBackground")
|
||||
drawThemeText = MustGetProcAddress(libuxtheme, "DrawThemeText")
|
||||
getThemeTextExtent = MustGetProcAddress(libuxtheme, "GetThemeTextExtent")
|
||||
openThemeData = MustGetProcAddress(libuxtheme, "OpenThemeData")
|
||||
setWindowTheme = MustGetProcAddress(libuxtheme, "SetWindowTheme")
|
||||
}
|
||||
|
||||
func CloseThemeData(hTheme HTHEME) HRESULT {
|
||||
ret, _, _ := syscall.Syscall(closeThemeData, 1,
|
||||
uintptr(hTheme),
|
||||
0,
|
||||
0)
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func DrawThemeBackground(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pRect, pClipRect *RECT) HRESULT {
|
||||
ret, _, _ := syscall.Syscall6(drawThemeBackground, 6,
|
||||
uintptr(hTheme),
|
||||
uintptr(hdc),
|
||||
uintptr(iPartId),
|
||||
uintptr(iStateId),
|
||||
uintptr(unsafe.Pointer(pRect)),
|
||||
uintptr(unsafe.Pointer(pClipRect)))
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func DrawThemeText(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText *uint16, iCharCount int32, dwTextFlags, dwTextFlags2 uint32, pRect *RECT) HRESULT {
|
||||
ret, _, _ := syscall.Syscall9(drawThemeText, 9,
|
||||
uintptr(hTheme),
|
||||
uintptr(hdc),
|
||||
uintptr(iPartId),
|
||||
uintptr(iStateId),
|
||||
uintptr(unsafe.Pointer(pszText)),
|
||||
uintptr(iCharCount),
|
||||
uintptr(dwTextFlags),
|
||||
uintptr(dwTextFlags2),
|
||||
uintptr(unsafe.Pointer(pRect)))
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func GetThemeTextExtent(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText *uint16, iCharCount int32, dwTextFlags uint32, pBoundingRect, pExtentRect *RECT) HRESULT {
|
||||
ret, _, _ := syscall.Syscall9(getThemeTextExtent, 9,
|
||||
uintptr(hTheme),
|
||||
uintptr(hdc),
|
||||
uintptr(iPartId),
|
||||
uintptr(iStateId),
|
||||
uintptr(unsafe.Pointer(pszText)),
|
||||
uintptr(iCharCount),
|
||||
uintptr(dwTextFlags),
|
||||
uintptr(unsafe.Pointer(pBoundingRect)),
|
||||
uintptr(unsafe.Pointer(pExtentRect)))
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
||||
|
||||
func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME {
|
||||
ret, _, _ := syscall.Syscall(openThemeData, 2,
|
||||
uintptr(hwnd),
|
||||
uintptr(unsafe.Pointer(pszClassList)),
|
||||
0)
|
||||
|
||||
return HTHEME(ret)
|
||||
}
|
||||
|
||||
func SetWindowTheme(hwnd HWND, pszSubAppName, pszSubIdList *uint16) HRESULT {
|
||||
ret, _, _ := syscall.Syscall(setWindowTheme, 3,
|
||||
uintptr(hwnd),
|
||||
uintptr(unsafe.Pointer(pszSubAppName)),
|
||||
uintptr(unsafe.Pointer(pszSubIdList)))
|
||||
|
||||
return HRESULT(ret)
|
||||
}
|
16
v3/internal/w32/vars.go
Normal file
16
v3/internal/w32/vars.go
Normal file
@ -0,0 +1,16 @@
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Tad Vizbaras. All Rights Reserved.
|
||||
* Copyright (C) 2010-2012 The W32 Authors. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package w32
|
||||
|
||||
var (
|
||||
IID_NULL = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
|
||||
IID_IUnknown = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
|
||||
IID_IDispatch = &GUID{0x00020400, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
|
||||
IID_IConnectionPointContainer = &GUID{0xB196B284, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}
|
||||
IID_IConnectionPoint = &GUID{0xB196B286, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}
|
||||
)
|
137
v3/internal/w32/window.go
Normal file
137
v3/internal/w32/window.go
Normal file
@ -0,0 +1,137 @@
|
||||
package w32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
GCLP_HBRBACKGROUND int32 = -10
|
||||
)
|
||||
|
||||
func ExtendFrameIntoClientArea(hwnd uintptr, extend bool) {
|
||||
// -1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11)
|
||||
// Also shows the caption buttons if transparent ant translucent but they don't work.
|
||||
// 0: Adds the default frame styling but no aero shadow, does not show the caption buttons.
|
||||
// 1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11) but no caption buttons
|
||||
// are shown if transparent ant translucent.
|
||||
var margins MARGINS
|
||||
if extend {
|
||||
margins = MARGINS{1, 1, 1, 1} // Only extend 1 pixel to have the default frame styling but no caption buttons
|
||||
}
|
||||
if err := dwmExtendFrameIntoClientArea(hwnd, &margins); err != nil {
|
||||
log.Fatal(fmt.Errorf("DwmExtendFrameIntoClientArea failed: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
func IsVisible(hwnd uintptr) bool {
|
||||
ret, _, _ := procIsWindowVisible.Call(hwnd)
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func IsWindowFullScreen(hwnd uintptr) bool {
|
||||
wRect := GetWindowRect(hwnd)
|
||||
m := MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)
|
||||
var mi MONITORINFO
|
||||
mi.CbSize = uint32(unsafe.Sizeof(mi))
|
||||
if !GetMonitorInfo(m, &mi) {
|
||||
return false
|
||||
}
|
||||
return wRect.Left == mi.RcMonitor.Left &&
|
||||
wRect.Top == mi.RcMonitor.Top &&
|
||||
wRect.Right == mi.RcMonitor.Right &&
|
||||
wRect.Bottom == mi.RcMonitor.Bottom
|
||||
}
|
||||
|
||||
func IsWindowMaximised(hwnd uintptr) bool {
|
||||
style := uint32(getWindowLong(hwnd, GWL_STYLE))
|
||||
return style&WS_MAXIMIZE != 0
|
||||
}
|
||||
func IsWindowMinimised(hwnd uintptr) bool {
|
||||
style := uint32(getWindowLong(hwnd, GWL_STYLE))
|
||||
return style&WS_MINIMIZE != 0
|
||||
}
|
||||
|
||||
func RestoreWindow(hwnd uintptr) {
|
||||
showWindow(hwnd, SW_RESTORE)
|
||||
}
|
||||
|
||||
func ShowWindowMaximised(hwnd uintptr) {
|
||||
showWindow(hwnd, SW_MAXIMIZE)
|
||||
}
|
||||
func ShowWindowMinimised(hwnd uintptr) {
|
||||
showWindow(hwnd, SW_MINIMIZE)
|
||||
}
|
||||
|
||||
func SetBackgroundColour(hwnd uintptr, r, g, b uint8) {
|
||||
col := uint32(r) | uint32(g)<<8 | uint32(b)<<16
|
||||
hbrush, _, _ := procCreateSolidBrush.Call(uintptr(col))
|
||||
setClassLongPtr(hwnd, GCLP_HBRBACKGROUND, hbrush)
|
||||
}
|
||||
|
||||
func IsWindowNormal(hwnd uintptr) bool {
|
||||
return !IsWindowMaximised(hwnd) && !IsWindowMinimised(hwnd) && !IsWindowFullScreen(hwnd)
|
||||
}
|
||||
|
||||
func setClassLongPtr(hwnd uintptr, param int32, val uintptr) bool {
|
||||
proc := procSetClassLongPtr
|
||||
if strconv.IntSize == 32 {
|
||||
/*
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongptrw
|
||||
Note: To write code that is compatible with both 32-bit and 64-bit Windows, use SetClassLongPtr.
|
||||
When compiling for 32-bit Windows, SetClassLongPtr is defined as a call to the SetClassLong function
|
||||
|
||||
=> We have to do this dynamically when directly calling the DLL procedures
|
||||
*/
|
||||
proc = procSetClassLong
|
||||
}
|
||||
|
||||
ret, _, _ := proc.Call(
|
||||
hwnd,
|
||||
uintptr(param),
|
||||
val,
|
||||
)
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func getWindowLong(hwnd uintptr, index int) int32 {
|
||||
ret, _, _ := procGetWindowLong.Call(
|
||||
hwnd,
|
||||
uintptr(index))
|
||||
|
||||
return int32(ret)
|
||||
}
|
||||
|
||||
func showWindow(hwnd uintptr, cmdshow int) bool {
|
||||
ret, _, _ := procShowWindow.Call(
|
||||
hwnd,
|
||||
uintptr(cmdshow))
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func MustStringToUTF16Ptr(input string) *uint16 {
|
||||
ret, err := syscall.UTF16PtrFromString(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func MustStringToUTF16uintptr(input string) uintptr {
|
||||
ret, err := syscall.UTF16PtrFromString(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return uintptr(unsafe.Pointer(ret))
|
||||
}
|
||||
|
||||
func MustUTF16FromString(input string) []uint16 {
|
||||
ret, err := syscall.UTF16FromString(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
@ -17,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
wmInvokeCallback = w32.RegisterWindowMessage("WailsV0.InvokeCallback")
|
||||
wmInvokeCallback = w32.RegisterWindowMessage(w32.MustStringToUTF16Ptr("WailsV0.InvokeCallback"))
|
||||
}
|
||||
|
||||
// initMainLoop must be called with the same OSThread that is used to call runMainLoop() later.
|
||||
|
@ -102,7 +102,7 @@ func (m *MessageProcessor) processWindowMethod(method string, rw http.ResponseWr
|
||||
m.Error("Invalid SetBackgroundColour Message: 'a' value required")
|
||||
return
|
||||
}
|
||||
window.SetBackgroundColour(&RGBA{
|
||||
window.SetBackgroundColour(RGBA{
|
||||
Red: *r,
|
||||
Green: *g,
|
||||
Blue: *b,
|
||||
|
@ -23,7 +23,8 @@ type WebviewWindowOptions struct {
|
||||
MaxHeight int
|
||||
StartState WindowState
|
||||
Mac MacWindow
|
||||
BackgroundColour *RGBA
|
||||
BackgroundType BackgroundType
|
||||
BackgroundColour RGBA
|
||||
HTML string
|
||||
JS string
|
||||
CSS string
|
||||
@ -43,8 +44,22 @@ var WebviewWindowDefaults = &WebviewWindowOptions{
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
URL: "",
|
||||
BackgroundColour: RGBA{
|
||||
Red: 255,
|
||||
Green: 255,
|
||||
Blue: 255,
|
||||
Alpha: 255,
|
||||
},
|
||||
}
|
||||
|
||||
type RGBA struct {
|
||||
Red, Green, Blue, Alpha uint8
|
||||
}
|
||||
|
||||
type BackgroundType int
|
||||
|
||||
const (
|
||||
BackgroundTypeSolid BackgroundType = iota
|
||||
BackgroundTypeTransparent
|
||||
BackgroundTypeTranslucent
|
||||
)
|
||||
|
@ -1,5 +1,18 @@
|
||||
package application
|
||||
|
||||
type BackdropType int32
|
||||
|
||||
const (
|
||||
Auto BackdropType = 0
|
||||
None BackdropType = 1
|
||||
Mica BackdropType = 2
|
||||
Acrylic BackdropType = 3
|
||||
Tabbed BackdropType = 4
|
||||
)
|
||||
|
||||
type WindowsWindow struct {
|
||||
AlwaysOnTop bool
|
||||
// Select the type of translucent backdrop. Requires Windows 11 22621 or later.
|
||||
BackdropType BackdropType
|
||||
// Disable the icon in the titlebar
|
||||
DisableIcon bool
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ type (
|
||||
setMaxSize(width, height int)
|
||||
execJS(js string)
|
||||
restore()
|
||||
setBackgroundColour(color *RGBA)
|
||||
setBackgroundColour(color RGBA)
|
||||
run()
|
||||
center()
|
||||
size() (int, int)
|
||||
@ -171,7 +171,7 @@ func (w *WebviewWindow) run() {
|
||||
|
||||
func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow {
|
||||
w.options.AlwaysOnTop = b
|
||||
if w.impl == nil {
|
||||
if w.impl != nil {
|
||||
w.impl.setAlwaysOnTop(b)
|
||||
}
|
||||
return w
|
||||
@ -346,7 +346,7 @@ func (w *WebviewWindow) IsFullscreen() bool {
|
||||
return w.impl.isFullscreen()
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) SetBackgroundColour(colour *RGBA) *WebviewWindow {
|
||||
func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow {
|
||||
w.options.BackgroundColour = colour
|
||||
if w.impl != nil {
|
||||
w.impl.setBackgroundColour(colour)
|
||||
|
@ -1147,7 +1147,7 @@ func (w *macosWebviewWindow) run() {
|
||||
})
|
||||
}
|
||||
|
||||
func (w *macosWebviewWindow) setBackgroundColour(colour *RGBA) {
|
||||
func (w *macosWebviewWindow) setBackgroundColour(colour RGBA) {
|
||||
if colour == nil {
|
||||
return
|
||||
}
|
||||
|
@ -3,11 +3,13 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v3/internal/w32"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/wailsapp/wails/v3/internal/w32"
|
||||
)
|
||||
|
||||
var showDevTools = func(window unsafe.Pointer) {}
|
||||
@ -15,6 +17,7 @@ var showDevTools = func(window unsafe.Pointer) {}
|
||||
type windowsWebviewWindow struct {
|
||||
windowImpl unsafe.Pointer
|
||||
parent *WebviewWindow
|
||||
hwnd w32.HWND
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setTitle(title string) {
|
||||
@ -23,13 +26,18 @@ func (w *windowsWebviewWindow) setTitle(title string) {
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setSize(width, height int) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
x, y := w.position()
|
||||
w32.MoveWindow(w.hwnd, x, y, width, height, true)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
globalApplication.dispatchOnMainThread(func() {
|
||||
position := w32.HWND_NOTOPMOST
|
||||
if alwaysOnTop {
|
||||
position = w32.HWND_TOPMOST
|
||||
}
|
||||
w32.SetWindowPos(w.hwnd, position, 0, 0, 0, 0, uint(w32.SWP_NOMOVE|w32.SWP_NOSIZE))
|
||||
})
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setURL(url string) {
|
||||
@ -38,8 +46,9 @@ func (w *windowsWebviewWindow) setURL(url string) {
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setResizable(resizable bool) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
globalApplication.dispatchOnMainThread(func() {
|
||||
w.setStyle(resizable, w32.WS_THICKFRAME)
|
||||
})
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setMinSize(width, height int) {
|
||||
@ -62,9 +71,8 @@ func (w *windowsWebviewWindow) restore() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setBackgroundColour(color *RGBA) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
func (w *windowsWebviewWindow) setBackgroundColour(color RGBA) {
|
||||
w32.SetBackgroundColour(w.hwnd, color.Red, color.Green, color.Blue)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) run() {
|
||||
@ -74,22 +82,18 @@ func (w *windowsWebviewWindow) run() {
|
||||
func (w *windowsWebviewWindow) _run() {
|
||||
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 {
|
||||
if options.BackgroundType != BackgroundTypeSolid {
|
||||
exStyle |= w32.WS_EX_NOREDIRECTIONBITMAP
|
||||
}
|
||||
if options.AlwaysOnTop {
|
||||
exStyle |= w32.WS_EX_TOPMOST
|
||||
}
|
||||
var hwnd w32.HWND
|
||||
hwnd = w32.CreateWindowEx(
|
||||
w.hwnd = w32.CreateWindowEx(
|
||||
exStyle,
|
||||
windowClassName,
|
||||
lo.Must(syscall.UTF16PtrFromString(options.Title)),
|
||||
w32.WS_OVERLAPPEDWINDOW|w32.WS_VISIBLE,
|
||||
w32.WS_OVERLAPPEDWINDOW,
|
||||
w32.CW_USEDEFAULT,
|
||||
w32.CW_USEDEFAULT,
|
||||
options.Width,
|
||||
@ -99,15 +103,38 @@ func (w *windowsWebviewWindow) _run() {
|
||||
w32.GetModuleHandle(""),
|
||||
nil)
|
||||
|
||||
if hwnd == 0 {
|
||||
if w.hwnd == 0 {
|
||||
panic("Unable to create window")
|
||||
}
|
||||
|
||||
if !options.Hidden {
|
||||
w32.ShowWindow(hwnd, w32.SW_SHOW)
|
||||
w32.UpdateWindow(hwnd)
|
||||
if options.DisableResize {
|
||||
w.setResizable(false)
|
||||
}
|
||||
w32.SetForegroundWindow(hwnd)
|
||||
|
||||
// Icon
|
||||
if !options.Windows.DisableIcon {
|
||||
// App icon ID is 3
|
||||
icon, err := NewIconFromResource(w32.GetModuleHandle(""), uint16(3))
|
||||
if err == nil {
|
||||
w.setIcon(icon)
|
||||
}
|
||||
} else {
|
||||
w.disableIcon()
|
||||
}
|
||||
|
||||
switch options.BackgroundType {
|
||||
case BackgroundTypeSolid:
|
||||
w.setBackgroundColour(options.BackgroundColour)
|
||||
case BackgroundTypeTransparent:
|
||||
case BackgroundTypeTranslucent:
|
||||
w.setBackdropType(options.Windows.BackdropType)
|
||||
}
|
||||
|
||||
if !options.Hidden {
|
||||
w.show()
|
||||
w.update()
|
||||
}
|
||||
w.setForeground()
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) center() {
|
||||
@ -120,19 +147,27 @@ func (w *windowsWebviewWindow) size() (int, int) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setForeground() {
|
||||
w32.SetForegroundWindow(w.hwnd)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) update() {
|
||||
w32.UpdateWindow(w.hwnd)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) width() int {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
rect := w32.GetWindowRect(w.hwnd)
|
||||
return int(rect.Right - rect.Left)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) height() int {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
rect := w32.GetWindowRect(w.hwnd)
|
||||
return int(rect.Bottom - rect.Top)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) position() (int, int) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
rect := w32.GetWindowRect(w.hwnd)
|
||||
return int(rect.Left), int(rect.Right)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) destroy() {
|
||||
@ -261,8 +296,7 @@ func (w *windowsWebviewWindow) setFullscreenButtonEnabled(enabled bool) {
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) show() {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
w32.ShowWindow(w.hwnd, w32.SW_SHOW)
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) hide() {
|
||||
@ -294,3 +328,76 @@ func (w *windowsWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData
|
||||
thisMenu.update()
|
||||
//C.windowShowMenu(w.nsWindow, thisMenu.nsMenu, C.int(data.X), C.int(data.Y))
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setStyle(b bool, style int) {
|
||||
currentStyle := int(w32.GetWindowLongPtr(w.hwnd, w32.GWL_STYLE))
|
||||
if currentStyle != 0 {
|
||||
if b {
|
||||
currentStyle |= style
|
||||
} else {
|
||||
currentStyle &^= style
|
||||
}
|
||||
w32.SetWindowLongPtr(w.hwnd, w32.GWL_STYLE, uintptr(currentStyle))
|
||||
}
|
||||
}
|
||||
func (w *windowsWebviewWindow) setExStyle(b bool, style int) {
|
||||
currentStyle := int(w32.GetWindowLongPtr(w.hwnd, w32.GWL_EXSTYLE))
|
||||
if currentStyle != 0 {
|
||||
if b {
|
||||
currentStyle |= style
|
||||
} else {
|
||||
currentStyle &^= style
|
||||
}
|
||||
w32.SetWindowLongPtr(w.hwnd, w32.GWL_EXSTYLE, uintptr(currentStyle))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setBackdropType(backdropType BackdropType) {
|
||||
if !w32.IsWindowsVersionAtLeast(10, 0, 22621) {
|
||||
var accent = w32.ACCENT_POLICY{
|
||||
AccentState: w32.ACCENT_ENABLE_BLURBEHIND,
|
||||
}
|
||||
var data w32.WINDOWCOMPOSITIONATTRIBDATA
|
||||
data.Attrib = w32.WCA_ACCENT_POLICY
|
||||
data.PvData = w32.PVOID(&accent)
|
||||
data.CbData = w32.SIZE_T(unsafe.Sizeof(accent))
|
||||
|
||||
w32.SetWindowCompositionAttribute(w.hwnd, &data)
|
||||
} else {
|
||||
backdropValue := backdropType
|
||||
// We default to None, but in win32 None = 1 and Auto = 0
|
||||
// So we check if the value given was Auto and set it to 0
|
||||
if backdropType == Auto {
|
||||
backdropValue = None
|
||||
}
|
||||
w32.DwmSetWindowAttribute(w.hwnd, w32.DwmwaSystemBackdropType, w32.LPCVOID(&backdropValue), uint32(unsafe.Sizeof(backdropValue)))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) setIcon(icon w32.HICON) {
|
||||
w32.SendMessage(w.hwnd, w32.BM_SETIMAGE, w32.IMAGE_ICON, uintptr(icon))
|
||||
}
|
||||
|
||||
func (w *windowsWebviewWindow) disableIcon() {
|
||||
|
||||
// TODO: If frameless, return
|
||||
|
||||
exStyle := w32.GetWindowLong(w.hwnd, w32.GWL_EXSTYLE)
|
||||
w32.SetWindowLong(w.hwnd, w32.GWL_EXSTYLE, uint32(exStyle|w32.WS_EX_DLGMODALFRAME))
|
||||
w32.SetWindowPos(w.hwnd, 0, 0, 0, 0, 0,
|
||||
uint(
|
||||
w32.SWP_FRAMECHANGED|
|
||||
w32.SWP_NOMOVE|
|
||||
w32.SWP_NOSIZE|
|
||||
w32.SWP_NOZORDER),
|
||||
)
|
||||
}
|
||||
|
||||
func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (w32.HICON, error) {
|
||||
var err error
|
||||
var result w32.HICON
|
||||
if result = w32.LoadIconWithResourceID(instance, resId); result == 0 {
|
||||
err = errors.New(fmt.Sprintf("Cannot load icon from resource with id %v", resId))
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user