diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..5572e69ea --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +* eol=lf + +*.cmd eol=crlf +*.bat eol=crlf + +*.syso binary +*.gif binary +*.png binary +*.jpg binary +*.ico binary +*.zip binary +*.ttf binary +*.otf binary +*.woff binary +*.eot binary +*.pdf binary diff --git a/examples/globalhotkey/globalhotkey.go b/examples/globalhotkey/globalhotkey.go new file mode 100644 index 000000000..3328142b6 --- /dev/null +++ b/examples/globalhotkey/globalhotkey.go @@ -0,0 +1,50 @@ +package main + +import ( + "github.com/lxn/walk" + . "github.com/lxn/walk/declarative" +) + +func main() { + + var ( + e error + winMain *walk.MainWindow + label *walk.Label + ) + + winMain, e = walk.NewMainWindow() + if e != nil { panic(e) } + + // Define hotkey handler + winMain.Hotkey().Attach(func(hkid int) { + label.SetText("") + switch hkid { + case 1: + label.SetText("Global hotkey 1 pressed: Ctrl+Alt+X") + case 2: + label.SetText("Global hotkey 2 pressed: Alt+Shift+D") + } + }) + + // Register hotkeys globally + walk.RegisterGlobalHotKey(winMain, 1, walk.Shortcut{Modifiers: walk.ModControl | walk.ModAlt, Key: walk.KeyX}) + walk.RegisterGlobalHotKey(winMain, 2, walk.Shortcut{Modifiers: walk.ModShift | walk.ModAlt, Key: walk.KeyD}) + + MainWindow { + AssignTo: &winMain, + Size: Size{400, 120}, + Layout: VBox{}, + Children: []Widget { + Label { + Text: "Focus on another window and press Ctrl+Alt+X or Alt+Shift+D", + }, + Label { + AssignTo: &label, + Text: "-", + Font: Font{PointSize: 12}, + }, + }, + }.Run() + +} diff --git a/examples/globalhotkey/globalhotkey.manifest b/examples/globalhotkey/globalhotkey.manifest new file mode 100644 index 000000000..7936c0e72 --- /dev/null +++ b/examples/globalhotkey/globalhotkey.manifest @@ -0,0 +1,14 @@ + + + + + + + + + + + true + + + diff --git a/examples/globalhotkey/rsrc.syso b/examples/globalhotkey/rsrc.syso new file mode 100644 index 000000000..e33cf240f Binary files /dev/null and b/examples/globalhotkey/rsrc.syso differ diff --git a/globalhotkey.go b/globalhotkey.go new file mode 100644 index 000000000..281e325c0 --- /dev/null +++ b/globalhotkey.go @@ -0,0 +1,32 @@ +// Copyright 2010 The Walk Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package walk + +import ( + "github.com/lxn/win" +) + +func RegisterGlobalHotKey(owner Form, hkid int, hKey Shortcut) bool { + var ownerHWnd win.HWND + + if owner != nil { + ownerHWnd = owner.Handle() + } + + var modifiers uint + if hKey.Modifiers & ModAlt != 0 { + modifiers |= 1 + } + if hKey.Modifiers & ModControl != 0 { + modifiers |= 2 + } + if hKey.Modifiers & ModShift != 0 { + modifiers |= 4 + } + // https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms646309.aspx + return win.RegisterHotKey(ownerHWnd, hkid, modifiers, uint(hKey.Key)) +} diff --git a/hotkeyevent.go b/hotkeyevent.go new file mode 100644 index 000000000..2b5b97827 --- /dev/null +++ b/hotkeyevent.go @@ -0,0 +1,45 @@ +// Copyright 2011 The Walk Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package walk + +type HotkeyEventHandler func(hkid int) + +type HotkeyEvent struct { + handlers []HotkeyEventHandler +} + +func (e *HotkeyEvent) Attach(handler HotkeyEventHandler) int { + for i, h := range e.handlers { + if h == nil { + e.handlers[i] = handler + return i + } + } + + e.handlers = append(e.handlers, handler) + return len(e.handlers) - 1 +} + +func (e *HotkeyEvent) Detach(handle int) { + e.handlers[handle] = nil +} + +type HotkeyEventPublisher struct { + event HotkeyEvent +} + +func (p *HotkeyEventPublisher) Event() *HotkeyEvent { + return &p.event +} + +func (p *HotkeyEventPublisher) Publish(hkid int) { + for _, handler := range p.event.handlers { + if handler != nil { + handler(hkid) + } + } +} diff --git a/window.go b/window.go index f580f6630..d50c3a89b 100644 --- a/window.go +++ b/window.go @@ -161,7 +161,11 @@ type Window interface { // events for the Window. KeyUp() *KeyEvent - // MaxSize returns the maximum allowed outer size for the Window, including + // Hotkey returns a *HotkeyEvent that you can attach to for handling global + // hotkey events for the Window. + Hotkey() *HotkeyEvent + + // MaxSize returns the maximum allowed outer Size for the Window, including // decorations. // // For child windows, this is only relevant when the parent of the Window @@ -419,6 +423,7 @@ type WindowBase struct { keyDownPublisher KeyEventPublisher keyPressPublisher KeyEventPublisher keyUpPublisher KeyEventPublisher + hotkeyPublisher HotkeyEventPublisher mouseDownPublisher MouseEventPublisher mouseUpPublisher MouseEventPublisher mouseMovePublisher MouseEventPublisher @@ -2004,6 +2009,12 @@ func (wb *WindowBase) KeyUp() *KeyEvent { return wb.keyUpPublisher.Event() } +// Hotkey returns a *HotkeyEvent that you can attach to for handling global +// hotkey events for the *WindowBase. +func (wb *WindowBase) Hotkey() *HotkeyEvent { + return wb.hotkeyPublisher.Event() +} + // DropFiles returns a *DropFilesEvent that you can attach to for handling // drop file events for the *WindowBase. func (wb *WindowBase) DropFiles() *DropFilesEvent { @@ -2216,6 +2227,10 @@ func (wb *WindowBase) handleKeyUp(wParam, lParam uintptr) { wb.keyUpPublisher.Publish(Key(wParam)) } +func (wb *WindowBase) handleHotkey(wParam, lParam uintptr) { + wb.hotkeyPublisher.Publish(int(wParam)) +} + func (wb *WindowBase) backgroundEffective() (Brush, Window) { wnd := wb.window bg := wnd.Background() @@ -2460,6 +2475,9 @@ func (wb *WindowBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) case win.WM_KEYUP: wb.handleKeyUp(wParam, lParam) + case win.WM_HOTKEY: + wb.handleHotkey(wParam, lParam) + case win.WM_DROPFILES: wb.dropFilesPublisher.Publish(win.HDROP(wParam))