Implemented the new MsgBox()/MsgBoxError() behavior on Windows.
This commit is contained in:
parent
7cb8fc1e32
commit
641d11c6fe
14
dialog.go
14
dialog.go
|
@ -19,7 +19,7 @@ var dialogWindow *Window
|
|||
// Whether or not resizing Windows will still be allowed is implementation-defined; if the implementation does allow it, resizes will still work properly.
|
||||
// Whether or not the message box stays above all other W+indows in the program is also implementation-defined.
|
||||
func MsgBox(primaryText string, secondaryText string) {
|
||||
dialogWindow.msgBox(parent, primaryText, secondaryText)
|
||||
<-dialogWindow.msgBox(primaryText, secondaryText)
|
||||
}
|
||||
|
||||
// MsgBox behaves like the package-scope MsgBox function, except the message box is modal to w only.
|
||||
|
@ -28,24 +28,26 @@ func MsgBox(primaryText string, secondaryText string) {
|
|||
// Whether w can be resized while the message box is displayed is implementation-defined, but will work properly if allowed.
|
||||
// If w has not yet been created, MsgBox() panics.
|
||||
// If w has not been shown yet or is currently hidden, what MsgBox does is implementation-defined.
|
||||
func (w *Window) MsgBox(primaryText string, secondaryText string) {
|
||||
//
|
||||
// On return, done will be a channel that is pulsed when the message box is dismissed.
|
||||
func (w *Window) MsgBox(primaryText string, secondaryText string) (done chan struct{}) {
|
||||
if !w.created {
|
||||
panic("parent window passed to Window.MsgBox() before it was created")
|
||||
}
|
||||
w.msgBox(primaryText, secondaryText)
|
||||
return w.msgBox(primaryText, secondaryText)
|
||||
}
|
||||
|
||||
// MsgBoxError displays a message box to the user with just an OK button and an icon indicating an error.
|
||||
// Otherwise, it behaves like MsgBox.
|
||||
func MsgBoxError(primaryText string, secondaryText string) {
|
||||
dialogWindow.msgBoxError(parent, primaryText, secondaryText)
|
||||
<-dialogWindow.msgBoxError(primaryText, secondaryText)
|
||||
}
|
||||
|
||||
// MsgBoxError displays a message box to the user with just an OK button and an icon indicating an error.
|
||||
// Otherwise, it behaves like Window.MsgBox.
|
||||
func (w *Window) MsgBoxError(primaryText string, secondaryText string) {
|
||||
func (w *Window) MsgBoxError(primaryText string, secondaryText string) (done chan struct{}) {
|
||||
if !w.created {
|
||||
panic("parent window passed to MsgBoxError() before it was created")
|
||||
}
|
||||
w.msgBoxError(primaryText, secondaryText)
|
||||
return w.msgBoxError(primaryText, secondaryText)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ var (
|
|||
_messageBox = user32.NewProc("MessageBoxW")
|
||||
)
|
||||
|
||||
func _msgBox(parent *Window, primarytext string, secondarytext string, uType uint32) (result int) {
|
||||
func _msgBox(parent *Window, primarytext string, secondarytext string, uType uint32) (result chan int) {
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa511267.aspx says "Use task dialogs whenever appropriate to achieve a consistent look and layout. Task dialogs require Windows Vista® or later, so they aren't suitable for earlier versions of Windows. If you must use a message box, separate the main instruction from the supplemental instruction with two line breaks."
|
||||
text := primarytext
|
||||
if secondarytext != "" {
|
||||
|
@ -19,15 +19,17 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin
|
|||
}
|
||||
ptext := toUTF16(text)
|
||||
ptitle := toUTF16(os.Args[0])
|
||||
ret := make(chan uiret)
|
||||
defer close(ret)
|
||||
parenthwnd := _HWND(_NULL)
|
||||
if parent != nil {
|
||||
if parent != dialogWindow {
|
||||
parenthwnd = parent.sysData.hwnd
|
||||
uType |= _MB_APPLMODAL // only for this window
|
||||
} else {
|
||||
uType |= _MB_TASKMODAL // make modal to every window in the program (they're all windows of the uitask, which is a single thread)
|
||||
}
|
||||
retchan := make(chan int)
|
||||
go func() {
|
||||
ret := make(chan uiret)
|
||||
defer close(ret)
|
||||
uitask <- &uimsg{
|
||||
call: _messageBox,
|
||||
p: []uintptr{
|
||||
|
@ -42,13 +44,25 @@ func _msgBox(parent *Window, primarytext string, secondarytext string, uType uin
|
|||
if r.ret == 0 { // failure
|
||||
panic(fmt.Sprintf("error displaying message box to user: %v\nstyle: 0x%08X\ntitle: %q\ntext:\n%s", r.err, uType, os.Args[0], text))
|
||||
}
|
||||
return int(r.ret)
|
||||
retchan <- int(r.ret)
|
||||
}()
|
||||
return retchan
|
||||
}
|
||||
|
||||
func msgBox(parent *Window, primarytext string, secondarytext string) {
|
||||
_msgBox(parent, primarytext, secondarytext, _MB_OK)
|
||||
func (w *Window) msgBox(primarytext string, secondarytext string) (done chan struct{}) {
|
||||
done = make(chan struct{})
|
||||
go func() {
|
||||
<-_msgBox(w, primarytext, secondarytext, _MB_OK)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
||||
func msgBoxError(parent *Window, primarytext string, secondarytext string) {
|
||||
_msgBox(parent, primarytext, secondarytext, _MB_OK | _MB_ICONERROR)
|
||||
func (w *Window) msgBoxError(primarytext string, secondarytext string) (done chan struct{}) {
|
||||
done = make(chan struct{})
|
||||
go func() {
|
||||
<-_msgBox(w, primarytext, secondarytext, _MB_OK | _MB_ICONERROR)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
|
38
test/main.go
38
test/main.go
|
@ -49,7 +49,7 @@ var macCrashTest = flag.Bool("maccrash", false, "attempt crash on Mac OS X on de
|
|||
func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
|
||||
x := func(what string ) {
|
||||
if j := recover(); j == nil {
|
||||
MsgBoxError(nil, "test", fmt.Sprintf("%s: no panic", what))
|
||||
MsgBoxError("test", fmt.Sprintf("%s: no panic", what))
|
||||
panic("invalid test fail")
|
||||
} else {
|
||||
println("got", j.(error).Error())
|
||||
|
@ -143,7 +143,7 @@ func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
|
|||
defer x("Area.SetSize() " + q.msg); a.SetSize(q.x, q.y); panic(nil)
|
||||
}()
|
||||
}
|
||||
MsgBox(nil, "test", "all working as intended")
|
||||
MsgBox("test", "all working as intended")
|
||||
}
|
||||
|
||||
var invalidBefore = flag.Bool("invalid", false, "run invalid test before opening window")
|
||||
|
@ -226,7 +226,7 @@ func areaTest() {
|
|||
if err != nil { println(err); continue }
|
||||
a.SetSize(width, height)
|
||||
case <-modaltest.Clicked:
|
||||
MsgBox(nil, "Modal Test", "")
|
||||
MsgBox("Modal Test", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +260,8 @@ func areaboundsTest() {
|
|||
<-w.Closing
|
||||
}
|
||||
|
||||
var dialogTest = flag.Bool("dialog", false, "add Window.MsgBox() channel test window")
|
||||
|
||||
func myMain() {
|
||||
if *doArea {
|
||||
areaTest()
|
||||
|
@ -284,6 +286,9 @@ func myMain() {
|
|||
cb2 := NewCombobox("You can't edit me!", "No you can't!", "No you won't!")
|
||||
e := NewLineEdit("Enter text here too")
|
||||
l := NewLabel("This is a label")
|
||||
resetl := func() {
|
||||
l.SetText("This is a label")
|
||||
}
|
||||
b3 := NewButton("List Info")
|
||||
s3 := NewHorizontalStack(l, b3)
|
||||
s3.SetStretchy(0)
|
||||
|
@ -330,6 +335,17 @@ func myMain() {
|
|||
|
||||
ticker := time.Tick(time.Second)
|
||||
|
||||
dialog_bMsgBox := NewButton("MsgBox()")
|
||||
dialog_bMsgBoxError := NewButton("MsgBoxError()")
|
||||
dialog_win := NewWindow("Dialogs", 200, 200)
|
||||
if *dialogTest {
|
||||
dialog_win.Open(NewVerticalStack(
|
||||
dialog_bMsgBox,
|
||||
dialog_bMsgBoxError))
|
||||
}
|
||||
|
||||
var dialog_sret chan struct{} = nil
|
||||
|
||||
mainloop:
|
||||
for {
|
||||
select {
|
||||
|
@ -368,7 +384,7 @@ _=curtime
|
|||
if c.Checked() {
|
||||
f = MsgBoxError
|
||||
}
|
||||
f(nil, "List Info",
|
||||
f("List Info",
|
||||
fmt.Sprintf("cb1: %d %q (len %d)\ncb2: %d %q (len %d)\nlb1: %d %q (len %d)\nlb2: %d %q (len %d)",
|
||||
cb1.SelectedIndex(), cb1.Selection(), cb1.Len(),
|
||||
cb2.SelectedIndex(), cb2.Selection(), cb2.Len(),
|
||||
|
@ -393,8 +409,18 @@ _=curtime
|
|||
case <-invalidButton.Clicked:
|
||||
invalidTest(cb1, lb1, nil, nil)
|
||||
case <-bmsg.Clicked:
|
||||
MsgBox(nil, "Title Only, no parent", "")
|
||||
MsgBox(w, "Title and Text", "parent")
|
||||
MsgBox("Title Only, no parent", "")
|
||||
MsgBox("Title and Text", "parent")
|
||||
// dialogs
|
||||
case <-dialog_bMsgBox.Clicked:
|
||||
dialog_sret = dialog_win.MsgBox("Message Box", "Dismiss")
|
||||
l.SetText("DIALOG")
|
||||
case <-dialog_bMsgBoxError.Clicked:
|
||||
dialog_sret = dialog_win.MsgBoxError("Message Box", "Dismiss")
|
||||
l.SetText("DIALOG")
|
||||
case <-dialog_sret:
|
||||
dialog_sret = nil
|
||||
resetl()
|
||||
}
|
||||
}
|
||||
w.Hide()
|
||||
|
|
Loading…
Reference in New Issue