windowcompact_windows.go 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. //go:build windows
  2. // ============================================================================
  3. // windowcompact_windows.go — 拖动手柄窗口尺寸切换(Windows 实现)
  4. //
  5. // Wails 无边框窗口仍带 WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX |
  6. // WS_MAXIMIZEBOX | WS_BORDER | WS_DLGFRAME 样式位,DWM 对它们强制最小宽度
  7. // (实测约 136px,剥离边框后仍有约 46px),WM_GETMINMAXINFO 的
  8. // PtMinTrackSize 无法覆盖该下限。因此进入收拢状态时临时剥离这些样式位
  9. // (SWP_FRAMECHANGED 使其生效),还原时恢复原样式。
  10. // ============================================================================
  11. package main
  12. import (
  13. "unsafe"
  14. "github.com/wailsapp/wails/v3/pkg/application"
  15. )
  16. const (
  17. gwlStyle = -16 // GWL_STYLE
  18. // 触发 DWM 最小宽度强制的样式位
  19. compactStyleMask = 0x00040000 | // WS_THICKFRAME
  20. 0x00080000 | // WS_SYSMENU
  21. 0x00020000 | // WS_MINIMIZEBOX
  22. 0x00010000 | // WS_MAXIMIZEBOX
  23. 0x00800000 | // WS_BORDER
  24. 0x00400000 // WS_DLGFRAME
  25. swpNoMove = 0x0002
  26. swpNoSize = 0x0001
  27. swpNoZOrder2 = 0x0004
  28. swpNoActivate2 = 0x0010
  29. swpFrameChanged = 0x0020
  30. )
  31. var (
  32. procGetWindowLongW = user32.NewProc("GetWindowLongW")
  33. procSetWindowLongW = user32.NewProc("SetWindowLongW")
  34. )
  35. // 收拢时保存的原始窗口样式(还原用)
  36. var compactSavedStyle int32
  37. func compactWindowHwnd(win *application.WebviewWindow) uintptr {
  38. if win == nil {
  39. return 0
  40. }
  41. return uintptr(unsafe.Pointer(win.NativeWindow()))
  42. }
  43. // compactEnterCompact 进入收拢状态:剥离 DWM 强制最小宽度的样式位后缩小窗口。
  44. func compactEnterCompact(win *application.WebviewWindow, width, height int) {
  45. if win.IsMaximised() {
  46. win.UnMaximise() // 最大化状态下 SetSize 不生效,先还原
  47. }
  48. hwnd := compactWindowHwnd(win)
  49. if hwnd != 0 {
  50. // 保存并剥离样式位,SWP_FRAMECHANGED 使样式变更立即生效
  51. styleIdx := int32(gwlStyle)
  52. style, _, _ := procGetWindowLongW.Call(hwnd, uintptr(styleIdx))
  53. compactSavedStyle = int32(style)
  54. newStyle := int32(style) &^ compactStyleMask
  55. procSetWindowLongW.Call(hwnd, uintptr(styleIdx), uintptr(newStyle))
  56. procSetWindowPos.Call(hwnd, 0, 0, 0, 0, 0,
  57. swpNoMove|swpNoSize|swpNoZOrder2|swpNoActivate2|swpFrameChanged)
  58. }
  59. win.SetMinSize(width, height) // 解锁 Wails 侧最小尺寸约束
  60. win.SetSize(width, height)
  61. }
  62. // compactExitCompact 退出收拢状态:恢复原样式位并还原窗口尺寸。
  63. func compactExitCompact(win *application.WebviewWindow, width, height int) {
  64. hwnd := compactWindowHwnd(win)
  65. if hwnd != 0 && compactSavedStyle != 0 {
  66. styleIdx := int32(gwlStyle)
  67. procSetWindowLongW.Call(hwnd, uintptr(styleIdx), uintptr(compactSavedStyle))
  68. procSetWindowPos.Call(hwnd, 0, 0, 0, 0, 0,
  69. swpNoMove|swpNoSize|swpNoZOrder2|swpNoActivate2|swpFrameChanged)
  70. compactSavedStyle = 0
  71. }
  72. win.SetSize(width, height)
  73. win.SetMinSize(0, 0)
  74. }