mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-09 04:43:00 +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`?
|
- 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.
|
- 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 (
|
require (
|
||||||
github.com/go-task/task/v3 v3.20.0
|
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/google/go-cmp v0.5.9
|
||||||
github.com/jackmordaunt/icns/v2 v2.2.1
|
github.com/jackmordaunt/icns/v2 v2.2.1
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
@ -18,6 +17,7 @@ require (
|
|||||||
github.com/samber/lo v1.37.0
|
github.com/samber/lo v1.37.0
|
||||||
github.com/tc-hib/winres v0.1.6
|
github.com/tc-hib/winres v0.1.6
|
||||||
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6
|
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6
|
||||||
|
golang.org/x/sys v0.7.0
|
||||||
modernc.org/sqlite v1.21.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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
golang.org/x/net v0.7.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/sync v0.1.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/term v0.5.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // 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/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 h1:pTavuhP+AiEpKLzh5I6Lja9Ux7ypYO5QMsEPTbhYEDc=
|
||||||
github.com/go-task/task/v3 v3.20.0/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI=
|
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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
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=
|
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-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-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.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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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-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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
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
|
package w32
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pIUnknownVtbl struct {
|
func MustLoadLibrary(name string) uintptr {
|
||||||
queryInterface uintptr
|
lib, err := syscall.LoadLibrary(name)
|
||||||
addRef uintptr
|
if err != nil {
|
||||||
release uintptr
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uintptr(lib)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IUnknown struct {
|
func MustGetProcAddress(lib uintptr, name string) uintptr {
|
||||||
lpVtbl *pIUnknownVtbl
|
addr, err := syscall.GetProcAddress(syscall.Handle(lib), name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uintptr(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *IUnknown) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
|
func SUCCEEDED(hr HRESULT) bool {
|
||||||
return ComQueryInterface(u, id)
|
return hr >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *IUnknown) AddRef() int32 {
|
func FAILED(hr HRESULT) bool {
|
||||||
return ComAddRef(u)
|
return hr < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *IUnknown) Release() int32 {
|
func LOWORD(dw uint32) uint16 {
|
||||||
return ComRelease(u)
|
return uint16(dw)
|
||||||
}
|
}
|
||||||
|
|
||||||
type pIDispatchVtbl struct {
|
func HIWORD(dw uint32) uint16 {
|
||||||
queryInterface uintptr
|
return uint16(dw >> 16 & 0xffff)
|
||||||
addRef uintptr
|
|
||||||
release uintptr
|
|
||||||
getTypeInfoCount uintptr
|
|
||||||
getTypeInfo uintptr
|
|
||||||
getIDsOfNames uintptr
|
|
||||||
invoke uintptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type IDispatch struct {
|
func MAKELONG(lo, hi uint16) uint32 {
|
||||||
lpVtbl *pIDispatchVtbl
|
return uint32(uint32(lo) | ((uint32(hi)) << 16))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *IDispatch) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
|
func BoolToBOOL(value bool) BOOL {
|
||||||
return ComQueryInterface((*IUnknown)(unsafe.Pointer(d)), id)
|
if value {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *IDispatch) AddRef() int32 {
|
func UTF16PtrToString(cstr *uint16) string {
|
||||||
return ComAddRef((*IUnknown)(unsafe.Pointer(d)))
|
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 ""
|
||||||
return ComRelease((*IUnknown)(unsafe.Pointer(d)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *IDispatch) GetIDsOfName(names []string) ([]int32, HRESULT) {
|
|
||||||
return ComGetIDsOfName(d, names)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) {
|
|
||||||
return ComInvoke(d, dispid, dispatch, params...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type pIStreamVtbl struct {
|
|
||||||
qeryInterface uintptr
|
|
||||||
addRef uintptr
|
|
||||||
release uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type IStream struct {
|
|
||||||
lpVtbl *pIStreamVtbl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *IStream) QueryInterface(id *GUID) (*IDispatch, HRESULT) {
|
|
||||||
return ComQueryInterface((*IUnknown)(unsafe.Pointer(s)), id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *IStream) AddRef() int32 {
|
|
||||||
return ComAddRef((*IUnknown)(unsafe.Pointer(s)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *IStream) Release() int32 {
|
|
||||||
return ComRelease((*IUnknown)(unsafe.Pointer(s)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ComAddRef(unknown *IUnknown) int32 {
|
func ComAddRef(unknown *IUnknown) int32 {
|
||||||
ret, _, _ := syscall.Syscall(unknown.lpVtbl.addRef, 1,
|
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1,
|
||||||
uintptr(unsafe.Pointer(unknown)),
|
uintptr(unsafe.Pointer(unknown)),
|
||||||
0,
|
0,
|
||||||
0)
|
0)
|
||||||
@ -94,41 +83,45 @@ func ComAddRef(unknown *IUnknown) int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ComRelease(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)),
|
uintptr(unsafe.Pointer(unknown)),
|
||||||
0,
|
0,
|
||||||
0)
|
0)
|
||||||
return int32(ret)
|
return int32(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ComQueryInterface(unknown *IUnknown, id *GUID) (*IDispatch, HRESULT) {
|
func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
|
||||||
var disp *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(unknown)),
|
||||||
uintptr(unsafe.Pointer(id)),
|
uintptr(unsafe.Pointer(id)),
|
||||||
uintptr(unsafe.Pointer(&disp)),
|
uintptr(unsafe.Pointer(&disp)))
|
||||||
)
|
if hr != 0 {
|
||||||
return disp, HRESULT(hr)
|
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))
|
wnames := make([]*uint16, len(names))
|
||||||
dispid := make([]int32, len(names))
|
dispid := make([]int32, len(names))
|
||||||
for i := 0; i < len(names); i++ {
|
for i := 0; i < len(names); i++ {
|
||||||
wnames[i] = syscall.StringToUTF16Ptr(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(disp)),
|
||||||
uintptr(unsafe.Pointer(IID_NULL)),
|
uintptr(unsafe.Pointer(IID_NULL)),
|
||||||
uintptr(unsafe.Pointer(&wnames[0])),
|
uintptr(unsafe.Pointer(&wnames[0])),
|
||||||
uintptr(len(names)),
|
uintptr(len(names)),
|
||||||
uintptr(GetUserDefaultLCID()),
|
uintptr(GetUserDefaultLCID()),
|
||||||
uintptr(unsafe.Pointer(&dispid[0])),
|
uintptr(unsafe.Pointer(&dispid[0])))
|
||||||
)
|
if hr != 0 {
|
||||||
return dispid, HRESULT(hr)
|
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
|
var dispparams DISPPARAMS
|
||||||
|
|
||||||
if dispatch&DISPATCH_PROPERTYPUT != 0 {
|
if dispatch&DISPATCH_PROPERTYPUT != 0 {
|
||||||
@ -140,6 +133,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
|||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
vargs = make([]VARIANT, len(params))
|
vargs = make([]VARIANT, len(params))
|
||||||
for i, v := range params {
|
for i, v := range params {
|
||||||
|
//n := len(params)-i-1
|
||||||
n := len(params) - i - 1
|
n := len(params) - i - 1
|
||||||
VariantInit(&vargs[n])
|
VariantInit(&vargs[n])
|
||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
@ -200,7 +194,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
|||||||
case *VARIANT:
|
case *VARIANT:
|
||||||
vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
|
vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("w32.ComInvoke: unknown variant type")
|
panic("unknown type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
|
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 ret VARIANT
|
||||||
var excepInfo EXCEPINFO
|
var excepInfo EXCEPINFO
|
||||||
VariantInit(&ret)
|
VariantInit(&ret)
|
||||||
hr, _, _ := syscall.Syscall9(disp.lpVtbl.invoke, 8,
|
hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8,
|
||||||
uintptr(unsafe.Pointer(disp)),
|
uintptr(unsafe.Pointer(disp)),
|
||||||
uintptr(dispid),
|
uintptr(dispid),
|
||||||
uintptr(unsafe.Pointer(IID_NULL)),
|
uintptr(unsafe.Pointer(IID_NULL)),
|
||||||
@ -223,7 +217,7 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
|||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
if excepInfo.BstrDescription != nil {
|
if excepInfo.BstrDescription != nil {
|
||||||
bs := UTF16PtrToString(excepInfo.BstrDescription)
|
bs := UTF16PtrToString(excepInfo.BstrDescription)
|
||||||
return nil, errors.New(bs)
|
panic(bs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, varg := range vargs {
|
for _, varg := range vargs {
|
||||||
@ -234,18 +228,3 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
|||||||
result = &ret
|
result = &ret
|
||||||
return
|
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() {
|
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.
|
// 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")
|
m.Error("Invalid SetBackgroundColour Message: 'a' value required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
window.SetBackgroundColour(&RGBA{
|
window.SetBackgroundColour(RGBA{
|
||||||
Red: *r,
|
Red: *r,
|
||||||
Green: *g,
|
Green: *g,
|
||||||
Blue: *b,
|
Blue: *b,
|
||||||
|
@ -23,7 +23,8 @@ type WebviewWindowOptions struct {
|
|||||||
MaxHeight int
|
MaxHeight int
|
||||||
StartState WindowState
|
StartState WindowState
|
||||||
Mac MacWindow
|
Mac MacWindow
|
||||||
BackgroundColour *RGBA
|
BackgroundType BackgroundType
|
||||||
|
BackgroundColour RGBA
|
||||||
HTML string
|
HTML string
|
||||||
JS string
|
JS string
|
||||||
CSS string
|
CSS string
|
||||||
@ -43,8 +44,22 @@ var WebviewWindowDefaults = &WebviewWindowOptions{
|
|||||||
Width: 800,
|
Width: 800,
|
||||||
Height: 600,
|
Height: 600,
|
||||||
URL: "",
|
URL: "",
|
||||||
|
BackgroundColour: RGBA{
|
||||||
|
Red: 255,
|
||||||
|
Green: 255,
|
||||||
|
Blue: 255,
|
||||||
|
Alpha: 255,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type RGBA struct {
|
type RGBA struct {
|
||||||
Red, Green, Blue, Alpha uint8
|
Red, Green, Blue, Alpha uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BackgroundType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
BackgroundTypeSolid BackgroundType = iota
|
||||||
|
BackgroundTypeTransparent
|
||||||
|
BackgroundTypeTranslucent
|
||||||
|
)
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
package application
|
package application
|
||||||
|
|
||||||
|
type BackdropType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
Auto BackdropType = 0
|
||||||
|
None BackdropType = 1
|
||||||
|
Mica BackdropType = 2
|
||||||
|
Acrylic BackdropType = 3
|
||||||
|
Tabbed BackdropType = 4
|
||||||
|
)
|
||||||
|
|
||||||
type WindowsWindow struct {
|
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)
|
setMaxSize(width, height int)
|
||||||
execJS(js string)
|
execJS(js string)
|
||||||
restore()
|
restore()
|
||||||
setBackgroundColour(color *RGBA)
|
setBackgroundColour(color RGBA)
|
||||||
run()
|
run()
|
||||||
center()
|
center()
|
||||||
size() (int, int)
|
size() (int, int)
|
||||||
@ -171,7 +171,7 @@ func (w *WebviewWindow) run() {
|
|||||||
|
|
||||||
func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow {
|
func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow {
|
||||||
w.options.AlwaysOnTop = b
|
w.options.AlwaysOnTop = b
|
||||||
if w.impl == nil {
|
if w.impl != nil {
|
||||||
w.impl.setAlwaysOnTop(b)
|
w.impl.setAlwaysOnTop(b)
|
||||||
}
|
}
|
||||||
return w
|
return w
|
||||||
@ -346,7 +346,7 @@ func (w *WebviewWindow) IsFullscreen() bool {
|
|||||||
return w.impl.isFullscreen()
|
return w.impl.isFullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WebviewWindow) SetBackgroundColour(colour *RGBA) *WebviewWindow {
|
func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow {
|
||||||
w.options.BackgroundColour = colour
|
w.options.BackgroundColour = colour
|
||||||
if w.impl != nil {
|
if w.impl != nil {
|
||||||
w.impl.setBackgroundColour(colour)
|
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 {
|
if colour == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
package application
|
package application
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/w32"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"github.com/wailsapp/wails/v3/internal/w32"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var showDevTools = func(window unsafe.Pointer) {}
|
var showDevTools = func(window unsafe.Pointer) {}
|
||||||
@ -15,6 +17,7 @@ var showDevTools = func(window unsafe.Pointer) {}
|
|||||||
type windowsWebviewWindow struct {
|
type windowsWebviewWindow struct {
|
||||||
windowImpl unsafe.Pointer
|
windowImpl unsafe.Pointer
|
||||||
parent *WebviewWindow
|
parent *WebviewWindow
|
||||||
|
hwnd w32.HWND
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setTitle(title string) {
|
func (w *windowsWebviewWindow) setTitle(title string) {
|
||||||
@ -23,13 +26,18 @@ func (w *windowsWebviewWindow) setTitle(title string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setSize(width, height int) {
|
func (w *windowsWebviewWindow) setSize(width, height int) {
|
||||||
//TODO implement me
|
x, y := w.position()
|
||||||
panic("implement me")
|
w32.MoveWindow(w.hwnd, x, y, width, height, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
func (w *windowsWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
||||||
//TODO implement me
|
globalApplication.dispatchOnMainThread(func() {
|
||||||
panic("implement me")
|
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) {
|
func (w *windowsWebviewWindow) setURL(url string) {
|
||||||
@ -38,8 +46,9 @@ func (w *windowsWebviewWindow) setURL(url string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setResizable(resizable bool) {
|
func (w *windowsWebviewWindow) setResizable(resizable bool) {
|
||||||
//TODO implement me
|
globalApplication.dispatchOnMainThread(func() {
|
||||||
panic("implement me")
|
w.setStyle(resizable, w32.WS_THICKFRAME)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setMinSize(width, height int) {
|
func (w *windowsWebviewWindow) setMinSize(width, height int) {
|
||||||
@ -62,9 +71,8 @@ func (w *windowsWebviewWindow) restore() {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) setBackgroundColour(color *RGBA) {
|
func (w *windowsWebviewWindow) setBackgroundColour(color RGBA) {
|
||||||
//TODO implement me
|
w32.SetBackgroundColour(w.hwnd, color.Red, color.Green, color.Blue)
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) run() {
|
func (w *windowsWebviewWindow) run() {
|
||||||
@ -74,22 +82,18 @@ func (w *windowsWebviewWindow) run() {
|
|||||||
func (w *windowsWebviewWindow) _run() {
|
func (w *windowsWebviewWindow) _run() {
|
||||||
var exStyle uint
|
var exStyle uint
|
||||||
options := w.parent.options
|
options := w.parent.options
|
||||||
windowsOptions := options.Windows
|
|
||||||
//if windowsOptions != nil {
|
|
||||||
exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW
|
exStyle = w32.WS_EX_CONTROLPARENT | w32.WS_EX_APPWINDOW
|
||||||
// if windowsOptions.WindowIsTranslucent {
|
if options.BackgroundType != BackgroundTypeSolid {
|
||||||
// exStyle |= w32.WS_EX_NOREDIRECTIONBITMAP
|
exStyle |= w32.WS_EX_NOREDIRECTIONBITMAP
|
||||||
// }
|
}
|
||||||
//}
|
if options.AlwaysOnTop {
|
||||||
if windowsOptions.AlwaysOnTop {
|
|
||||||
exStyle |= w32.WS_EX_TOPMOST
|
exStyle |= w32.WS_EX_TOPMOST
|
||||||
}
|
}
|
||||||
var hwnd w32.HWND
|
w.hwnd = w32.CreateWindowEx(
|
||||||
hwnd = w32.CreateWindowEx(
|
|
||||||
exStyle,
|
exStyle,
|
||||||
windowClassName,
|
windowClassName,
|
||||||
lo.Must(syscall.UTF16PtrFromString(options.Title)),
|
lo.Must(syscall.UTF16PtrFromString(options.Title)),
|
||||||
w32.WS_OVERLAPPEDWINDOW|w32.WS_VISIBLE,
|
w32.WS_OVERLAPPEDWINDOW,
|
||||||
w32.CW_USEDEFAULT,
|
w32.CW_USEDEFAULT,
|
||||||
w32.CW_USEDEFAULT,
|
w32.CW_USEDEFAULT,
|
||||||
options.Width,
|
options.Width,
|
||||||
@ -99,15 +103,38 @@ func (w *windowsWebviewWindow) _run() {
|
|||||||
w32.GetModuleHandle(""),
|
w32.GetModuleHandle(""),
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
if hwnd == 0 {
|
if w.hwnd == 0 {
|
||||||
panic("Unable to create window")
|
panic("Unable to create window")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !options.Hidden {
|
if options.DisableResize {
|
||||||
w32.ShowWindow(hwnd, w32.SW_SHOW)
|
w.setResizable(false)
|
||||||
w32.UpdateWindow(hwnd)
|
|
||||||
}
|
}
|
||||||
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() {
|
func (w *windowsWebviewWindow) center() {
|
||||||
@ -120,19 +147,27 @@ func (w *windowsWebviewWindow) size() (int, int) {
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *windowsWebviewWindow) setForeground() {
|
||||||
|
w32.SetForegroundWindow(w.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *windowsWebviewWindow) update() {
|
||||||
|
w32.UpdateWindow(w.hwnd)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) width() int {
|
func (w *windowsWebviewWindow) width() int {
|
||||||
//TODO implement me
|
rect := w32.GetWindowRect(w.hwnd)
|
||||||
panic("implement me")
|
return int(rect.Right - rect.Left)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) height() int {
|
func (w *windowsWebviewWindow) height() int {
|
||||||
//TODO implement me
|
rect := w32.GetWindowRect(w.hwnd)
|
||||||
panic("implement me")
|
return int(rect.Bottom - rect.Top)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) position() (int, int) {
|
func (w *windowsWebviewWindow) position() (int, int) {
|
||||||
//TODO implement me
|
rect := w32.GetWindowRect(w.hwnd)
|
||||||
panic("implement me")
|
return int(rect.Left), int(rect.Right)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) destroy() {
|
func (w *windowsWebviewWindow) destroy() {
|
||||||
@ -261,8 +296,7 @@ func (w *windowsWebviewWindow) setFullscreenButtonEnabled(enabled bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) show() {
|
func (w *windowsWebviewWindow) show() {
|
||||||
//TODO implement me
|
w32.ShowWindow(w.hwnd, w32.SW_SHOW)
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *windowsWebviewWindow) hide() {
|
func (w *windowsWebviewWindow) hide() {
|
||||||
@ -294,3 +328,76 @@ func (w *windowsWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData
|
|||||||
thisMenu.update()
|
thisMenu.update()
|
||||||
//C.windowShowMenu(w.nsWindow, thisMenu.nsMenu, C.int(data.X), C.int(data.Y))
|
//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