mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[v3 windows] Initial systray support
This commit is contained in:
@@ -137,6 +137,10 @@ type macosApp struct {
|
||||
parent *App
|
||||
}
|
||||
|
||||
func getNativeApplication() *macosApp {
|
||||
return globalApplication.impl.(*macosApp)
|
||||
}
|
||||
|
||||
func (m *macosApp) hide() {
|
||||
C.hide()
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ type windowsApp struct {
|
||||
|
||||
instance w32.HINSTANCE
|
||||
|
||||
windowMap map[w32.HWND]*windowsWebviewWindow
|
||||
windowMap map[w32.HWND]*windowsWebviewWindow
|
||||
systrayMap map[w32.HMENU]*windowsSystemTray
|
||||
|
||||
mainThreadID w32.HANDLE
|
||||
mainThreadWindowHWND w32.HWND
|
||||
@@ -33,6 +34,10 @@ type windowsApp struct {
|
||||
isDarkMode bool
|
||||
}
|
||||
|
||||
func getNativeApplication() *windowsApp {
|
||||
return globalApplication.impl.(*windowsApp)
|
||||
}
|
||||
|
||||
func (m *windowsApp) getPrimaryScreen() (*Screen, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
@@ -194,6 +199,10 @@ func (m *windowsApp) wndProc(hwnd w32.HWND, msg uint32, wParam, lParam uintptr)
|
||||
return window.WndProc(msg, wParam, lParam)
|
||||
}
|
||||
|
||||
if systray, ok := m.systrayMap[hwnd]; ok {
|
||||
return systray.wndProc(msg, wParam, lParam)
|
||||
}
|
||||
|
||||
// Dispatch the message to the appropriate window
|
||||
|
||||
return w32.DefWindowProc(hwnd, msg, wParam, lParam)
|
||||
@@ -203,6 +212,10 @@ func (m *windowsApp) registerWindow(result *windowsWebviewWindow) {
|
||||
m.windowMap[result.hwnd] = result
|
||||
}
|
||||
|
||||
func (m *windowsApp) registerSystemTray(result *windowsSystemTray) {
|
||||
m.systrayMap[result.hwnd] = result
|
||||
}
|
||||
|
||||
func (m *windowsApp) unregisterWindow(w *windowsWebviewWindow) {
|
||||
delete(m.windowMap, w.hwnd)
|
||||
|
||||
@@ -220,9 +233,10 @@ func newPlatformApp(app *App) *windowsApp {
|
||||
}
|
||||
|
||||
result := &windowsApp{
|
||||
parent: app,
|
||||
instance: w32.GetModuleHandle(""),
|
||||
windowMap: make(map[w32.HWND]*windowsWebviewWindow),
|
||||
parent: app,
|
||||
instance: w32.GetModuleHandle(""),
|
||||
windowMap: make(map[w32.HWND]*windowsWebviewWindow),
|
||||
systrayMap: make(map[w32.HWND]*windowsSystemTray),
|
||||
}
|
||||
|
||||
result.init()
|
||||
|
||||
@@ -30,6 +30,11 @@ type SystemTray struct {
|
||||
icon []byte
|
||||
iconPosition int
|
||||
|
||||
leftButtonClickHandler func()
|
||||
rightButtonClickHandler func()
|
||||
leftButtonDoubleClickHandler func()
|
||||
rightButtonDoubleClickHandler func()
|
||||
|
||||
// Platform specific implementation
|
||||
impl systemTrayImpl
|
||||
menu *Menu
|
||||
@@ -41,6 +46,7 @@ func NewSystemTray(id uint) *SystemTray {
|
||||
id: id,
|
||||
label: "",
|
||||
iconPosition: NSImageLeading,
|
||||
icon: DefaultApplicationIcon,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,24 @@
|
||||
|
||||
package application
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/events"
|
||||
"github.com/wailsapp/wails/v3/pkg/w32"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type windowsSystemTray struct {
|
||||
id uint
|
||||
icon []byte
|
||||
menu *Menu
|
||||
parent *SystemTray
|
||||
|
||||
// Platform specific implementation
|
||||
uid uint32
|
||||
hwnd w32.HWND
|
||||
appIcon w32.HICON
|
||||
lightModeIcon w32.HICON
|
||||
darkModeIcon w32.HICON
|
||||
currentIcon w32.HICON
|
||||
//menu *w32.PopupMenu
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setIconPosition(position int) {
|
||||
@@ -13,56 +27,183 @@ func (s *windowsSystemTray) setIconPosition(position int) {
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setMenu(menu *Menu) {
|
||||
s.menu = menu
|
||||
//s.menu = menu
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) run() {
|
||||
globalApplication.dispatchOnMainThread(func() {
|
||||
//if s.nsStatusItem != nil {
|
||||
// Fatal("System tray '%d' already running", s.id)
|
||||
//}
|
||||
//s.nsStatusItem = unsafe.Pointer(C.systemTrayNew())
|
||||
//if s.label != "" {
|
||||
// C.systemTraySetLabel(s.nsStatusItem, C.CString(s.label))
|
||||
//}
|
||||
//if s.icon != nil {
|
||||
// s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&s.icon[0]), C.int(len(s.icon))))
|
||||
// C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon))
|
||||
//}
|
||||
//if s.menu != nil {
|
||||
// s.menu.Update()
|
||||
// // Convert impl to macosMenu object
|
||||
// s.nsMenu = (s.menu.impl).(*macosMenu).nsMenu
|
||||
// C.systemTraySetMenu(s.nsStatusItem, s.nsMenu)
|
||||
//}
|
||||
panic("implement me")
|
||||
|
||||
NotifyIconClassName := "WailsSystray"
|
||||
_, err := w32.RegisterWindow(NotifyIconClassName, getNativeApplication().wndProc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s.hwnd = w32.CreateWindowEx(
|
||||
0,
|
||||
w32.MustStringToUTF16Ptr(NotifyIconClassName),
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
w32.HWND_MESSAGE,
|
||||
0,
|
||||
0,
|
||||
nil)
|
||||
if s.hwnd == 0 {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
|
||||
nid := w32.NOTIFYICONDATA{
|
||||
HWnd: s.hwnd,
|
||||
UID: uint32(s.parent.id),
|
||||
UFlags: w32.NIF_ICON | w32.NIF_MESSAGE,
|
||||
HIcon: s.currentIcon,
|
||||
UCallbackMessage: w32.WM_USER + uint32(s.parent.id),
|
||||
}
|
||||
nid.CbSize = uint32(unsafe.Sizeof(nid))
|
||||
|
||||
if !w32.ShellNotifyIcon(w32.NIM_ADD, &nid) {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
|
||||
nid.UVersion = w32.NOTIFYICON_VERSION
|
||||
|
||||
if !w32.ShellNotifyIcon(w32.NIM_SETVERSION, &nid) {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
|
||||
defaultIcon, err := w32.CreateHIconFromPNG(s.parent.icon)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s.lightModeIcon = defaultIcon
|
||||
s.darkModeIcon = defaultIcon
|
||||
s.uid = nid.UID
|
||||
|
||||
// TODO: Set Menu
|
||||
|
||||
// Update the icon
|
||||
s.updateIcon()
|
||||
|
||||
// Listen for dark mode changes
|
||||
globalApplication.On(events.Windows.SystemThemeChanged, func() {
|
||||
s.updateIcon()
|
||||
})
|
||||
|
||||
// Register the system tray
|
||||
getNativeApplication().registerSystemTray(s)
|
||||
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) updateIcon() {
|
||||
|
||||
var newIcon w32.HICON
|
||||
if w32.IsCurrentlyDarkMode() {
|
||||
newIcon = s.darkModeIcon
|
||||
} else {
|
||||
newIcon = s.lightModeIcon
|
||||
}
|
||||
if s.currentIcon == newIcon {
|
||||
return
|
||||
}
|
||||
|
||||
s.currentIcon = newIcon
|
||||
nid := s.newNotifyIconData()
|
||||
nid.UFlags = w32.NIF_ICON | w32.NIF_MESSAGE
|
||||
if s.currentIcon != 0 {
|
||||
nid.HIcon = s.currentIcon
|
||||
}
|
||||
|
||||
if !w32.ShellNotifyIcon(w32.NIM_MODIFY, &nid) {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) newNotifyIconData() w32.NOTIFYICONDATA {
|
||||
nid := w32.NOTIFYICONDATA{
|
||||
UID: s.uid,
|
||||
HWnd: s.hwnd,
|
||||
}
|
||||
nid.CbSize = uint32(unsafe.Sizeof(nid))
|
||||
return nid
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setIcon(icon []byte) {
|
||||
s.icon = icon
|
||||
globalApplication.dispatchOnMainThread(func() {
|
||||
//s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon))))
|
||||
//C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setTemplateIcon(icon []byte) {
|
||||
// Unsupported - do nothing
|
||||
}
|
||||
|
||||
func newSystemTrayImpl(s *SystemTray) systemTrayImpl {
|
||||
return &windowsSystemTray{
|
||||
id: s.id,
|
||||
icon: s.icon,
|
||||
menu: s.menu,
|
||||
// TODO:
|
||||
var err error
|
||||
if w32.IsCurrentlyDarkMode() {
|
||||
s.darkModeIcon, err = w32.CreateHIconFromPNG(icon)
|
||||
if err != nil {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
} else {
|
||||
s.lightModeIcon, err = w32.CreateHIconFromPNG(icon)
|
||||
if err != nil {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
}
|
||||
// Update the icon
|
||||
s.updateIcon()
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setLabel(label string) {
|
||||
// Unsupported - do nothing
|
||||
func newSystemTrayImpl(parent *SystemTray) systemTrayImpl {
|
||||
return &windowsSystemTray{
|
||||
parent: parent,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) destroy() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) wndProc(msg uint32, wParam, lParam uintptr) uintptr {
|
||||
switch msg {
|
||||
case w32.WM_USER + uint32(s.parent.id):
|
||||
switch lParam {
|
||||
case w32.WM_LBUTTONUP:
|
||||
if s.parent.leftButtonClickHandler != nil {
|
||||
s.parent.leftButtonClickHandler()
|
||||
}
|
||||
case w32.WM_RBUTTONUP:
|
||||
if s.parent.rightButtonClickHandler != nil {
|
||||
s.parent.rightButtonClickHandler()
|
||||
}
|
||||
case w32.WM_LBUTTONDBLCLK:
|
||||
if s.parent.leftButtonDoubleClickHandler != nil {
|
||||
s.parent.leftButtonDoubleClickHandler()
|
||||
}
|
||||
case w32.WM_RBUTTONDBLCLK:
|
||||
if s.parent.rightButtonDoubleClickHandler != nil {
|
||||
s.parent.rightButtonDoubleClickHandler()
|
||||
}
|
||||
default:
|
||||
println(w32.WMMessageToString(lParam))
|
||||
}
|
||||
// TODO: Menu processing
|
||||
//case w32.WM_COMMAND:
|
||||
// cmdMsgID := int(wparam & 0xffff)
|
||||
// switch cmdMsgID {
|
||||
// default:
|
||||
// p.menu.ProcessCommand(cmdMsgID)
|
||||
// }
|
||||
default:
|
||||
msg := int(wParam & 0xffff)
|
||||
println(w32.WMMessageToString(uintptr(msg)))
|
||||
}
|
||||
|
||||
return w32.DefWindowProc(s.hwnd, msg, wParam, lParam)
|
||||
}
|
||||
|
||||
// ---- Unsupported ----
|
||||
|
||||
func (s *windowsSystemTray) setLabel(_ string) {
|
||||
// Unsupported - do nothing
|
||||
}
|
||||
|
||||
func (s *windowsSystemTray) setTemplateIcon(_ []byte) {
|
||||
// Unsupported - do nothing
|
||||
}
|
||||
|
||||
@@ -115,8 +115,7 @@ func (w *windowsWebviewWindow) run() {
|
||||
}
|
||||
|
||||
// Register the window with the application
|
||||
windowsApp := globalApplication.impl.(*windowsApp)
|
||||
windowsApp.registerWindow(w)
|
||||
getNativeApplication().registerWindow(w)
|
||||
|
||||
w.setResizable(!options.DisableResize)
|
||||
|
||||
|
||||
+106
-76
@@ -1046,39 +1046,39 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
TBM_GETPOS = (WM_USER)
|
||||
TBM_GETRANGEMIN = (WM_USER + 1)
|
||||
TBM_GETRANGEMAX = (WM_USER + 2)
|
||||
TBM_GETTIC = (WM_USER + 3)
|
||||
TBM_SETTIC = (WM_USER + 4)
|
||||
TBM_SETPOS = (WM_USER + 5)
|
||||
TBM_SETRANGE = (WM_USER + 6)
|
||||
TBM_SETRANGEMIN = (WM_USER + 7)
|
||||
TBM_SETRANGEMAX = (WM_USER + 8)
|
||||
TBM_CLEARTICS = (WM_USER + 9)
|
||||
TBM_SETSEL = (WM_USER + 10)
|
||||
TBM_SETSELSTART = (WM_USER + 11)
|
||||
TBM_SETSELEND = (WM_USER + 12)
|
||||
TBM_GETPTICS = (WM_USER + 14)
|
||||
TBM_GETTICPOS = (WM_USER + 15)
|
||||
TBM_GETNUMTICS = (WM_USER + 16)
|
||||
TBM_GETSELSTART = (WM_USER + 17)
|
||||
TBM_GETSELEND = (WM_USER + 18)
|
||||
TBM_CLEARSEL = (WM_USER + 19)
|
||||
TBM_SETTICFREQ = (WM_USER + 20)
|
||||
TBM_SETPAGESIZE = (WM_USER + 21)
|
||||
TBM_GETPAGESIZE = (WM_USER + 22)
|
||||
TBM_SETLINESIZE = (WM_USER + 23)
|
||||
TBM_GETLINESIZE = (WM_USER + 24)
|
||||
TBM_GETTHUMBRECT = (WM_USER + 25)
|
||||
TBM_GETCHANNELRECT = (WM_USER + 26)
|
||||
TBM_SETTHUMBLENGTH = (WM_USER + 27)
|
||||
TBM_GETTHUMBLENGTH = (WM_USER + 28)
|
||||
TBM_SETTOOLTIPS = (WM_USER + 29)
|
||||
TBM_GETTOOLTIPS = (WM_USER + 30)
|
||||
TBM_SETTIPSIDE = (WM_USER + 31)
|
||||
TBM_SETBUDDY = (WM_USER + 32)
|
||||
TBM_GETBUDDY = (WM_USER + 33)
|
||||
TBM_GETPOS = WM_USER
|
||||
TBM_GETRANGEMIN = WM_USER + 1
|
||||
TBM_GETRANGEMAX = WM_USER + 2
|
||||
TBM_GETTIC = WM_USER + 3
|
||||
TBM_SETTIC = WM_USER + 4
|
||||
TBM_SETPOS = WM_USER + 5
|
||||
TBM_SETRANGE = WM_USER + 6
|
||||
TBM_SETRANGEMIN = WM_USER + 7
|
||||
TBM_SETRANGEMAX = WM_USER + 8
|
||||
TBM_CLEARTICS = WM_USER + 9
|
||||
TBM_SETSEL = WM_USER + 10
|
||||
TBM_SETSELSTART = WM_USER + 11
|
||||
TBM_SETSELEND = WM_USER + 12
|
||||
TBM_GETPTICS = WM_USER + 14
|
||||
TBM_GETTICPOS = WM_USER + 15
|
||||
TBM_GETNUMTICS = WM_USER + 16
|
||||
TBM_GETSELSTART = WM_USER + 17
|
||||
TBM_GETSELEND = WM_USER + 18
|
||||
TBM_CLEARSEL = WM_USER + 19
|
||||
TBM_SETTICFREQ = WM_USER + 20
|
||||
TBM_SETPAGESIZE = WM_USER + 21
|
||||
TBM_GETPAGESIZE = WM_USER + 22
|
||||
TBM_SETLINESIZE = WM_USER + 23
|
||||
TBM_GETLINESIZE = WM_USER + 24
|
||||
TBM_GETTHUMBRECT = WM_USER + 25
|
||||
TBM_GETCHANNELRECT = WM_USER + 26
|
||||
TBM_SETTHUMBLENGTH = WM_USER + 27
|
||||
TBM_GETTHUMBLENGTH = WM_USER + 28
|
||||
TBM_SETTOOLTIPS = WM_USER + 29
|
||||
TBM_GETTOOLTIPS = WM_USER + 30
|
||||
TBM_SETTIPSIDE = WM_USER + 31
|
||||
TBM_SETBUDDY = WM_USER + 32
|
||||
TBM_GETBUDDY = WM_USER + 33
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -1809,8 +1809,8 @@ const (
|
||||
RRF_RT_REG_DWORD = 0x00000010
|
||||
RRF_RT_REG_MULTI_SZ = 0x00000020
|
||||
RRF_RT_REG_QWORD = 0x00000040
|
||||
RRF_RT_DWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
|
||||
RRF_RT_QWORD = (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
|
||||
RRF_RT_DWORD = RRF_RT_REG_BINARY | RRF_RT_REG_DWORD
|
||||
RRF_RT_QWORD = RRF_RT_REG_BINARY | RRF_RT_REG_QWORD
|
||||
RRF_RT_ANY = 0x0000ffff
|
||||
RRF_NOEXPAND = 0x10000000
|
||||
RRF_ZEROONFAILURE = 0x20000000
|
||||
@@ -2047,39 +2047,39 @@ const (
|
||||
|
||||
// Tooltip messages
|
||||
const (
|
||||
TTM_ACTIVATE = (WM_USER + 1)
|
||||
TTM_SETDELAYTIME = (WM_USER + 3)
|
||||
TTM_ADDTOOL = (WM_USER + 50)
|
||||
TTM_DELTOOL = (WM_USER + 51)
|
||||
TTM_NEWTOOLRECT = (WM_USER + 52)
|
||||
TTM_RELAYEVENT = (WM_USER + 7)
|
||||
TTM_GETTOOLINFO = (WM_USER + 53)
|
||||
TTM_SETTOOLINFO = (WM_USER + 54)
|
||||
TTM_HITTEST = (WM_USER + 55)
|
||||
TTM_GETTEXT = (WM_USER + 56)
|
||||
TTM_UPDATETIPTEXT = (WM_USER + 57)
|
||||
TTM_GETTOOLCOUNT = (WM_USER + 13)
|
||||
TTM_ENUMTOOLS = (WM_USER + 58)
|
||||
TTM_GETCURRENTTOOL = (WM_USER + 59)
|
||||
TTM_WINDOWFROMPOINT = (WM_USER + 16)
|
||||
TTM_TRACKACTIVATE = (WM_USER + 17)
|
||||
TTM_TRACKPOSITION = (WM_USER + 18)
|
||||
TTM_SETTIPBKCOLOR = (WM_USER + 19)
|
||||
TTM_SETTIPTEXTCOLOR = (WM_USER + 20)
|
||||
TTM_GETDELAYTIME = (WM_USER + 21)
|
||||
TTM_GETTIPBKCOLOR = (WM_USER + 22)
|
||||
TTM_GETTIPTEXTCOLOR = (WM_USER + 23)
|
||||
TTM_SETMAXTIPWIDTH = (WM_USER + 24)
|
||||
TTM_GETMAXTIPWIDTH = (WM_USER + 25)
|
||||
TTM_SETMARGIN = (WM_USER + 26)
|
||||
TTM_GETMARGIN = (WM_USER + 27)
|
||||
TTM_POP = (WM_USER + 28)
|
||||
TTM_UPDATE = (WM_USER + 29)
|
||||
TTM_GETBUBBLESIZE = (WM_USER + 30)
|
||||
TTM_ADJUSTRECT = (WM_USER + 31)
|
||||
TTM_SETTITLE = (WM_USER + 33)
|
||||
TTM_POPUP = (WM_USER + 34)
|
||||
TTM_GETTITLE = (WM_USER + 35)
|
||||
TTM_ACTIVATE = WM_USER + 1
|
||||
TTM_SETDELAYTIME = WM_USER + 3
|
||||
TTM_ADDTOOL = WM_USER + 50
|
||||
TTM_DELTOOL = WM_USER + 51
|
||||
TTM_NEWTOOLRECT = WM_USER + 52
|
||||
TTM_RELAYEVENT = WM_USER + 7
|
||||
TTM_GETTOOLINFO = WM_USER + 53
|
||||
TTM_SETTOOLINFO = WM_USER + 54
|
||||
TTM_HITTEST = WM_USER + 55
|
||||
TTM_GETTEXT = WM_USER + 56
|
||||
TTM_UPDATETIPTEXT = WM_USER + 57
|
||||
TTM_GETTOOLCOUNT = WM_USER + 13
|
||||
TTM_ENUMTOOLS = WM_USER + 58
|
||||
TTM_GETCURRENTTOOL = WM_USER + 59
|
||||
TTM_WINDOWFROMPOINT = WM_USER + 16
|
||||
TTM_TRACKACTIVATE = WM_USER + 17
|
||||
TTM_TRACKPOSITION = WM_USER + 18
|
||||
TTM_SETTIPBKCOLOR = WM_USER + 19
|
||||
TTM_SETTIPTEXTCOLOR = WM_USER + 20
|
||||
TTM_GETDELAYTIME = WM_USER + 21
|
||||
TTM_GETTIPBKCOLOR = WM_USER + 22
|
||||
TTM_GETTIPTEXTCOLOR = WM_USER + 23
|
||||
TTM_SETMAXTIPWIDTH = WM_USER + 24
|
||||
TTM_GETMAXTIPWIDTH = WM_USER + 25
|
||||
TTM_SETMARGIN = WM_USER + 26
|
||||
TTM_GETMARGIN = WM_USER + 27
|
||||
TTM_POP = WM_USER + 28
|
||||
TTM_UPDATE = WM_USER + 29
|
||||
TTM_GETBUBBLESIZE = WM_USER + 30
|
||||
TTM_ADJUSTRECT = WM_USER + 31
|
||||
TTM_SETTITLE = WM_USER + 33
|
||||
TTM_POPUP = WM_USER + 34
|
||||
TTM_GETTITLE = WM_USER + 35
|
||||
)
|
||||
|
||||
// Tooltip icons
|
||||
@@ -2097,10 +2097,10 @@ const (
|
||||
const (
|
||||
TTN_FIRST = -520
|
||||
TTN_LAST = -549
|
||||
TTN_GETDISPINFO = (TTN_FIRST - 10)
|
||||
TTN_SHOW = (TTN_FIRST - 1)
|
||||
TTN_POP = (TTN_FIRST - 2)
|
||||
TTN_LINKCLICK = (TTN_FIRST - 3)
|
||||
TTN_GETDISPINFO = TTN_FIRST - 10
|
||||
TTN_SHOW = TTN_FIRST - 1
|
||||
TTN_POP = TTN_FIRST - 2
|
||||
TTN_LINKCLICK = TTN_FIRST - 3
|
||||
TTN_NEEDTEXT = TTN_GETDISPINFO
|
||||
)
|
||||
|
||||
@@ -2244,8 +2244,8 @@ const (
|
||||
|
||||
// WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes
|
||||
const (
|
||||
HTERROR = (-2)
|
||||
HTTRANSPARENT = (-1)
|
||||
HTERROR = -2
|
||||
HTTRANSPARENT = -1
|
||||
HTNOWHERE = 0
|
||||
HTCLIENT = 1
|
||||
HTCAPTION = 2
|
||||
@@ -2328,8 +2328,8 @@ const (
|
||||
GMEM_LOWER = GMEM_NOT_BANKED
|
||||
GMEM_VALID_FLAGS = 0x7F72
|
||||
GMEM_INVALID_HANDLE = 0x8000
|
||||
GHND = (GMEM_MOVEABLE | GMEM_ZEROINIT)
|
||||
GPTR = (GMEM_FIXED | GMEM_ZEROINIT)
|
||||
GHND = GMEM_MOVEABLE | GMEM_ZEROINIT
|
||||
GPTR = GMEM_FIXED | GMEM_ZEROINIT
|
||||
)
|
||||
|
||||
// Ternary raster operations
|
||||
@@ -2511,6 +2511,31 @@ const (
|
||||
MAX_PATH = 260
|
||||
)
|
||||
|
||||
const (
|
||||
NIM_ADD = 0x00000000
|
||||
NIM_MODIFY = 0x00000001
|
||||
NIM_DELETE = 0x00000002
|
||||
NIM_SETVERSION = 0x00000004
|
||||
|
||||
NIF_MESSAGE = 0x00000001
|
||||
NIF_ICON = 0x00000002
|
||||
NIF_TIP = 0x00000004
|
||||
NIF_STATE = 0x00000008
|
||||
NIF_INFO = 0x00000010
|
||||
|
||||
NIS_HIDDEN = 0x00000001
|
||||
|
||||
NIIF_NONE = 0x00000000
|
||||
NIIF_INFO = 0x00000001
|
||||
NIIF_WARNING = 0x00000002
|
||||
NIIF_ERROR = 0x00000003
|
||||
NIIF_USER = 0x00000004
|
||||
NIIF_NOSOUND = 0x00000010
|
||||
NIIF_LARGE_ICON = 0x00000020
|
||||
NIIF_RESPECT_QUIET_TIME = 0x00000080
|
||||
NIIF_ICON_MASK = 0x0000000F
|
||||
)
|
||||
|
||||
const (
|
||||
FOREGROUND_BLUE = 0x0001
|
||||
FOREGROUND_GREEN = 0x0002
|
||||
@@ -2675,6 +2700,11 @@ const (
|
||||
XBUTTON2 = 2
|
||||
)
|
||||
|
||||
const (
|
||||
LR_LOADFROMFILE = 0x00000010
|
||||
LR_DEFAULTSIZE = 0x00000040
|
||||
)
|
||||
|
||||
// Devmode
|
||||
const (
|
||||
DM_SPECVERSION = 0x0401
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func CreateIconFromResourceEx(presbits uintptr, dwResSize uint32, isIcon bool, version uint32, cxDesired int, cyDesired int, flags uint) (uintptr, error) {
|
||||
icon := 0
|
||||
if isIcon {
|
||||
icon = 1
|
||||
}
|
||||
r, _, err := procCreateIconFromResourceEx.Call(
|
||||
presbits,
|
||||
uintptr(dwResSize),
|
||||
uintptr(icon),
|
||||
uintptr(version),
|
||||
uintptr(cxDesired),
|
||||
uintptr(cyDesired),
|
||||
uintptr(flags),
|
||||
)
|
||||
|
||||
if r == 0 {
|
||||
return 0, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// CreateHIconFromPNG creates a HICON from a PNG file
|
||||
func CreateHIconFromPNG(pngData []byte) (HICON, error) {
|
||||
icon, err := CreateIconFromResourceEx(
|
||||
uintptr(unsafe.Pointer(&pngData[0])),
|
||||
uint32(len(pngData)),
|
||||
true,
|
||||
0x00030000,
|
||||
0,
|
||||
0,
|
||||
LR_DEFAULTSIZE)
|
||||
return HICON(icon), err
|
||||
}
|
||||
@@ -78,6 +78,8 @@ const (
|
||||
CSIDL_FLAG_NO_ALIAS = 0x1000
|
||||
CSIDL_FLAG_PER_USER_INIT = 0x8000
|
||||
CSIDL_FLAG_MASK = 0xFF00
|
||||
|
||||
NOTIFYICON_VERSION = 4
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -92,8 +94,14 @@ var (
|
||||
procShellExecute = modshell32.NewProc("ShellExecuteW")
|
||||
procExtractIcon = modshell32.NewProc("ExtractIconW")
|
||||
procGetSpecialFolderPath = modshell32.NewProc("SHGetSpecialFolderPathW")
|
||||
procShellNotifyIcon = modshell32.NewProc("Shell_NotifyIconW")
|
||||
)
|
||||
|
||||
func ShellNotifyIcon(cmd uintptr, nid *NOTIFYICONDATA) bool {
|
||||
ret, _, _ := procShellNotifyIcon.Call(cmd, uintptr(unsafe.Pointer(nid)))
|
||||
return ret == 1
|
||||
}
|
||||
|
||||
func SHBrowseForFolder(bi *BROWSEINFO) uintptr {
|
||||
ret, _, _ := procSHBrowseForFolder.Call(uintptr(unsafe.Pointer(bi)))
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ package w32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/sys/windows"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -653,6 +654,24 @@ type TRACKMOUSEEVENT struct {
|
||||
DwHoverTime uint32
|
||||
}
|
||||
|
||||
type NOTIFYICONDATA struct {
|
||||
CbSize uint32
|
||||
HWnd HWND
|
||||
UID uint32
|
||||
UFlags uint32
|
||||
UCallbackMessage uint32
|
||||
HIcon HICON
|
||||
SzTip [128]uint16
|
||||
DwState uint32
|
||||
DwStateMask uint32
|
||||
SzInfo [256]uint16
|
||||
UVersion uint32
|
||||
SzInfoTitle [64]uint16
|
||||
DwInfoFlags uint32
|
||||
GuidItem windows.GUID
|
||||
HBalloonIcon HICON
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms534067.aspx
|
||||
type GdiplusStartupInput struct {
|
||||
GdiplusVersion uint32
|
||||
|
||||
+20
-19
@@ -69,27 +69,28 @@ var (
|
||||
procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics")
|
||||
procPostThreadMessageW = moduser32.NewProc("PostThreadMessageW")
|
||||
procRegisterWindowMessageA = moduser32.NewProc("RegisterWindowMessageA")
|
||||
procCopyRect = moduser32.NewProc("CopyRect")
|
||||
procEqualRect = moduser32.NewProc("EqualRect")
|
||||
procInflateRect = moduser32.NewProc("InflateRect")
|
||||
procIntersectRect = moduser32.NewProc("IntersectRect")
|
||||
procIsRectEmpty = moduser32.NewProc("IsRectEmpty")
|
||||
procOffsetRect = moduser32.NewProc("OffsetRect")
|
||||
procPtInRect = moduser32.NewProc("PtInRect")
|
||||
procSetRect = moduser32.NewProc("SetRect")
|
||||
procSetRectEmpty = moduser32.NewProc("SetRectEmpty")
|
||||
procSubtractRect = moduser32.NewProc("SubtractRect")
|
||||
procUnionRect = moduser32.NewProc("UnionRect")
|
||||
procCreateDialogParam = moduser32.NewProc("CreateDialogParamW")
|
||||
procDialogBoxParam = moduser32.NewProc("DialogBoxParamW")
|
||||
procGetDlgItem = moduser32.NewProc("GetDlgItem")
|
||||
procDrawIcon = moduser32.NewProc("DrawIcon")
|
||||
procCreateMenu = moduser32.NewProc("CreateMenu")
|
||||
procDestroyMenu = moduser32.NewProc("DestroyMenu")
|
||||
procCreatePopupMenu = moduser32.NewProc("CreatePopupMenu")
|
||||
procCheckMenuRadioItem = moduser32.NewProc("CheckMenuRadioItem")
|
||||
procCreateIconFromResourceEx = moduser32.NewProc("CreateIconFromResourceEx")
|
||||
//procSysColorBrush = moduser32.NewProc("GetSysColorBrush")
|
||||
procCopyRect = moduser32.NewProc("CopyRect")
|
||||
procEqualRect = moduser32.NewProc("EqualRect")
|
||||
procInflateRect = moduser32.NewProc("InflateRect")
|
||||
procIntersectRect = moduser32.NewProc("IntersectRect")
|
||||
procIsRectEmpty = moduser32.NewProc("IsRectEmpty")
|
||||
procOffsetRect = moduser32.NewProc("OffsetRect")
|
||||
procPtInRect = moduser32.NewProc("PtInRect")
|
||||
procSetRect = moduser32.NewProc("SetRect")
|
||||
procSetRectEmpty = moduser32.NewProc("SetRectEmpty")
|
||||
procSubtractRect = moduser32.NewProc("SubtractRect")
|
||||
procUnionRect = moduser32.NewProc("UnionRect")
|
||||
procCreateDialogParam = moduser32.NewProc("CreateDialogParamW")
|
||||
procDialogBoxParam = moduser32.NewProc("DialogBoxParamW")
|
||||
procGetDlgItem = moduser32.NewProc("GetDlgItem")
|
||||
procDrawIcon = moduser32.NewProc("DrawIcon")
|
||||
procCreateMenu = moduser32.NewProc("CreateMenu")
|
||||
//procSetMenu = moduser32.NewProc("SetMenu")
|
||||
procDestroyMenu = moduser32.NewProc("DestroyMenu")
|
||||
procCreatePopupMenu = moduser32.NewProc("CreatePopupMenu")
|
||||
procCheckMenuRadioItem = moduser32.NewProc("CheckMenuRadioItem")
|
||||
//procDrawMenuBar = moduser32.NewProc("DrawMenuBar")
|
||||
//procInsertMenuItem = moduser32.NewProc("InsertMenuItemW") // FIXIT:
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package w32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
@@ -228,3 +229,409 @@ func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interfac
|
||||
result = &ret
|
||||
return
|
||||
}
|
||||
|
||||
func WMMessageToString(msg uintptr) string {
|
||||
// Convert windows message to string
|
||||
switch msg {
|
||||
case WM_APP:
|
||||
return "WM_APP"
|
||||
case WM_ACTIVATE:
|
||||
return "WM_ACTIVATE"
|
||||
case WM_ACTIVATEAPP:
|
||||
return "WM_ACTIVATEAPP"
|
||||
case WM_AFXFIRST:
|
||||
return "WM_AFXFIRST"
|
||||
case WM_AFXLAST:
|
||||
return "WM_AFXLAST"
|
||||
case WM_ASKCBFORMATNAME:
|
||||
return "WM_ASKCBFORMATNAME"
|
||||
case WM_CANCELJOURNAL:
|
||||
return "WM_CANCELJOURNAL"
|
||||
case WM_CANCELMODE:
|
||||
return "WM_CANCELMODE"
|
||||
case WM_CAPTURECHANGED:
|
||||
return "WM_CAPTURECHANGED"
|
||||
case WM_CHANGECBCHAIN:
|
||||
return "WM_CHANGECBCHAIN"
|
||||
case WM_CHAR:
|
||||
return "WM_CHAR"
|
||||
case WM_CHARTOITEM:
|
||||
return "WM_CHARTOITEM"
|
||||
case WM_CHILDACTIVATE:
|
||||
return "WM_CHILDACTIVATE"
|
||||
case WM_CLEAR:
|
||||
return "WM_CLEAR"
|
||||
case WM_CLOSE:
|
||||
return "WM_CLOSE"
|
||||
case WM_COMMAND:
|
||||
return "WM_COMMAND"
|
||||
case WM_COMMNOTIFY /* OBSOLETE */ :
|
||||
return "WM_COMMNOTIFY"
|
||||
case WM_COMPACTING:
|
||||
return "WM_COMPACTING"
|
||||
case WM_COMPAREITEM:
|
||||
return "WM_COMPAREITEM"
|
||||
case WM_CONTEXTMENU:
|
||||
return "WM_CONTEXTMENU"
|
||||
case WM_COPY:
|
||||
return "WM_COPY"
|
||||
case WM_COPYDATA:
|
||||
return "WM_COPYDATA"
|
||||
case WM_CREATE:
|
||||
return "WM_CREATE"
|
||||
case WM_CTLCOLORBTN:
|
||||
return "WM_CTLCOLORBTN"
|
||||
case WM_CTLCOLORDLG:
|
||||
return "WM_CTLCOLORDLG"
|
||||
case WM_CTLCOLOREDIT:
|
||||
return "WM_CTLCOLOREDIT"
|
||||
case WM_CTLCOLORLISTBOX:
|
||||
return "WM_CTLCOLORLISTBOX"
|
||||
case WM_CTLCOLORMSGBOX:
|
||||
return "WM_CTLCOLORMSGBOX"
|
||||
case WM_CTLCOLORSCROLLBAR:
|
||||
return "WM_CTLCOLORSCROLLBAR"
|
||||
case WM_CTLCOLORSTATIC:
|
||||
return "WM_CTLCOLORSTATIC"
|
||||
case WM_CUT:
|
||||
return "WM_CUT"
|
||||
case WM_DEADCHAR:
|
||||
return "WM_DEADCHAR"
|
||||
case WM_DELETEITEM:
|
||||
return "WM_DELETEITEM"
|
||||
case WM_DESTROY:
|
||||
return "WM_DESTROY"
|
||||
case WM_DESTROYCLIPBOARD:
|
||||
return "WM_DESTROYCLIPBOARD"
|
||||
case WM_DEVICECHANGE:
|
||||
return "WM_DEVICECHANGE"
|
||||
case WM_DEVMODECHANGE:
|
||||
return "WM_DEVMODECHANGE"
|
||||
case WM_DISPLAYCHANGE:
|
||||
return "WM_DISPLAYCHANGE"
|
||||
case WM_DRAWCLIPBOARD:
|
||||
return "WM_DRAWCLIPBOARD"
|
||||
case WM_DRAWITEM:
|
||||
return "WM_DRAWITEM"
|
||||
case WM_DROPFILES:
|
||||
return "WM_DROPFILES"
|
||||
case WM_ENABLE:
|
||||
return "WM_ENABLE"
|
||||
case WM_ENDSESSION:
|
||||
return "WM_ENDSESSION"
|
||||
case WM_ENTERIDLE:
|
||||
return "WM_ENTERIDLE"
|
||||
case WM_ENTERMENULOOP:
|
||||
return "WM_ENTERMENULOOP"
|
||||
case WM_ENTERSIZEMOVE:
|
||||
return "WM_ENTERSIZEMOVE"
|
||||
case WM_ERASEBKGND:
|
||||
return "WM_ERASEBKGND"
|
||||
case WM_EXITMENULOOP:
|
||||
return "WM_EXITMENULOOP"
|
||||
case WM_EXITSIZEMOVE:
|
||||
return "WM_EXITSIZEMOVE"
|
||||
case WM_FONTCHANGE:
|
||||
return "WM_FONTCHANGE"
|
||||
case WM_GETDLGCODE:
|
||||
return "WM_GETDLGCODE"
|
||||
case WM_GETFONT:
|
||||
return "WM_GETFONT"
|
||||
case WM_GETHOTKEY:
|
||||
return "WM_GETHOTKEY"
|
||||
case WM_GETICON:
|
||||
return "WM_GETICON"
|
||||
case WM_GETMINMAXINFO:
|
||||
return "WM_GETMINMAXINFO"
|
||||
case WM_GETTEXT:
|
||||
return "WM_GETTEXT"
|
||||
case WM_GETTEXTLENGTH:
|
||||
return "WM_GETTEXTLENGTH"
|
||||
case WM_HANDHELDFIRST:
|
||||
return "WM_HANDHELDFIRST"
|
||||
case WM_HANDHELDLAST:
|
||||
return "WM_HANDHELDLAST"
|
||||
case WM_HELP:
|
||||
return "WM_HELP"
|
||||
case WM_HOTKEY:
|
||||
return "WM_HOTKEY"
|
||||
case WM_HSCROLL:
|
||||
return "WM_HSCROLL"
|
||||
case WM_HSCROLLCLIPBOARD:
|
||||
return "WM_HSCROLLCLIPBOARD"
|
||||
case WM_ICONERASEBKGND:
|
||||
return "WM_ICONERASEBKGND"
|
||||
case WM_INITDIALOG:
|
||||
return "WM_INITDIALOG"
|
||||
case WM_INITMENU:
|
||||
return "WM_INITMENU"
|
||||
case WM_INITMENUPOPUP:
|
||||
return "WM_INITMENUPOPUP"
|
||||
case WM_INPUT:
|
||||
return "WM_INPUT"
|
||||
case WM_INPUTLANGCHANGE:
|
||||
return "WM_INPUTLANGCHANGE"
|
||||
case WM_INPUTLANGCHANGEREQUEST:
|
||||
return "WM_INPUTLANGCHANGEREQUEST"
|
||||
case WM_KEYDOWN:
|
||||
return "WM_KEYDOWN"
|
||||
case WM_KEYUP:
|
||||
return "WM_KEYUP"
|
||||
case WM_KILLFOCUS:
|
||||
return "WM_KILLFOCUS"
|
||||
case WM_MDIACTIVATE:
|
||||
return "WM_MDIACTIVATE"
|
||||
case WM_MDICASCADE:
|
||||
return "WM_MDICASCADE"
|
||||
case WM_MDICREATE:
|
||||
return "WM_MDICREATE"
|
||||
case WM_MDIDESTROY:
|
||||
return "WM_MDIDESTROY"
|
||||
case WM_MDIGETACTIVE:
|
||||
return "WM_MDIGETACTIVE"
|
||||
case WM_MDIICONARRANGE:
|
||||
return "WM_MDIICONARRANGE"
|
||||
case WM_MDIMAXIMIZE:
|
||||
return "WM_MDIMAXIMIZE"
|
||||
case WM_MDINEXT:
|
||||
return "WM_MDINEXT"
|
||||
case WM_MDIREFRESHMENU:
|
||||
return "WM_MDIREFRESHMENU"
|
||||
case WM_MDIRESTORE:
|
||||
return "WM_MDIRESTORE"
|
||||
case WM_MDISETMENU:
|
||||
return "WM_MDISETMENU"
|
||||
case WM_MDITILE:
|
||||
return "WM_MDITILE"
|
||||
case WM_MEASUREITEM:
|
||||
return "WM_MEASUREITEM"
|
||||
case WM_GETOBJECT:
|
||||
return "WM_GETOBJECT"
|
||||
case WM_CHANGEUISTATE:
|
||||
return "WM_CHANGEUISTATE"
|
||||
case WM_UPDATEUISTATE:
|
||||
return "WM_UPDATEUISTATE"
|
||||
case WM_QUERYUISTATE:
|
||||
return "WM_QUERYUISTATE"
|
||||
case WM_UNINITMENUPOPUP:
|
||||
return "WM_UNINITMENUPOPUP"
|
||||
case WM_MENURBUTTONUP:
|
||||
return "WM_MENURBUTTONUP"
|
||||
case WM_MENUCOMMAND:
|
||||
return "WM_MENUCOMMAND"
|
||||
case WM_MENUGETOBJECT:
|
||||
return "WM_MENUGETOBJECT"
|
||||
case WM_MENUDRAG:
|
||||
return "WM_MENUDRAG"
|
||||
case WM_APPCOMMAND:
|
||||
return "WM_APPCOMMAND"
|
||||
case WM_MENUCHAR:
|
||||
return "WM_MENUCHAR"
|
||||
case WM_MENUSELECT:
|
||||
return "WM_MENUSELECT"
|
||||
case WM_MOVE:
|
||||
return "WM_MOVE"
|
||||
case WM_MOVING:
|
||||
return "WM_MOVING"
|
||||
case WM_NCACTIVATE:
|
||||
return "WM_NCACTIVATE"
|
||||
case WM_NCCALCSIZE:
|
||||
return "WM_NCCALCSIZE"
|
||||
case WM_NCCREATE:
|
||||
return "WM_NCCREATE"
|
||||
case WM_NCDESTROY:
|
||||
return "WM_NCDESTROY"
|
||||
case WM_NCHITTEST:
|
||||
return "WM_NCHITTEST"
|
||||
case WM_NCLBUTTONDBLCLK:
|
||||
return "WM_NCLBUTTONDBLCLK"
|
||||
case WM_NCLBUTTONDOWN:
|
||||
return "WM_NCLBUTTONDOWN"
|
||||
case WM_NCLBUTTONUP:
|
||||
return "WM_NCLBUTTONUP"
|
||||
case WM_NCMBUTTONDBLCLK:
|
||||
return "WM_NCMBUTTONDBLCLK"
|
||||
case WM_NCMBUTTONDOWN:
|
||||
return "WM_NCMBUTTONDOWN"
|
||||
case WM_NCMBUTTONUP:
|
||||
return "WM_NCMBUTTONUP"
|
||||
case WM_NCXBUTTONDOWN:
|
||||
return "WM_NCXBUTTONDOWN"
|
||||
case WM_NCXBUTTONUP:
|
||||
return "WM_NCXBUTTONUP"
|
||||
case WM_NCXBUTTONDBLCLK:
|
||||
return "WM_NCXBUTTONDBLCLK"
|
||||
case WM_NCMOUSEHOVER:
|
||||
return "WM_NCMOUSEHOVER"
|
||||
case WM_NCMOUSELEAVE:
|
||||
return "WM_NCMOUSELEAVE"
|
||||
case WM_NCMOUSEMOVE:
|
||||
return "WM_NCMOUSEMOVE"
|
||||
case WM_NCPAINT:
|
||||
return "WM_NCPAINT"
|
||||
case WM_NCRBUTTONDBLCLK:
|
||||
return "WM_NCRBUTTONDBLCLK"
|
||||
case WM_NCRBUTTONDOWN:
|
||||
return "WM_NCRBUTTONDOWN"
|
||||
case WM_NCRBUTTONUP:
|
||||
return "WM_NCRBUTTONUP"
|
||||
case WM_NEXTDLGCTL:
|
||||
return "WM_NEXTDLGCTL"
|
||||
case WM_NEXTMENU:
|
||||
return "WM_NEXTMENU"
|
||||
case WM_NOTIFY:
|
||||
return "WM_NOTIFY"
|
||||
case WM_NOTIFYFORMAT:
|
||||
return "WM_NOTIFYFORMAT"
|
||||
case WM_NULL:
|
||||
return "WM_NULL"
|
||||
case WM_PAINT:
|
||||
return "WM_PAINT"
|
||||
case WM_PAINTCLIPBOARD:
|
||||
return "WM_PAINTCLIPBOARD"
|
||||
case WM_PAINTICON:
|
||||
return "WM_PAINTICON"
|
||||
case WM_PALETTECHANGED:
|
||||
return "WM_PALETTECHANGED"
|
||||
case WM_PALETTEISCHANGING:
|
||||
return "WM_PALETTEISCHANGING"
|
||||
case WM_PARENTNOTIFY:
|
||||
return "WM_PARENTNOTIFY"
|
||||
case WM_PASTE:
|
||||
return "WM_PASTE"
|
||||
case WM_PENWINFIRST:
|
||||
return "WM_PENWINFIRST"
|
||||
case WM_PENWINLAST:
|
||||
return "WM_PENWINLAST"
|
||||
case WM_POWER:
|
||||
return "WM_POWER"
|
||||
case WM_PRINT:
|
||||
return "WM_PRINT"
|
||||
case WM_PRINTCLIENT:
|
||||
return "WM_PRINTCLIENT"
|
||||
case WM_QUERYDRAGICON:
|
||||
return "WM_QUERYDRAGICON"
|
||||
case WM_QUERYENDSESSION:
|
||||
return "WM_QUERYENDSESSION"
|
||||
case WM_QUERYNEWPALETTE:
|
||||
return "WM_QUERYNEWPALETTE"
|
||||
case WM_QUERYOPEN:
|
||||
return "WM_QUERYOPEN"
|
||||
case WM_QUEUESYNC:
|
||||
return "WM_QUEUESYNC"
|
||||
case WM_QUIT:
|
||||
return "WM_QUIT"
|
||||
case WM_RENDERALLFORMATS:
|
||||
return "WM_RENDERALLFORMATS"
|
||||
case WM_RENDERFORMAT:
|
||||
return "WM_RENDERFORMAT"
|
||||
case WM_SETCURSOR:
|
||||
return "WM_SETCURSOR"
|
||||
case WM_SETFOCUS:
|
||||
return "WM_SETFOCUS"
|
||||
case WM_SETFONT:
|
||||
return "WM_SETFONT"
|
||||
case WM_SETHOTKEY:
|
||||
return "WM_SETHOTKEY"
|
||||
case WM_SETICON:
|
||||
return "WM_SETICON"
|
||||
case WM_SETREDRAW:
|
||||
return "WM_SETREDRAW"
|
||||
case WM_SETTEXT:
|
||||
return "WM_SETTEXT"
|
||||
case WM_SETTINGCHANGE:
|
||||
return "WM_SETTINGCHANGE"
|
||||
case WM_SHOWWINDOW:
|
||||
return "WM_SHOWWINDOW"
|
||||
case WM_SIZE:
|
||||
return "WM_SIZE"
|
||||
case WM_SIZECLIPBOARD:
|
||||
return "WM_SIZECLIPBOARD"
|
||||
case WM_SIZING:
|
||||
return "WM_SIZING"
|
||||
case WM_SPOOLERSTATUS:
|
||||
return "WM_SPOOLERSTATUS"
|
||||
case WM_STYLECHANGED:
|
||||
return "WM_STYLECHANGED"
|
||||
case WM_STYLECHANGING:
|
||||
return "WM_STYLECHANGING"
|
||||
case WM_SYSCHAR:
|
||||
return "WM_SYSCHAR"
|
||||
case WM_SYSCOLORCHANGE:
|
||||
return "WM_SYSCOLORCHANGE"
|
||||
case WM_SYSCOMMAND:
|
||||
return "WM_SYSCOMMAND"
|
||||
case WM_SYSDEADCHAR:
|
||||
return "WM_SYSDEADCHAR"
|
||||
case WM_SYSKEYDOWN:
|
||||
return "WM_SYSKEYDOWN"
|
||||
case WM_SYSKEYUP:
|
||||
return "WM_SYSKEYUP"
|
||||
case WM_TCARD:
|
||||
return "WM_TCARD"
|
||||
case WM_THEMECHANGED:
|
||||
return "WM_THEMECHANGED"
|
||||
case WM_TIMECHANGE:
|
||||
return "WM_TIMECHANGE"
|
||||
case WM_TIMER:
|
||||
return "WM_TIMER"
|
||||
case WM_UNDO:
|
||||
return "WM_UNDO"
|
||||
case WM_USER:
|
||||
return "WM_USER"
|
||||
case WM_USERCHANGED:
|
||||
return "WM_USERCHANGED"
|
||||
case WM_VKEYTOITEM:
|
||||
return "WM_VKEYTOITEM"
|
||||
case WM_VSCROLL:
|
||||
return "WM_VSCROLL"
|
||||
case WM_VSCROLLCLIPBOARD:
|
||||
return "WM_VSCROLLCLIPBOARD"
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
return "WM_WINDOWPOSCHANGED"
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
return "WM_WINDOWPOSCHANGING"
|
||||
case WM_KEYLAST:
|
||||
return "WM_KEYLAST"
|
||||
case WM_SYNCPAINT:
|
||||
return "WM_SYNCPAINT"
|
||||
case WM_MOUSEACTIVATE:
|
||||
return "WM_MOUSEACTIVATE"
|
||||
case WM_MOUSEMOVE:
|
||||
return "WM_MOUSEMOVE"
|
||||
case WM_LBUTTONDOWN:
|
||||
return "WM_LBUTTONDOWN"
|
||||
case WM_LBUTTONUP:
|
||||
return "WM_LBUTTONUP"
|
||||
case WM_LBUTTONDBLCLK:
|
||||
return "WM_LBUTTONDBLCLK"
|
||||
case WM_RBUTTONDOWN:
|
||||
return "WM_RBUTTONDOWN"
|
||||
case WM_RBUTTONUP:
|
||||
return "WM_RBUTTONUP"
|
||||
case WM_RBUTTONDBLCLK:
|
||||
return "WM_RBUTTONDBLCLK"
|
||||
case WM_MBUTTONDOWN:
|
||||
return "WM_MBUTTONDOWN"
|
||||
case WM_MBUTTONUP:
|
||||
return "WM_MBUTTONUP"
|
||||
case WM_MBUTTONDBLCLK:
|
||||
return "WM_MBUTTONDBLCLK"
|
||||
case WM_MOUSEWHEEL:
|
||||
return "WM_MOUSEWHEEL"
|
||||
case WM_XBUTTONDOWN:
|
||||
return "WM_XBUTTONDOWN"
|
||||
case WM_XBUTTONUP:
|
||||
return "WM_XBUTTONUP"
|
||||
case WM_MOUSELAST:
|
||||
return "WM_MOUSELAST"
|
||||
case WM_MOUSEHOVER:
|
||||
return "WM_MOUSEHOVER"
|
||||
case WM_MOUSELEAVE:
|
||||
return "WM_MOUSELEAVE"
|
||||
case WM_CLIPBOARDUPDATE:
|
||||
return "WM_CLIPBOARDUPDATE"
|
||||
default:
|
||||
return fmt.Sprintf("0x%08x", msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//go:build windows
|
||||
|
||||
package w32
|
||||
|
||||
import (
|
||||
@@ -6,6 +7,7 @@ import (
|
||||
"github.com/samber/lo"
|
||||
"log"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -162,3 +164,50 @@ func GetMonitorInfoForWindow(hwnd HWND) *MONITORINFO {
|
||||
GetMonitorInfo(currentMonitor, &info)
|
||||
return &info
|
||||
}
|
||||
|
||||
type WindowProc func(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr
|
||||
|
||||
var windowClasses = make(map[string]HINSTANCE)
|
||||
var windowClassesLock sync.Mutex
|
||||
|
||||
func getWindowClass(name string) (HINSTANCE, bool) {
|
||||
windowClassesLock.Lock()
|
||||
defer windowClassesLock.Unlock()
|
||||
result, exists := windowClasses[name]
|
||||
return result, exists
|
||||
}
|
||||
|
||||
func setWindowClass(name string, instance HINSTANCE) {
|
||||
windowClassesLock.Lock()
|
||||
defer windowClassesLock.Unlock()
|
||||
windowClasses[name] = instance
|
||||
}
|
||||
|
||||
func RegisterWindow(name string, proc WindowProc) (HINSTANCE, error) {
|
||||
classInstance, exists := getWindowClass(name)
|
||||
if exists {
|
||||
return classInstance, nil
|
||||
}
|
||||
applicationInstance := GetModuleHandle("")
|
||||
if applicationInstance == 0 {
|
||||
return 0, fmt.Errorf("get module handle failed")
|
||||
}
|
||||
|
||||
var wc WNDCLASSEX
|
||||
wc.Size = uint32(unsafe.Sizeof(wc))
|
||||
wc.WndProc = syscall.NewCallback(proc)
|
||||
wc.Instance = applicationInstance
|
||||
wc.Icon = LoadIconWithResourceID(0, uint16(IDI_APPLICATION))
|
||||
wc.Cursor = LoadCursorWithResourceID(0, uint16(IDC_ARROW))
|
||||
wc.Background = COLOR_BTNFACE + 1
|
||||
wc.ClassName = MustStringToUTF16Ptr(name)
|
||||
|
||||
atom := RegisterClassEx(&wc)
|
||||
if atom == 0 {
|
||||
panic(syscall.GetLastError())
|
||||
}
|
||||
|
||||
setWindowClass(name, applicationInstance)
|
||||
|
||||
return applicationInstance, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user