feat: FFmpeg GUI desktop application
Wails v2 + Vue3 + Go project with: - Encode/Remux/Subtitle burn with hardware acceleration - Real-time progress with ffmpeg stderr parsing (\r delimiter handling) - Task queue with cancel support - Per-task log viewer with color-coded output - Custom frameless window with resize support - Dark/light theme toggle - Hardware encoder detection (NVENC/QSV/AMF)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
//go:build windows
|
||||
|
||||
package platform
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
user32 = syscall.NewLazyDLL("user32.dll")
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
setWindowLong = user32.NewProc("SetWindowLongW")
|
||||
getWindowLong = user32.NewProc("GetWindowLongW")
|
||||
setWindowPos = user32.NewProc("SetWindowPos")
|
||||
enumWindows = user32.NewProc("EnumWindows")
|
||||
getWindowThreadProcessId = user32.NewProc("GetWindowThreadProcessId")
|
||||
getCurrentProcessId = kernel32.NewProc("GetCurrentProcessId")
|
||||
)
|
||||
|
||||
const (
|
||||
GWL_STYLE = ^uintptr(15) // -16
|
||||
WS_THICKFRAME = 0x00040000
|
||||
WS_MAXIMIZEBOX = 0x00010000
|
||||
WS_MINIMIZEBOX = 0x00020000
|
||||
SWP_FRAMECHANGED = 0x0020
|
||||
SWP_NOMOVE = 0x0002
|
||||
SWP_NOSIZE = 0x0001
|
||||
SWP_NOZORDER = 0x0004
|
||||
SWP_NOACTIVATE = 0x0010
|
||||
)
|
||||
|
||||
var mainHwnd uintptr
|
||||
|
||||
// EnableResizeBorder re-adds the WS_THICKFRAME style to
|
||||
// the frameless Wails window so it can be resized from edges.
|
||||
func EnableResizeBorder() {
|
||||
pid, _, _ := getCurrentProcessId.Call()
|
||||
|
||||
// Find our main window by enumerating top-level windows
|
||||
cb := syscall.NewCallback(func(hwnd uintptr, lparam uintptr) uintptr {
|
||||
var wpid uintptr
|
||||
getWindowThreadProcessId.Call(hwnd, uintptr(unsafe.Pointer(&wpid)))
|
||||
if wpid == pid {
|
||||
// Check if it's a visible owned window (not a child/message-only)
|
||||
style, _, _ := getWindowLong.Call(hwnd, GWL_STYLE)
|
||||
if style&0x10000000 != 0 && style&0x40000000 == 0 { // WS_VISIBLE && !WS_CHILD
|
||||
mainHwnd = hwnd
|
||||
return 0 // stop enumeration
|
||||
}
|
||||
}
|
||||
return 1 // continue
|
||||
})
|
||||
enumWindows.Call(cb, 0)
|
||||
|
||||
if mainHwnd == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
style, _, _ := getWindowLong.Call(mainHwnd, GWL_STYLE)
|
||||
newStyle := style | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX
|
||||
setWindowLong.Call(mainHwnd, GWL_STYLE, newStyle)
|
||||
setWindowPos.Call(mainHwnd, 0, 0, 0, 0, 0,
|
||||
SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE)
|
||||
|
||||
// Log for debugging
|
||||
os.Stdout.WriteString("[platform] WS_THICKFRAME enabled on frameless window\n")
|
||||
}
|
||||
Reference in New Issue
Block a user