mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 15:19:12 +08:00

* fix: fix go test errors * Add flags to mac test * Run on all branches * Update PR workflow Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
236 lines
6.9 KiB
Go
236 lines
6.9 KiB
Go
//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
|
|
}
|