237 lines
4.7 KiB
Go
237 lines
4.7 KiB
Go
// 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 (
|
|
"unsafe"
|
|
)
|
|
|
|
import (
|
|
"github.com/lxn/win"
|
|
)
|
|
|
|
const mainWindowWindowClass = `\o/ Walk_MainWindow_Class \o/`
|
|
|
|
func init() {
|
|
AppendToWalkInit(func() {
|
|
MustRegisterWindowClass(mainWindowWindowClass)
|
|
})
|
|
}
|
|
|
|
type MainWindow struct {
|
|
FormBase
|
|
windowPlacement *win.WINDOWPLACEMENT
|
|
menu *Menu
|
|
toolBar *ToolBar
|
|
statusBar *StatusBar
|
|
}
|
|
|
|
func NewMainWindow() (*MainWindow, error) {
|
|
return NewMainWindowWithName("")
|
|
}
|
|
|
|
func NewMainWindowWithName(name string) (*MainWindow, error) {
|
|
mw := new(MainWindow)
|
|
mw.SetName(name)
|
|
|
|
if err := InitWindow(
|
|
mw,
|
|
nil,
|
|
mainWindowWindowClass,
|
|
win.WS_OVERLAPPEDWINDOW,
|
|
win.WS_EX_CONTROLPARENT); err != nil {
|
|
|
|
return nil, err
|
|
}
|
|
|
|
succeeded := false
|
|
defer func() {
|
|
if !succeeded {
|
|
mw.Dispose()
|
|
}
|
|
}()
|
|
|
|
mw.SetPersistent(true)
|
|
|
|
var err error
|
|
|
|
if mw.menu, err = newMenuBar(mw); err != nil {
|
|
return nil, err
|
|
}
|
|
if !win.SetMenu(mw.hWnd, mw.menu.hMenu) {
|
|
return nil, lastError("SetMenu")
|
|
}
|
|
|
|
tb, err := NewToolBar(mw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mw.SetToolBar(tb)
|
|
|
|
if mw.statusBar, err = NewStatusBar(mw); err != nil {
|
|
return nil, err
|
|
}
|
|
mw.statusBar.parent = nil
|
|
mw.Children().Remove(mw.statusBar)
|
|
mw.statusBar.parent = mw
|
|
win.SetParent(mw.statusBar.hWnd, mw.hWnd)
|
|
mw.statusBar.visibleChangedPublisher.event.Attach(func() {
|
|
mw.SetBoundsPixels(mw.BoundsPixels())
|
|
})
|
|
|
|
succeeded = true
|
|
|
|
return mw, nil
|
|
}
|
|
|
|
func (mw *MainWindow) Menu() *Menu {
|
|
return mw.menu
|
|
}
|
|
|
|
func (mw *MainWindow) ToolBar() *ToolBar {
|
|
return mw.toolBar
|
|
}
|
|
|
|
func (mw *MainWindow) SetToolBar(tb *ToolBar) {
|
|
if mw.toolBar != nil {
|
|
win.SetParent(mw.toolBar.hWnd, 0)
|
|
}
|
|
|
|
if tb != nil {
|
|
parent := tb.parent
|
|
tb.parent = nil
|
|
parent.Children().Remove(tb)
|
|
tb.parent = mw
|
|
win.SetParent(tb.hWnd, mw.hWnd)
|
|
}
|
|
|
|
mw.toolBar = tb
|
|
}
|
|
|
|
func (mw *MainWindow) StatusBar() *StatusBar {
|
|
return mw.statusBar
|
|
}
|
|
|
|
func (mw *MainWindow) ClientBoundsPixels() Rectangle {
|
|
bounds := mw.FormBase.ClientBoundsPixels()
|
|
|
|
if mw.toolBar != nil && mw.toolBar.Actions().Len() > 0 {
|
|
tlbBounds := mw.toolBar.BoundsPixels()
|
|
|
|
bounds.Y += tlbBounds.Height
|
|
bounds.Height -= tlbBounds.Height
|
|
}
|
|
|
|
if mw.statusBar.Visible() {
|
|
bounds.Height -= mw.statusBar.HeightPixels()
|
|
}
|
|
|
|
return bounds
|
|
}
|
|
|
|
func (mw *MainWindow) SetVisible(visible bool) {
|
|
if visible {
|
|
win.DrawMenuBar(mw.hWnd)
|
|
|
|
mw.clientComposite.RequestLayout()
|
|
}
|
|
|
|
mw.FormBase.SetVisible(visible)
|
|
}
|
|
|
|
func (mw *MainWindow) applyFont(font *Font) {
|
|
mw.FormBase.applyFont(font)
|
|
|
|
if mw.toolBar != nil {
|
|
mw.toolBar.applyFont(font)
|
|
}
|
|
|
|
if mw.statusBar != nil {
|
|
mw.statusBar.applyFont(font)
|
|
}
|
|
}
|
|
|
|
func (mw *MainWindow) Fullscreen() bool {
|
|
return win.GetWindowLong(mw.hWnd, win.GWL_STYLE)&win.WS_OVERLAPPEDWINDOW == 0
|
|
}
|
|
|
|
func (mw *MainWindow) SetFullscreen(fullscreen bool) error {
|
|
if fullscreen == mw.Fullscreen() {
|
|
return nil
|
|
}
|
|
|
|
if fullscreen {
|
|
var mi win.MONITORINFO
|
|
mi.CbSize = uint32(unsafe.Sizeof(mi))
|
|
|
|
if mw.windowPlacement == nil {
|
|
mw.windowPlacement = new(win.WINDOWPLACEMENT)
|
|
}
|
|
|
|
if !win.GetWindowPlacement(mw.hWnd, mw.windowPlacement) {
|
|
return lastError("GetWindowPlacement")
|
|
}
|
|
if !win.GetMonitorInfo(win.MonitorFromWindow(
|
|
mw.hWnd, win.MONITOR_DEFAULTTOPRIMARY), &mi) {
|
|
|
|
return newError("GetMonitorInfo")
|
|
}
|
|
|
|
if err := mw.ensureStyleBits(win.WS_OVERLAPPEDWINDOW, false); err != nil {
|
|
return err
|
|
}
|
|
|
|
if r := mi.RcMonitor; !win.SetWindowPos(
|
|
mw.hWnd, win.HWND_TOP,
|
|
r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top,
|
|
win.SWP_FRAMECHANGED|win.SWP_NOOWNERZORDER) {
|
|
|
|
return lastError("SetWindowPos")
|
|
}
|
|
} else {
|
|
if err := mw.ensureStyleBits(win.WS_OVERLAPPEDWINDOW, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !win.SetWindowPlacement(mw.hWnd, mw.windowPlacement) {
|
|
return lastError("SetWindowPlacement")
|
|
}
|
|
|
|
if !win.SetWindowPos(mw.hWnd, 0, 0, 0, 0, 0, win.SWP_FRAMECHANGED|win.SWP_NOMOVE|
|
|
win.SWP_NOOWNERZORDER|win.SWP_NOSIZE|win.SWP_NOZORDER) {
|
|
|
|
return lastError("SetWindowPos")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (mw *MainWindow) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
|
|
switch msg {
|
|
case win.WM_WINDOWPOSCHANGED:
|
|
wp := (*win.WINDOWPOS)(unsafe.Pointer(lParam))
|
|
|
|
if wp.Flags&win.SWP_NOSIZE != 0 {
|
|
break
|
|
}
|
|
|
|
cb := mw.ClientBoundsPixels()
|
|
|
|
if mw.toolBar != nil {
|
|
mw.toolBar.SetBoundsPixels(Rectangle{0, 0, cb.Width, mw.toolBar.HeightPixels()})
|
|
}
|
|
|
|
mw.statusBar.SetBoundsPixels(Rectangle{0, cb.Y + cb.Height, cb.Width, mw.statusBar.HeightPixels()})
|
|
|
|
case win.WM_INITMENUPOPUP:
|
|
mw.menu.updateItemsWithImageForWindow(mw)
|
|
}
|
|
|
|
return mw.FormBase.WndProc(hwnd, msg, wParam, lParam)
|
|
}
|