diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6463613 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.bat +go-taskbar.exe diff --git a/FindWindow.go b/FindWindow.go new file mode 100644 index 0000000..018132d --- /dev/null +++ b/FindWindow.go @@ -0,0 +1,15 @@ +package main + +import ( + "syscall" + "unsafe" +) + +func FindWindow(lpClassName, lpWindowName *uint16) HWND { + ret, _, _ := syscall.Syscall(findWindow.Addr(), 2, + uintptr(unsafe.Pointer(lpClassName)), + uintptr(unsafe.Pointer(lpWindowName)), + 0) + + return HWND(ret) +} diff --git a/MessageBox.go b/MessageBox.go new file mode 100644 index 0000000..fba1806 --- /dev/null +++ b/MessageBox.go @@ -0,0 +1,35 @@ +package main + +import ( + "log" + "strings" + "syscall" + "unsafe" +) + +const ( + MB_YESNO = 0x00000004 + MB_ICONQUESTION = 0x00000020 +) + +func MsgBox(title, message string, style uintptr) int { + titleInt, err := syscall.UTF16PtrFromString(strings.ReplaceAll(title, "\x00", "␀")) + if err != nil { + log.Println(err) + } + + messageInt, err := syscall.UTF16PtrFromString(strings.ReplaceAll(message, "\x00", "␀")) + if err != nil { + log.Println(err) + } + + ret, _, _ := syscall.Syscall6(messageBox.Addr(), 4, + uintptr(0), + uintptr(unsafe.Pointer(messageInt)), + uintptr(unsafe.Pointer(titleInt)), + uintptr(style), + 0, + 0) + + return int(int32(ret)) +} diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..4b221c8 --- /dev/null +++ b/Readme.md @@ -0,0 +1,3 @@ +# go-taskbar + +I am trying to build something like "[TaskbarX](https://github.com/ChrisAnd1998/TaskbarX)" or "[TaskbarDock](https://github.com/vhanla/TaskbarDock)" with less functions but in Go without dependencys. diff --git a/SetWindowCompositionAttribute.go b/SetWindowCompositionAttribute.go new file mode 100644 index 0000000..eabda8d --- /dev/null +++ b/SetWindowCompositionAttribute.go @@ -0,0 +1,72 @@ +package main + +import ( + "syscall" + "unsafe" +) + +const ( + ACCENT_DISABLED = iota // [1] Default value. Background is black. + ACCENT_ENABLE_GRADIENT = iota // [2] Background is GradientColor, alpha channel ignored. + ACCENT_ENABLE_TRANSPARENTGRADIENT = iota // [3] Background is GradientColor. + ACCENT_ENABLE_BLURBEHIND = iota // [4] Background is GradientColor, with blur effect. + ACCENT_ENABLE_ACRYLICBLURBEHIND = iota // [5] Background is GradientColor, with acrylic blur effect. + ACCENT_INVALID_STATE = iota // [6] Unknown. + ACCENT_ENABLE_TRANSPARENT = iota // [7] Unknown. Seems to draw background fully transparent. +) + +type ACCENT_POLICY struct { + ACCENT_STATE int + AccentFlags uint32 + GradientColor uint32 + AnimationId uint32 +} + +const ( + WCA_UNDEFINED = iota + WCA_NCRENDERING_ENABLED = iota + WCA_NCRENDERING_POLICY = iota + WCA_TRANSITIONS_FORCEDISABLED = iota + WCA_ALLOW_NCPAINT = iota + WCA_CAPTION_BUTTON_BOUNDS = iota + WCA_NONCLIENT_RTL_LAYOUT = iota + WCA_FORCE_ICONIC_REPRESENTATION = iota + WCA_EXTENDED_FRAME_BOUNDS = iota + WCA_HAS_ICONIC_BITMAP = iota + WCA_THEME_ATTRIBUTES = iota + WCA_NCRENDERING_EXILED = iota + WCA_NCADORNMENTINFO = iota + WCA_EXCLUDED_FROM_LIVEPREVIEW = iota + WCA_VIDEO_OVERLAY_ACTIVE = iota + WCA_FORCE_ACTIVEWINDOW_APPEARANCE = iota + WCA_DISALLOW_PEEK = iota + WCA_CLOAK = iota + WCA_CLOAKED = iota + WCA_ACCENT_POLICY = iota + WCA_FREEZE_REPRESENTATION = iota + WCA_EVER_UNCLOAKED = iota + WCA_VISUAL_OWNER = iota + WCA_LAST = iota +) + +type WINCOMPATTRDATA struct { + nAttribute int + pData *ACCENT_POLICY + ulDataSize uint32 +} + +func SetWindowCompositionAttribute(hwnd HWND, accent_state int, dword uint32) bool { + var accent = ACCENT_POLICY{} + accent.ACCENT_STATE = accent_state + data := WINCOMPATTRDATA{ + nAttribute: WCA_ACCENT_POLICY, + pData: &accent, + } + data.ulDataSize = uint32(unsafe.Sizeof(data)) + + ret, _, _ := syscall.Syscall(setWindowCompositionAttribute.Addr(), 2, + uintptr(hwnd), + uintptr(unsafe.Pointer(&data)), + 0) + return ret != 0 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..389eade --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/spddl/go-taskbar + +go 1.16 + +require golang.org/x/sys v0.0.0-20210603125802-9665404d3644 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0e6439a --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/init.go b/init.go new file mode 100644 index 0000000..567f6ca --- /dev/null +++ b/init.go @@ -0,0 +1,49 @@ +package main + +import ( + "flag" + "log" + "os" + + "golang.org/x/sys/windows" +) + +type HANDLE uintptr +type HWND HANDLE + +const ( + zeroHandle = HWND(0) +) + +var ( + // Library + libuser32 *windows.LazyDLL + setWindowCompositionAttribute *windows.LazyProc + messageBox *windows.LazyProc + findWindow *windows.LazyProc + + FLAG_ACCENT int +) + +func init() { + log.SetFlags(log.Lmicroseconds | log.Lshortfile) // https://ispycode.com/GO/Logging/Setting-output-flags + + // Library + libuser32 = windows.NewLazySystemDLL("user32.dll") + setWindowCompositionAttribute = libuser32.NewProc("SetWindowCompositionAttribute") + messageBox = libuser32.NewProc("MessageBoxW") + findWindow = libuser32.NewProc("FindWindowW") + + flag.IntVar(&FLAG_ACCENT, "accent", 0, "help message for flagname") + flag.Parse() + + if len(os.Args) < 2 { + result := MsgBox("Transparent Taskbar", "Change Taskbar style to Transparent?", MB_ICONQUESTION|MB_YESNO) + switch result { + case 6: + FLAG_ACCENT = ACCENT_ENABLE_TRANSPARENT + default: + FLAG_ACCENT = ACCENT_ENABLE_GRADIENT + } + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..3748897 --- /dev/null +++ b/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "log" + "syscall" +) + +func main() { + szShellTray, err := syscall.UTF16PtrFromString("Shell_TrayWnd") + if err != nil { + log.Println(err) + } + firstTaskbarHWND := FindWindow(szShellTray, nil) // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindoww + + szShellSecondaryTray, err := syscall.UTF16PtrFromString("Shell_SecondaryTrayWnd") + if err != nil { + log.Println(err) + } + secondTaskbarHWND := FindWindow(szShellSecondaryTray, nil) + + if firstTaskbarHWND != zeroHandle { + result := SetWindowCompositionAttribute(firstTaskbarHWND, FLAG_ACCENT, 1) + if !result { + log.Println("could not change the taskbar") + } + } + if secondTaskbarHWND != zeroHandle { + result := SetWindowCompositionAttribute(secondTaskbarHWND, FLAG_ACCENT, 1) + if !result { + log.Println("could not change the second taskbar") + } + } +}